Flutter开发 - tableview的cell中for循环怎么写

376 阅读3分钟

写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(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

刚好需要的小伙伴可以拿走代码自己跑一下,代码是完整的界面代码,直接贴进去就可以跑。

专注手把手教大家写代码,让学习没有难处。