1.Flutter 中的线性布局(Android 中 LinearLayout)
在 Flutter 中,可以使用 Row (横向)和 Column (纵向) widget 来实现同样的效果:
void main() {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('1'),
Text('2'),
Text('3'),
Text('4'),
],
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('1'),
Text('2'),
Text('3'),
Text('4'),
],
);
}
}
2.Flutter 中的相对布局(Android 中 RelativeLayout)
在 Flutter 中,可以通过 Column、Row 和 Stack 的组合来实现相对布局的效果。
3.使用 widget 定义布局属性
在 Flutter 中,布局主要由专门设计用于提供布局的小部件定义,并结合控件 widget 及样式属性。
如,行和列 widgets 控制一个数组中的条目,并且将它们分别垂直和水平对齐。Container widget 控制一个布局的样式和属性,Center widget 负责将它的子 widget 居中。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
Container(
color: Colors.red,
width: 100.0,
height: 100.0,
),
Container(
color: Colors.blue,
width: 100.0,
height: 100.0,
),
Container(
color: Colors.green,
width: 100.0,
height: 100.0,
),
],
));
}
}
4.分层布局
在 Flutter 中,使用 Stack widget 控制子 widget 在一层,子 widgets 可以完全或部分覆盖下面 widgets。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
alignment: const Alignment(0.6, 0.6),
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(
"https://avatars3.githubusercontent.com/u/14101776?v=4"
),
),
Container(
decoration: BoxDecoration(
color: Colors.black45
),
child: Text('Hello'),
)
],
);
}
}
5.设置布局样式
通过 Padding、Center、Column、Row 来设置布局样式,这些都是 widget。
class MyApp extends StatelessWidget {
var textStyle = TextStyle(
fontSize: 20.0, color: Colors.cyan, fontWeight: FontWeight.w600);
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Text(
'你好',
style: textStyle,
),
Padding(
padding: EdgeInsets.all(20.0),
child: Icon(Icons.lightbulb_outline, size: 48, color: Colors.red),
),
],
),
);
}
}
6.Flutter 中的滑动组件(Android 中 ScrollView)
使用 ListView :
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children:[
Center(
child: Text('1'),
),
Center(
child: Text('1'),
),
Center(
child: Text('1'),
),
Center(
child: Text('1'),
),
],
);
}
}
7.Flutter中的列表组件(Android 中 ListView)
如下:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView(
children: _getListData(),
),
);
}
_getListData() {
List<Widget> widgets = [];
for (int i = 0; i < 50; i++) {
widgets.add(Padding(padding: EdgeInsets.all(10.0),child: Center(child: Text("第 $i 个")),));
}
return widgets;
}
}
8.点击列表中的 item
添加手势即可,用 GestureDetector,如下:
void main() {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView(
children: _getListData(),
),
);
}
_getListData() {
List<Widget> widgets = [];
for (int i = 0; i < 50; i++) {
widgets.add(
GestureDetector(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Center(child: Text("第 $i 个")),
),
onTap: () {
print('点击 $i');
},
onDoubleTap: () {
print('双击 $i');
}),
);
}
return widgets;
}
}
9.动态更新 ListView
如果想通过 setState() 方法更新 widget 列表,会发现并没有更新,因为调用 setState() 方法,Flutter 会检查 widget 树什么地方改变了,得到 ListView 时,它用 == 判断,发现两个 ListView 是相同的,所以不会更新。
更新 ListView 的方法是,创建一个 ListView.builder 接受两个主要参数:列表的初始长度和一个 ItemBuilder 方法。
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Widget> widgets = [];
@override
void initState() {
// TODO: implement initState
super.initState();
for (int i = 0; i < 50; i++) {
widgets.add(getRow(i));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView.builder(
itemCount: widgets.length,
itemBuilder: (BuildContext context,int position){
return getRow(position);
},
),
);
}
getRow(int i) {
return GestureDetector(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Center(child: Text("第 $i 个")),
),
onTap: () {
setState((){
widgets.add(getRow(widgets.length + 1));
});
});
}
}