简单列举总结一下常用的布局widget。
Flutter有丰富的layout组件库。其中有一些是常用库。
下面的widget分为两类:标准组件和来自Material Components的特殊组件。
只有Material App能够使用Material Components的组件。
1、基本组件(无法设置margin,只能设置padding)
Text, 设置文本
Image,设置图片,网络图片
Column 纵向布局,可设置居中(横向,纵向等)
Row 横向布局,可设置居中(横向,纵向等)
2、标准组件 - Standard widgets
- Container
给一个组件添加 padding, margins, 边界(borders), 背景颜色或其它装饰(decorations)。 - GridView
将多个widget放在一个可滑动的表格中。 - ListView
将多个widget放在一个可滑动的列表中。 - Stack
在一个widget上面盖上另一个widget。
3、Material Components - Card
将一些相近的信息装进一个有圆角和阴影的盒子里。 - ListTile
一个Row中装载最多3行文字;可选则在前面或尾部添加图标。
在Flutter中构建布局(Flutter中文网)
https://flutterchina.club/tutorials/layout/
基本组件
widget基本组件重点:
MainAxisAlignment(主轴)就是与当前控件方向一致的轴
CrossAxisAlignment(交叉轴)就是与当前控件方向垂直的轴
Text, Image无法嵌套子组件;
Column,Row中可嵌套子组件
左边图片代码
import 'package:flutter/material.dart';
//1、圆角
class ButtonWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('button and text'),
),
body: Container(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(horizontal: 8.0),
child: RaisedButton(
onPressed: () {},
color: Colors.yellow,
disabledTextColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
elevation: 20.0,
//下方阴影
splashColor: Colors.green,
//没设置highlightColor时才生效,点击按钮时逐步颜色变化
highlightColor: Colors.red,
highlightElevation: 1.0,
child: Text("Raised Button"),
),
),
FlatButton(
onPressed: () {},
colorBrightness: Brightness.dark,
color: Colors.deepPurpleAccent,
splashColor: Colors.green,
highlightColor: Colors.red,
child: Text("FlatButton Button"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(
left: Radius.circular(20.0),
right: Radius.circular(1.0))),
),
],
),
//http://docs.flutter.kim/material/RaisedButton-class.html
MaterialButton(
minWidth: 250.0,
onPressed: () {},
colorBrightness: Brightness.dark,
color: Colors.deepPurpleAccent,
elevation: 20.0,
splashColor: Colors.green,
//highlightColor: Colors.red,
highlightElevation: 1.0,
child: Text("MaterialButton Button"),
),
OutlineButton(
onPressed: () {},
borderSide: BorderSide(width: 5.0, color: Colors.deepPurpleAccent),
color: Colors.deepPurpleAccent,
highlightedBorderColor: Colors.purple,
splashColor: Colors.green,
//highlightColor: Colors.red,
child: Text("OutlineButton Button"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20.0), bottom: Radius.circular(10.0))),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,//MainAxisAlignment(主轴)就是与当前控件方向一致的轴,而CrossAxisAlignment(交叉轴)就是与当前控件方向垂直的轴
children: <Widget>[
FloatingActionButton(
backgroundColor: Colors.orange,
child: Icon(
Icons.mic,
size: 30.0,
color: Colors.white,
),
onPressed: () {}),
IconButton(
color: Colors.purple,
splashColor: Colors.yellow,
// highlightColor: Colors.red,
icon: Icon(
Icons.build,
size: 40.0,
),
onPressed: () {}),
],
),
Text(
"我的flutter demo,一行展示,啊啊啊啊啊啊啊啊啊啊啊啊",
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: Colors.red,
fontSize: 20.0,
decoration: TextDecoration.underline,
//横线,可设置顶部,底部
decorationColor: Colors.green,
decorationStyle: TextDecorationStyle.solid //底部线样式
),
),
new Text(
'inherit: 为 false 的时候不显示',
style: new TextStyle(
inherit: true,
),
),
new Text(
'color/fontSize: 字体颜色,字号等',
style: new TextStyle(
color: Color.fromARGB(255, 150, 150, 150),
fontSize: 22.0,
),
),
new Text(
'fontWeight: 字重',
style: new TextStyle(fontWeight: FontWeight.w700),
),
new Text(
'fontStyle: FontStyle.italic 斜体',
style: new TextStyle(
fontStyle: FontStyle.italic,
),
),
new Text(
'letterSpacing: 字符间距',
style: new TextStyle(
letterSpacing: 10.0,
// wordSpacing: 15.0
),
),
new Text(
'wordSpacing: 字或单词间距',
style: new TextStyle(
// letterSpacing: 10.0,
wordSpacing: 15.0),
),
new Text(
'textBaseline:这一行的值为TextBaseline.alphabetic',
style: new TextStyle(textBaseline: TextBaseline.alphabetic),
),
new Text(
'textBaseline:这一行的值为TextBaseline.ideographic',
style: new TextStyle(textBaseline: TextBaseline.ideographic),
),
new Text('height: 用在Text控件上的时候,会乘以fontSize做为行高,所以这个值不能设置过大',
style: new TextStyle(
height: 1.0,
)),
new Text('decoration: TextDecoration.overline 上划线',
style: new TextStyle(
decoration: TextDecoration.overline,
decorationStyle: TextDecorationStyle.wavy)),
new Text('decoration: TextDecoration.lineThrough 删除线',
style: new TextStyle(
decoration: TextDecoration.lineThrough,
decorationStyle: TextDecorationStyle.dashed)),
new Text('decoration: TextDecoration.underline 下划线',
style: new TextStyle(
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.dotted)),
],
)),
);
}
}
右边图片代代码
import 'package:flutter/material.dart';
class ContainerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(title: Text("container"),),
body: Row(
children: <Widget>[
Column(children: <Widget>[
Container(
margin: EdgeInsets.all(10.0),
height: 60.0,
width: 100.0,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20.0),
),
color: Colors.green,
),
child: Text('Hello'),
),
Container(
height: 80,
width: 80,
margin: EdgeInsets.all(5.0),
decoration: FlutterLogoDecoration(),
),
Container(
height: 80,
width: 100,
margin: EdgeInsets.all(5.0),
decoration: new ShapeDecoration(
color: Colors.white,
shadows: <BoxShadow>[
BoxShadow(color: Colors.black, blurRadius: 15.0)
],
shape: new Border.all(
color: Colors.red,
width: 8.0,
),
),
child: Center(
child:
const Text('Hello Flutter', textAlign: TextAlign.center)),
),
Container(
height: 80,
width: 80,
margin: EdgeInsets.all(5.0),
decoration: new BoxDecoration(
color: Colors.yellow,
borderRadius: new BorderRadius.circular(55.0),
border: new Border.all(
width: 5.0,
color: Colors.red,
),
),
child: Center(
child:
const Text('Hello Flutter', textAlign: TextAlign.center)),
),
Container(
height: 80.0,
width: 80.0,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(80.0),
color: Colors.green,
),
child: Text('Hello'),
)
],
),
Column(children: <Widget>[
Container(
margin: EdgeInsets.all(20.0),
constraints: BoxConstraints(
maxWidth: 200.0,
minWidth: 100.0
),
width: 50.0,
alignment: Alignment.topCenter,
child: Image.network('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559212316292&di=a64f6fa62a8d67b6b770c10c9265db5f&imgtype=0&src=http%3A%2F%2Fimg2015.zdface.com%2F20161129%2F16af77dc3bcb7bf81c18506eaa412a9b.jpg'),
),
Container(
margin: EdgeInsets.all(10.0),
height: 80.0,
width: 100.0,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(color: Colors.red, blurRadius: 12.0 ),
BoxShadow(color: Colors.green, blurRadius: 40.0)
]
),
child: Center(child: Text("阴影"),),
),
Container(
height: 100.0,
width: 100.0,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20.0),
bottom: Radius.circular(50.0)
),
color: Colors.green,
),
child: Text('Hello'),
),
Container(
height: 100.0,
width: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.white,
image: DecorationImage(fit: BoxFit.cover,
image: NetworkImage('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559212477448&di=33798bc3e11474ac60916e6afce4c8cb&imgtype=0&src=http%3A%2F%2Fphotocdn.sohu.com%2F20160612%2FImg454047240.jpg'))
),
)
],),
],
),
);
}
}
标准组件
- Container
可包含多个其它组件,一般设置间距,颜色都可以用Container嵌套 - GridView
GridView
使用GridView将widget放置为二维列表。 GridView提供了两个预制list,或者您可以构建自定义网格。当GridView检测到其内容太长而不适合渲染框时,它会自动滚动。
GridView 概览:
- 在网格中放置widget
- 检测列内容超过渲染框时自动提供滚动
- 构建您自己的自定义grid,或使用一下提供的grid之一:
-
GridView.count
允许您指定列数 -
GridView.extent
允许您指定项的最大像素宽度
-
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: buildGrid(),
),
);
}
List<Container> _buildGridTileList(int count) {
return new List<Container>.generate(
count,
(int index) => Container(
child: Stack(
children: <Widget>[
Container(
child: new Image.asset(
'assets/images/pic${index % 2}.jpeg')),
Positioned(
//可设置以左,右,顶部,底部为基准
top: 0.0,
right: 0.0,
left: 0.0,
child: Container(
height: 20.0,
color: Colors.black45,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: Text("第${index + 1}张图片"),
)
],
),
)),
],
),
));
}
Widget buildGrid() {
return new GridView.extent(
maxCrossAxisExtent: 150.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: _buildGridTileList(30));
}
}
网格布局参照:
https://www.jianshu.com/p/fb3bf633ee12
瀑布流布局
https://pub.dev/packages/flutter_staggered_grid_view
- ListView
上下滑动
@override
Widget build(BuildContext context) {
var widgetList = ["Appbar", "Container", "Column", "Row", "ButtonAndTxt", "Stack","test","t1","t2","t3","t4","t1","t2","t3","t4"];
return Scaffold(
appBar: AppBar(
title: Text("Flutter Widgets Demo"),
),
body: ListView.builder(
itemCount: widgetList.length,
shrinkWrap: true,
itemBuilder: (builder, index){
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
//InkWell 添加Material触摸水波效果
child: InkWell(
onTap: (){
Navigator.of(context).pushNamed('${widgetList[index]}');
},
child: Card(
elevation: 5.0,
child: new Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
new Image.asset(
"assets/images/bg_net_error.jpg",width: 167,
height: 122,),
new ListTile(
title: Row(
children: <Widget>[
new Text(widgetList[index], style: TextStyle(color: Colors.black, fontSize: 20.0),),
Icon(Icons.keyboard_arrow_right),
],
),
subtitle: new Text('A'),
leading: index % 3 == 0
? new Icon(Icons.theaters, color: Colors.blue,)
: new Icon(Icons.restaurant, color: Colors.blue,),
),
],
)
),
),
),
);
}),
);
}
上拉加载下拉刷新请参考:
https://pub.dev/packages/pull_to_refresh
-
Stack
class StackWidget extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
height: 300.0,
width: 300.0,
color: Colors.red,
),
Container(
height: 250.0,
width: 250.0,
color: Colors.green,
),
Container(
height: 200.0,
width: 200.0,
color: Colors.yellow,
),
Container(
height: 150.0,
color: Colors.black,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
height: 120.0,
width: 120.0,
color: Colors.orange,
),
Positioned(//可设置以左,右,顶部,底部为基准
top: 0.0,
child: Container(
height: 120.0,
width: 100.0,
color: Colors.indigoAccent
,
),
),
],
),
),
),
],
),
);
}
}
Material Components**
Card ListTitle
child: Card(
elevation: 5.0,
child: new Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
new Image.asset(
"assets/images/bg_net_error.jpg",width: 167,
height: 122,),
new ListTile(
title: Row(
children: <Widget>[
new Text(widgetList[index], style: TextStyle(color: Colors.black, fontSize: 20.0),),
Icon(Icons.keyboard_arrow_right),
],
),
subtitle: new Text('A'),
leading: index % 3 == 0
? new Icon(Icons.theaters, color: Colors.blue,)
: new Icon(Icons.restaurant, color: Colors.blue,),
),
],
)
),
),
flutter插件地址
https://pub.dev/flutter/packages?q=