服装行业网站建设比较好,大宗交易平台,全网推广图片,建设移动端网站布局
基本布局
GridView#xff08;二维滚动列表#xff09;#xff1a;比ListView多了一个方向的数据填充。ListBody#xff08;滚动列表#xff09;#xff1a;相比ListView#xff0c;没有回收复用#xff0c;简单易用。Table#xff08;表格布局#xff09;二维滚动列表比ListView多了一个方向的数据填充。ListBody滚动列表相比ListView没有回收复用简单易用。Table表格布局子元素类似表格一样在X轴和Y轴排列分布。Flow流式布局相比Wrap布局的子元素自动换行Flow需要自行在Delegate里写算法实现换行。Wrap流式布局子元素在X轴放得下就放放不下就去下一行的布局。ScrollView(滚动视图)一般搭配Column使用的类似滚动列表的布局。
GridView
就是二维的ListView有五种构造方式 GridView() 默认构造硬编码子widget数量多有性能风险 GridVIew.builder() 懒加载 GridView.costom()GirdView.count() 在交叉轴方向上固定数目 GridView.extent() 在交叉轴方向上固定数目且有长度限制
代码
/// GridView()
GridView(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,//交叉轴方向的数目),children: Widget[Text(1),Text(2),Text(3),Text(4),Text(5),Text(6),Text(7),Text(8),Text(9),],
),
/// GridView.builder()
final ListString name String[1,2,3,];
GridView.builder(itemCount: name.length,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,//交叉轴方向item的数量mainAxisSpacing: 2.0,//主轴方向的间隔crossAxisSpacing: 2.0,//交叉轴之间的间隔),itemBuilder: (context, index) {return Container(child: Text(name[index]),);},
),
/// GridView.costom()GridView.custom(gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 80.0,//在交叉轴方向上单个item的最大长度crossAxisCount: 3,//交叉轴方向item的数量mainAxisSpacing: 2.0,//主轴方向的间隔),childrenDelegate: SliverChildBuilderDelegate((context, index) {return Container(child: Text(name[index]),);},childCount: name.length,),
),
/// GirdView.count()
GridView.count(crossAxisCount: 3,children: Widget[Text(1),Text(2),Text(3),Text(4),Text(5),Text(6),Text(7),Text(8),Text(9),],
),
/// GridView.extent()
GridView.extent(maxCrossAxisExtent: 100.0,//在交叉轴方向上item的最大长度crossAxisCount: 3,//交叉轴方向item的数量mainAxisSpacing: 2.0,//主轴方向的间隔children: Widget[Container(child: Text(1),),Container(child: Text(2),),Container(child: Text(3),),],
),
完整示例代码
import package:flutter/material.dart;class HomeTabPage1 extends StatelessWidget {List listData [{title: 标题1,author: 内容1,image: https://www.itying.com/images/flutter/1.png},{title: 标题2,author: 内容2,image: https://www.itying.com/images/flutter/2.png},{title: 标题3,author: 内容3,image: https://www.itying.com/images/flutter/3.png},{title: 标题4,author: 内容4,image: https://www.itying.com/images/flutter/4.png},{title: 标题5,author: 内容5,image: https://www.itying.com/images/flutter/5.png},{title: 标题6,author: 内容6,image: https://www.itying.com/images/flutter/6.png},{title: 标题7,author: 内容7,image: https://www.itying.com/images/flutter/7.png},{title: 标题8,author: 内容8,image: https://www.itying.com/images/flutter/1.png},{title: 标题9,author: 内容9,image: https://www.itying.com/images/flutter/2.png},{title: 标题1,author: 内容1,image: https://www.itying.com/images/flutter/1.png},{title: 标题2,author: 内容2,image: https://www.itying.com/images/flutter/2.png},{title: 标题3,author: 内容3,image: https://www.itying.com/images/flutter/3.png},{title: 标题4,author: 内容4,image: https://www.itying.com/images/flutter/4.png},{title: 标题5,author: 内容5,image: https://www.itying.com/images/flutter/5.png},{title: 标题6,author: 内容6,image: https://www.itying.com/images/flutter/6.png}];ListWidget _getData() {ListWidget list [];for (var i 0; i listData.length; i) {list.add(Container(child: Column(children: [Image.network(listData[i][image],fit: BoxFit.cover,),Text(listData[i][title],textAlign:TextAlign.center,)],),));}return list;}overrideWidget build(BuildContext context) {return GridView.count(//设置滚动方向scrollDirection: Axis.vertical,//设置列数crossAxisCount: 5,//设置内边距整个GridView的padding: EdgeInsets.all(30),//设置横向间距3个间距一起用就能控制item各种距离了crossAxisSpacing: 30,//设置主轴间距mainAxisSpacing: 30,children: _getData(),);}
}常用参数
gridDelegate
有两个实现类 SliverGridDelegateWithFixedCrossAxisCount 根据设置的个数显示二维滚动列表 SliverGridDelegateWithMaxCrossAxisExtent 根据设置的长度显示二维滚动列表
scrollDirection
* 滚动方向* Axis.vertical* 竖向滚动* Axis.horizontal* 横向滚动reverse
* 组件反向排序controller
* 滚动监听primary
* 值为false内容不足不可滑动
* 值为true内容不足可以尝试滑动shrinkWrap
* 内容适配默认为falsepadding
* 内边距crossAxisCount
* 列数mainAxisSpacing
* 主轴之间的间距crossAxisSpacing
* 横轴之间的间距childAspectRatio
* 设置宽高的比例
* GridView的子组件直接设置宽高没有反应可以通过childAspectRatio修改宽高cacheExtent
* 设置预加载区域children
* 组件元素 const Widget列表
* 数组内添加widget类型的数据
* flutter的所有组件都是widget,也就是说所有的GridView可以添加所有的组件semanticChildCount
* 提供语义信息的子组件数量ListBody
很少单独使用搭配如Row、Column、ListView、Flex一起使用。
代码
Column(//主轴垂直排列的列表未限制宽默认将充满屏幕children: Widget[ListBody(//指定主轴方向与父框架相同mainAxis: Axis.vertical,reverse: false,//不反向children: Widget[Container(color: Colors.red, width: 50.0, height: 50.0),Container(color: Colors.yellow, width: 50.0, height: 50.0),Container(color: Colors.green, width: 50.0, height: 50.0),Container(color: Colors.blue, width: 50.0, height: 50.0),Container(color: Colors.black, width: 50.0, height: 50.0),],)],
)Table
像表格一样布局
代码
Container(width: 300.0,height: 200.0,padding: EdgeInsets.all(2.0),color: Color(0xFFC5CAE9),child: Table(//每行中单元格的宽度TableRow内元素个数即列数从第一个到最后一个的宽度//如果排列根据排列方向显示不同columnWidths: const int, TableColumnWidth{0: FixedColumnWidth(30.0),1: FixedColumnWidth(70.0),2: FixedColumnWidth(50.0),3: FixedColumnWidth(100.0),},//默认未显示宽度 默认的每一列宽度值默认情况下均分。defaultColumnWidth: const FlexColumnWidth(1.0),//每个表格的排列方向此处设置从右到左textDirection: TextDirection.rtl,//表格边框此处设置蓝色2像素宽实线border: TableBorder.all(color: Colors.blue, width: 2.0, style: BorderStyle.solid),//每一个单元格的垂直方向的对齐方式默认为顶部对齐defaultVerticalAlignment: TableCellVerticalAlignment.top,//基线类型与TableCellVerticalAlignment.baseline一起使用//textBaseline: null,children: TableRow[TableRow(decoration: BoxDecoration(color: Colors.purpleAccent),children: Widget[Text(A1),Text(A2),Text(A3),Text(A4),],),TableRow(decoration: BoxDecoration(color: Colors.purpleAccent),children: Widget[Container(color: Colors.red, child: Text(赤)),Container(color: Colors.orange, child: Text(橙)),Container(color: Colors.yellow, child: Text(黄)),Container(color: Colors.green, child: Text(绿)),],),TableRow(children: Widget[Text(B1),Text(B2),Text(B3),Text(B4),]),],),
)参数
columnWidth每列单元格的宽度int为从0到每行的个数-1defaultColumnWidth默认的每一列宽度值默认情况下均分。textDirection每列的排列方向默认从左到右borderTableBorder 表格的边框defaultVerticalAlignment单元格默认垂直方向上的对齐方式默认上对齐TableCellVerticalAlignment.toptextBaselineTableCellVerticalAlignment.baseline与此属性配合使用。文本基线类型children存放每行的单元格内容的类别
Flow
重点在于FlowDelegate的使用
FlowDelegate的方法
abstract class FlowDelegate {const FlowDelegate({ Listenable repaint }) : _repaint repaint;final Listenable _repaint;//重写设置尺寸Size getSize(BoxConstraints constraints) constraints.biggest;//重写设置约束BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) constraints;//绘制children的位置和大小void paintChildren(FlowPaintingContext context);//是否要从新布局可自己定制规则bool shouldRelayout(covariant FlowDelegate oldDelegate) false;//是否从新绘制可自己定制规则bool shouldRepaint(covariant FlowDelegate oldDelegate);overrideString toString() $runtimeType;
}代码
Flow(delegate: TestFlowDelegate(margin: EdgeInsets.all(5.0)),children: Widget[new Container(width: 60.0, height: 60.0, color: Colors.red,child: Text(红), alignment: Alignment.center, ),new Container(width: 60.0, height: 60.0,color: Colors.orange,child: Text(橙),alignment: Alignment.center, ),new Container(width: 60.0,height: 60.0,color: Colors.yellow,child: Text(黄),alignment: Alignment.center, ),new Container(width: 60.0,height: 60.0,color: Colors.green,child: Text(绿),alignment: Alignment.center, ),new Container(width: 60.0,height: 60.0,color: Colors.cyan,child: Text(青),alignment: Alignment.center ),new Container(width: 60.0, height: 60.0,color: Colors.blue,child: Text(蓝),alignment: Alignment.center, ),new Container(width: 60.0,height: 60.0,color: Colors.purple,child: Text(紫),alignment: Alignment.center, ),],
)class TestFlowDelegate extends FlowDelegate {EdgeInsets margin EdgeInsets.zero;TestFlowDelegate({this.margin});overridevoid paintChildren(FlowPaintingContext context) {var x margin.left;var y margin.top;for (int i 0; i context.childCount; i) {var w context.getChildSize(i).width x margin.right;if (w context.size.width) {context.paintChild(i,transform: new Matrix4.translationValues(x, y, 0.0));x w margin.left;} else {x margin.left;y context.getChildSize(i).height margin.top margin.bottom;context.paintChild(i,transform: new Matrix4.translationValues(x, y, 0.0));x context.getChildSize(i).width margin.left margin.right;}}}overridebool shouldRepaint(FlowDelegate oldDelegate) {return oldDelegate ! this;}
}Wrap
在mainAxis上空间不足时则向crossAxis上去扩展显示。Wrap使用方便一些但是Flow能实现WrapFlow更强一些。
参数
direction 主轴方向默认水平alignment 主轴方向方式值为WrapAlignment的枚举值详情请看Row的对齐方式spacing 主轴方向上child之间的间距默认为0runAlignment 新一行或一列的对齐方式runSpacing 新的一行或一列的间距默认为0crossAxisAlignment交叉轴的对齐方式默认是从主轴开始位置开始textDirection每一行或一列的排列方式 如果一行有三个元素则第一行取出前三个元素2,1,0这样排列 verticalDirection垂直方向上排列方式值为VerticalDirection的枚举值默认从上到下
代码
Container(alignment: Alignment.topCenter,child: Wrap(//主轴方向默认水平direction: Axis.horizontal,//主轴方向方式包裹在一个控件内效果明显默认主轴方向开始位置开始alignment: WrapAlignment.spaceBetween,//主轴方向上child之间的间距默认为0spacing: 6.0,// 新一行或一列的对齐方式runAlignment: WrapAlignment.spaceBetween,//新的一行或一列的间距默认为0runSpacing: 0.0,//交叉轴的对齐方式默认是从主轴开始位置开始crossAxisAlignment: WrapCrossAlignment.start,//每一行或一列的排列方式如果一行有三个元素则第一行取出前三个元素2,1,0这样排列//默认从左到右textDirection: TextDirection.ltr,//垂直方向上排列方式默认从上到下verticalDirection: VerticalDirection.down,children: Widget[Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(1)),label: Text(Hamilton),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(2)),label: Text(Lafayette),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(3)),label: Text(Mulligan),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(4)),label: Text(Laurens),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(5)),label: Text(Hamilton),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(6)),label: Text(Lafayette),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(7)),label: Text(Mulligan),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(8)),label: Text(Laurens),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(9)),label: Text(Hamilton),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(10)),label: Text(Lafayette),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(11)),label: Text(Mulligan),),Chip(avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text(12)),label: Text(Laurens),),],),
)ScrollView
有很多子类实现 SingleChildScrollView
SingleChildScrollView
有子view数组的ScrollView
代码
SingleChildScrollView(child: Column(children: Widget[Container(height: 200,color: Colors.red,),Container(height: 200,color: Colors.green,),Container(height: 200,color: Colors.blue,),Container(height: 200,color: Colors.yellow,),Container(height: 200,color: Colors.orange,),],),
),自定义ScrollPhysics控制滑动效果
准确的说这个属于所有physics参数共用的一个案例继承ScrollPhysics可以实现自定义滑动的效果
import package:flutter/material.dart;void main() {runApp(MyApp());
}class MyCustomScrollPhysics extends ScrollPhysics {const MyCustomScrollPhysics({ScrollPhysics? parent}) : super(parent: parent);overrideMyCustomScrollPhysics applyTo(ScrollPhysics? ancestor) {return MyCustomScrollPhysics(parent: buildParent(ancestor));}overridedouble applyBoundaryConditions(ScrollMetrics position, double value) {// 检查是否已经滑动到边界if (value position.pixels position.pixels position.minScrollExtent) {// 滑动到顶部边界时允许继续向上滚动return 0.0;} else if (value position.pixels position.pixels position.maxScrollExtent) {// 滑动到底部边界时允许继续向下滚动return 0.0;}// 其他情况使用默认的边界条件return super.applyBoundaryConditions(position, value);}
}class MyApp extends StatelessWidget {overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(body: CustomScrollView(physics: MyCustomScrollPhysics(), // 使用自定义的ScrollPhysicsslivers: Widget[SliverAppBar(expandedHeight: 200.0,pinned: true,flexibleSpace: FlexibleSpaceBar(title: Text(Custom Scroll Physics Example),),),SliverList(delegate: SliverChildBuilderDelegate((BuildContext context, int index) {return ListTile(title: Text(Item $index),);},childCount: 100, // 你的列表项数量),),],),),);}
}