写flutter也有一段时间了,期间多是带着iOS的思想在写,今天带给大家的是flutter中tableview,cell里面有多个相似的item的布局。看下图:
这个布局在iOS中是比较常见的布局,我们一般会在cell中通过for循环的方式布局,在flutter中,for循环并不能直接用来布局,那要怎么写呢?
方法1:这个是博主曾经用过的方式,就是一个个的写,效率比较低,还要判空,点击事件和赋值都要单独分开给数据源,不推荐这么做;
方法2:博主今天推荐的方法是使用Wrap,看看具体代码怎么写的吧:
Container(
margin: EdgeInsets.only(left: 16, right: 16, top: 18, bottom: 0),
child: Wrap(
spacing: 8.0, // 主轴(水平)方向间距
runSpacing: 0, // 纵轴(垂直)方向间距
///用下面的属性控制起始位置
alignment: WrapAlignment.start,
runAlignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
///数据源,这里控制下最大数量即可
children: ['商品1', '商品2', '商品3', '商品4']
.map<Widget>((e) => new GestureDetector(
child: Container(
color: Colors.white,
///根据屏幕计算好每个item的宽度
width: (MediaQuery.of(context).size.width - 64 - 24) / 4,
height: 112,
child: Column(
children: <Widget>[
//设置圆角(下一篇会讲讲设置圆角的坑)
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
color: Color(0xFFF1F1F1),
child: Container(
width: (MediaQuery.of(context).size.width - 64 - 24) / 4,
height: (MediaQuery.of(context).size.width - 64 - 24) / 4,
),
)),
Container(
padding: EdgeInsets.only(top: 5),
width: (MediaQuery.of(context).size.width - 64 - 24) / 4,
child: Text(e, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),),
),
],
),
),
onTap: () {
},
))
.toList(),
),
),
这个页面分两部分给大家呈现:
第一部分:页面page,也加入了返回顶部的功能,基本上就是上一篇的翻版,主要看cell
import 'package:flutter/material.dart';
import 'package:flutter_app/back_to_top.dart';
import 'package:flutter_app/list_item_cell.dart';
class ForListView extends StatefulWidget {
@override
_ForListViewState createState() => _ForListViewState();
}
class _ForListViewState extends State<ForListView> {
final ScrollController _controller =
new ScrollController(keepScrollOffset: false);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('for循环布局怎么写?'),
),
body: SafeArea(
child: Container(
color: Color(0xf5f5f5f5),
child: Stack(
children: <Widget>[
ListView.builder(
controller: _controller,
itemBuilder: (BuildContext context, int index) {
return ListItemCell();
},
itemCount: 100,
),
BackToTop(_controller),
],
),
),
),
);
}
}
第二部分:cell的widget自定义,这个是重点
import 'package:flutter/material.dart';
class ListItemCell extends StatefulWidget {
@override
_ListItemCellState createState() => _ListItemCellState();
}
class _ListItemCellState extends State<ListItemCell> {
@override
Widget build(BuildContext context) {
return Card(
elevation: 0.0, //设置阴影
margin: EdgeInsets.only(left: 16, top:12, right: 16, bottom: 0),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))),
child: Container(
height: 188,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: GestureDetector(
onTap: () {
},
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 16, top: 18),
child: Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Container(
width: 40,
height: 40,
color: Color(0xFFF1F1F1),
child: Container(
width: 40,
height: 40,
),
),
),
),
),
Container(
margin: EdgeInsets.only(top: 18, left: 12),
width: MediaQuery.of(context).size.width - 64 - 52 - 68,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 0, left: 0),
height: 18,
child: Text('Flutter的tableView布局',
textDirection: TextDirection.ltr,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 15,
color: Color.fromRGBO(38, 38, 38, 1),
fontWeight: FontWeight.bold
),
),
),
Container(
margin: EdgeInsets.only(left: 0, top: 5),
child: Text(
'好多cell啊',
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12,
color: Color.fromRGBO(165, 171, 182, 1),
),
),
),
],
),
),
Container(
width: 48,
height: 24,
padding: EdgeInsets.all(0),
margin: EdgeInsets.only(left: 20, top: 26),
child: OutlineButton(
padding: EdgeInsets.all(0),
color: Colors.white,
splashColor: Colors.grey,
child: Text("详情", style: TextStyle(color: Color.fromRGBO(255, 73, 28, 1), fontSize: 12),),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0)),
borderSide: new BorderSide(color: Color.fromRGBO(255, 73, 28, 1)),
onPressed: () {
},
),
),
],
),
)
),
Container(
margin: EdgeInsets.only(left: 16, right: 16, top: 18, bottom: 0),
child: Wrap(
spacing: 8.0, // 主轴(水平)方向间距
runSpacing: 0, // 纵轴(垂直)方向间距
alignment: WrapAlignment.start,
runAlignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
children: ['商品1', '商品2', '商品3', '商品4']
.map<Widget>((e) => new GestureDetector(
child: Container(
color: Colors.white,
width: (MediaQuery.of(context).size.width - 64 - 24) / 4,
height: 112,
child: Column(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
color: Color(0xFFF1F1F1),
child: Container(
width: (MediaQuery.of(context).size.width - 64 - 24) / 4,
height: (MediaQuery.of(context).size.width - 64 - 24) / 4,
),
)),
Container(
padding: EdgeInsets.only(top: 5),
width: (MediaQuery.of(context).size.width - 64 - 24) / 4,
child: Text(e, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),),
),
],
),
),
onTap: () {
},
))
.toList(),
),
),
],
),
),
);
}
}
刚好需要的小伙伴可以拿走代码自己跑一下,代码是完整的界面代码,直接贴进去就可以跑。
专注手把手教大家写代码,让学习没有难处。