Flutter容器
内边距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 往下平移10offset: 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的长度,默认值为falsebool shrinkWrap = false,// cell高度this.itemExtent,// 子widget是否包裹在AutomaticKeepAlive中bool addAutomaticKeepAlives = true,// 子widget是否包裹在RepaintBoundary中bool addRepaintBoundaries = true,bool addSemanticIndexes = true,// 设置预加载的区域, moren 0.0double 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 buildreturn 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