内边距padding
class MyBody extends StatelessWidget {
Widget build(BuildContext context) {
return Container(//为了可以看出内边距,将容器设置成红色
color: Colors.red,
child: Padding(
padding: EdgeInsets.all(15),
child: MyImage('https://raw.githubusercontent.com/think-ing/flutter_demo/master/images/a.jpg'),
),
);
}
}
//定义一个 公共类
class MyImage extends StatelessWidget {
String imgUrl;
MyImage(this.imgUrl);
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,
child: Image.network(this.imgUrl,fit: BoxFit.cover,),
);
}
}
布局限制类容器
- 布局限制类容器是用来限制子元素的,并不是用来限制自身的
body: ConstrainedBox(
constraints: BoxConstraints. expandO.//编辑剩余空间
constraints: BoxConstraints(
minWidth: double. infinity,
minHeipht: 200,
maxHeight: 300
),
child: Container(
width: 1,
color: Colors. red
)
)
);
装饰容器
- DecoratedBox可以在其子组件绘制前后增加一些装饰,如背景、边框等。
body: DecoratedBox(decoration: BoxDecoration(
gradient: LinearGradient (colors: [Colors. yellow, Colors. red]),
borderRadius: BorderRadius. all(Radius. circular(3. 0)),
boxShadow: [
BoxShadow(
color: Colors. black,
offset: Offset(3, 3),
blurRadigs: 4.0
)
]
),
child: FlatButton(onPressed: null, child: Text ('test button')))
- BoxDecoration是DecoratedBox的子类:
BoxDecoration({
Color color, //颜色
DecorationImage image,//图片
BoxBorder border, //边框
BorderRadiusGeometry borderRadius, //圆角
List<BoxShadow> boxShadow, //阴影,可以指定多个
Gradient gradient, //渐变
BlendMode backgroundBlendMode, //背景混合模式
BoxShape shape = BoxShape.rectangle, //形状
})
变换transform
- Transform可以在其子组件绘制时对其应用一些矩阵变换来实现一些特效。Matrix4是一个4D矩阵,通过它我们可以实现各种矩阵操作
Container(
margin: const EdgeInsets.fromLTRB(20, 100, 20, 20),
color: Colors.green,
child: Transform(
alignment: Alignment.bottomRight, //原点
transform: Matrix4.skewY(0.5), //沿Y轴倾斜0.5弧度
child: Container(
padding: const EdgeInsets.all(10),
color: Colors.brown,
child: Text("Flutter NB"),
),
),
width: 100,
height: 50,
),
- Transform.translate接收一个offset参数,可以在绘制时沿x、y轴对子组件平移指定的距离。
Text("平移"),
DecoratedBox(
decoration: BoxDecoration(color: Colors.purple),
child: Transform.translate(
//原点为左上角 往右平移 50 往下平移10
offset: Offset(50, 10),
child: Text("谁是最可爱的人?"),
),
),
- Transform.rotate可以对子组件进行旋转变换
Container(
margin: const EdgeInsets.only(top: 50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("旋转"),
DecoratedBox(
decoration: BoxDecoration(color: Colors.purple),
child: Transform.rotate(
angle: pi / 2,
child: Text("是他是他就是他"),
),
),
],
),
),
- Transform.scale可以对子组件进行缩小或放大
Container(
margin: const EdgeInsets.only(left: 100, top: 50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("缩放"),
DecoratedBox(
decoration: BoxDecoration(color: Colors.purple),
child: Transform.scale(
scale: 2, //放大2倍
child: Text("大大泡泡糖"),
),
),
],
),
),
Container
- 是flutter里面一个很重要的容器,相当于html中的div
属性:
- key:Container唯一标识符,用于查找更新。
- alignment:控制child的对齐方式,如果container或者container父节点尺寸大于child的尺寸,这个属性设置会起作用,有很多种对齐方式。
- padding:decoration内部的空白区域,如果有child的话,child位于padding内部。padding与margin的不同之处在于,padding是包含在content内,而margin则是外部边界,设置点击事件的话,padding区域会响应,而margin区域不会响应。
- color:用来设置container背景色,如果foregroundDecoration设置的话,可能会遮盖color效果。
- decoration:绘制在child后面的装饰,设置了decoration的话,就不能设置color属性,否则会报错,此时应该在decoration中进行颜色的设置。
- foregroundDecoration:绘制在child前面的装饰。
- width:container的宽度,设置为double.infinity可以强制在宽度上撑满,不设置,则根据child和父节点两者一起布局。
- height:container的高度,设置为double.infinity可以强制在高度上撑满。
- constraints:添加到child上额外的约束条件。
- margin:围绕在decoration和child之外的空白区域,不属于内容区域。
- transform:设置container的变换矩阵,类型为Matrix4。
- child:container中的内容widget。
可滚动widgets
- 在Flutter中, 当内容超过显示视图时,如果没有特殊处理,Flutter则会提示Overflow错误
- Flutter提供了多种可滚动(Scrollable Widget)用于显示列表和长布局
- 可滚动Widget都直接或间接包含一个Scrollable, 下面是常用的几个可滚动的Widget
SingleChildScrollView
ListView
GridView
CustomScrollView
- 滚动监听及控制
ScrollController
1.SingleChildScrollView
,使用的时候外边需要Scrollbar包裹
body: Scrollbar(
child: SingleChildScrollView(
child: Container(
height: 3000,
color: Colors.red
)
),
)
2.ListView
-
ListView
是最常用的可滚动widget,它可以沿一个方向线性排布所有子widget, 类似于ReactNative
中的ListView
-
ListView共有四种构造函数
1. ListView()默认构造函数 2. ListView.builder() 3. ListView.separated() 4. ListView custom()
ListView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
EdgeInsetsGeometry padding,
// 是否根据子widget的总长度来设置ListView的长度,默认值为false
bool shrinkWrap = false,
// cell高度
this.itemExtent,
// 子widget是否包裹在AutomaticKeepAlive中
bool addAutomaticKeepAlives = true,
// 子widget是否包裹在RepaintBoundary中
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
// 设置预加载的区域, moren 0.0
double cacheExtent,
//子widget列表
List<Widget> children = const <Widget>[],
// 子widget的个数
int semanticChildCount,
})
例子
class ScrollView extends StatelessWidget {
Widget build(BuildContext context) {
return ListView(
itemExtent: 60,
cacheExtent: 100,
addAutomaticKeepAlives: false,
children: renderCell(),
);
}
List<Widget> renderCell() {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return str.split("")
.map((item) => ListTile(
title: Text('字母--$item'),
subtitle: Text('这是字母列表'),
leading: Icon(Icons.wifi),
)).toList();
}
}
body: Column(
children: <Widget>[
ListTile(title:Text(因定的表头”)),
Container(
height: 400,
child: ListView. builder(
itemCount: 50,
itemExtent: 50,
itemDuilder: (BuildContext context, int index) {
return Text (' + index. toString0);
)),
)
],
)
3.GridView
GridView
可以构建二维网格列表, 系统给出了五中构造函数
- GridView()
- GridView.count
- GridView.extent
- GridView.builder
- GridView.custom
// 默认构造函数
GridView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required this.gridDelegate,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
})
- 可以看到, 除了gridDelegate属性外, 其他属性和ListView的属性都一样, 含义也都相同
- SliverGridDelegate是一个抽象类,定义了GridView排列相关接口,子类需要通过实现它们来实现具体的布局算法
- Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent, 下面我们分别介绍
1. SliverGridDelegateWithFixedCrossAxisCount
该子类实现了一个横轴为固定数量子元素的排列算法,其构造函数为:
const SliverGridDelegateWithFixedCrossAxisCount({
// 横轴子元素的数量,此属性值确定后子元素在横轴的长度就确定了,即ViewPort横轴长度/crossAxisCount。
this.crossAxisCount,
// 主轴方向的间距
this.mainAxisSpacing = 0.0,
// 侧轴方向子元素的间距
this.crossAxisSpacing = 0.0,
// 子元素在侧轴长度和主轴长度的比例, 由于crossAxisCount指定后子元素横轴长度就确定了,然后通过此参数值就可以确定子元素在主轴的长度
this.childAspectRatio = 1.0,
})
从上面的个属性可以发现,子元素的大小是通过crossAxisCount
和childAspectRatio
两个参数共同决定的。注意,这里的子元素指的是子widget的最大显示空间,注意确保子widget的实际大小不要超出子元素的空间, 代码示例如下
class ScrollView extends StatelessWidget {
Widget build(BuildContext context) {
return GridView(
padding: EdgeInsets.all(10),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1,
mainAxisSpacing: 10,
crossAxisSpacing: 10
),
children: <Widget>[
Container(color: Colors.orange),
Container(color: Colors.blue),
Container(color: Colors.orange),
Container(color: Colors.yellow),
Container(color: Colors.pink)
],
);
}
}
2.GridView.count
GridView.count
构造函数内部使用了
SliverGridDelegateWithFixedCrossAxisCount
,我们通过它可以快速的创建横轴固定数量子元素的GridView
GridView.count({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
int crossAxisCount,
double mainAxisSpacing = 0.0,
double crossAxisSpacing = 0.0,
double childAspectRatio = 1.0,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
})
上面SliverGridDelegateWithFixedCrossAxisCount
中给出的示例代码等价于:
class CountGridView extends StatelessWidget {
Widget build(BuildContext context) {
// TODO: implement build
return GridView.count(
padding: EdgeInsets.all(10),
crossAxisCount: 3,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 1,
children: <Widget>[
Container(color: Colors.orange),
Container(color: Colors.blue),
Container(color: Colors.orange),
Container(color: Colors.yellow),
Container(color: Colors.pink)
],
);
}
}
3.GridView.extent
同样GridView.extent
构造函数内部使用了SliverGridDelegateWithMaxCrossAxisExtent
,我们通过它可以快速的创建侧轴子元素为固定最大长度的的GridView
class ExtentScrollView extends StatelessWidget {
Widget build(BuildContext context) {
return GridView.extent(
padding: EdgeInsets.all(10),
maxCrossAxisExtent: 100,
childAspectRatio: 1,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
children: <Widget>[
Container(color: Colors.orange),
Container(color: Colors.blue),
Container(color: Colors.orange),
Container(color: Colors.yellow),
Container(color: Colors.pink)
],
);
}
}
4.GridView.builder
class BuilderGridView extends StatelessWidget {
Widget build(BuildContext context) {
return GridView.builder(
itemCount: 50,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
mainAxisSpacing: 10,
crossAxisSpacing: 10
),
itemBuilder: (content, index) {
return Container(
color: Colors.orange,
child: Center(
child: Text('$index'),
),
);
},
);
}
}
5.GridView.custom