Flutter筆記 - 布局類組件
布局類組件

Row水平方向排列
- textDirection 水平方向子組件布局順序。
- mainAxisSize 占用空間,默認MainAxisSize.MAX
- mainAxisAligment 對齊方式
MainAxisAligment.start 初始方向對齊
MainAxisAligment.ltr 左對齊
MainAxisAligment.rtl 右對齊
MainAxisAligment.end 和MainAxisAligment.start相反
MainAxisAligment.center 居中對齊 - verticalDirection:處置對齊方向,默認從上到下VerticalDirection.down
- crossAxisAligment 子組件縱軸對齊方式
crossAxisAligment.start 頂部對齊
crossAxisAligment.start 底部對齊
children:子組件數組
彈性布局Flex
沿著水平或者垂直方向排列。
flex 比例
Spacer為Expandes的包裝類
import 'package:flutter/material.dart';
class FlexLayoutRouter extends StatelessWidget {
const FlexLayoutRouter({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(
flex: 2,
child: Container(
height: 30,
color: Colors.green,
)),
Expanded(
flex: 1,
child: Container(
height: 30,
color: Colors.green,
))
],
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: SizedBox(
height: 100,
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
height: 30,
color: Colors.grey,
)),
const Spacer(
flex: 2,
),
Expanded(
flex: 1,
child: Container(
height: 30,
color: Colors.black,
)),
],
),
),
)
],
);
}
}
流式布局
spaceing:主軸子Widget間距。
runSpacing:縱軸間距。
runAligment:縱軸對齊方式。
例子:
import 'package:flutter/material.dart';
class WrapRoute extends StatelessWidget{
const WrapRoute({super.key});
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Wrap(
spacing: 8.0,
runSpacing: 4.0,
alignment: WrapAlignment.center,
children: const <Widget>[
Chip(label: Text("A"),
avatar: CircleAvatar(backgroundColor: Colors.blue,child: Text("A")),
),
Chip(label: Text("B"),
avatar: CircleAvatar(backgroundColor: Colors.blue,child: Text("B")),
),
Chip(label: Text("C"),
avatar: CircleAvatar(backgroundColor: Colors.blue,child: Text("C")),
),
Chip(label: Text("D"),
avatar: CircleAvatar(backgroundColor: Colors.blue,child: Text("D")),
),
],
)
],
);
}
}
GestureDetector
一次完整的手勢過程是指用戶手指按下到抬起的整個過程,期間,用戶按下手指后可能會移動,也可能不會移動。GestureDetector對于拖動和滑動事件是沒有區分的,他們本質上是一樣的。GestureDetector會將要監聽的組件的原點(左上角)作為本次手勢的原點,當用戶在監聽的組件上按下手指時,手勢識別就會開始。
- DragDownDetails.globalPosition:當用戶按下時,此屬性為用戶按下的位置相對于屏幕(而非父組件)原點(左上角)的偏移。
- DragUpdateDetails.delta:當用戶在屏幕上滑動時,會觸發多次Update事件,delta指一次Update事件的滑動的偏移量。
- DragEndDetails.velocity:該屬性代表用戶抬起手指時的滑動速度(包含x、y兩個軸的),示例中并沒有處理手指抬起時的速度,常見的效果是根據用戶抬起手指時的速度做一個減速動畫。
import 'package:flutter/material.dart';
class DragWidget extends StatefulWidget {
const DragWidget({super.key});
@override
DragState createState() => DragState();
}
class DragState extends State<DragWidget>
with SingleTickerProviderStateMixin<DragWidget> {
double _top = 0.0;
double _left = 0.0;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
top: _top,
left: _left,
child: GestureDetector(
child: const CircleAvatar(child: Text("A")),
// 手指按下,全局位置
onPanDown: (DragDownDetails e) {
print("按下:${e.globalPosition}");
},
// 滑動過程中
onPanUpdate: (DragUpdateDetails e) {
setState(() {
// dx 為x軸偏移量
_left = _left + e.delta.dx;
_top = _top + e.delta.dy;
});
},
// 滑動結束的時候
onPanEnd: (DragEndDetails e) {
print("速度:${e.velocity}");
},
))
],
);
}
}
onScaleUpdate 縮放監聽
import 'package:flutter/material.dart';
class ZoomWidget extends StatefulWidget {
const ZoomWidget({super.key});
@override
ZoomWidgetState createState() => ZoomWidgetState();
}
class ZoomWidgetState extends State<ZoomWidget> {
double _width = 200.0; //通過修改圖片寬度來達到縮放效果
@override
Widget build(BuildContext context) {
return Center(
child: GestureDetector(
child: Image.asset("./graphics/ic_launcher.png"),
onScaleUpdate: (ScaleUpdateDetails details) {
setState(() {
_width = 200 * details.scale.clamp(.8, 10.0);
});
},
),
);
}
}
GestureRecognizer
GestureRecognizer的作用就是通過 Listener來將原始指針事件轉換為語義手勢,GestureDetector直接可以接收一個子widget。
例子:變顏色的TextSpan
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class ChangeColorWidget extends StatefulWidget {
const ChangeColorWidget({super.key});
@override
ChangeColorWidgetState createState() => ChangeColorWidgetState();
}
class ChangeColorWidgetState extends State<ChangeColorWidget> {
// 手勢識別器
TapGestureRecognizer tapGestureRecognizer = TapGestureRecognizer();
//手勢開關
bool toggle = false;
@override
Widget build(BuildContext context) {
return Center(
child: Text.rich(TextSpan(
text: "點我變顏色",
style: TextStyle(
fontSize: 30,
color: toggle ? Colors.green : Colors.red,
),
recognizer: tapGestureRecognizer
..onTap = () {
setState(() {
toggle = !toggle;
});
},
)),
);
}
}

浙公網安備 33010602011771號