Flutter组件渲染集合的几种方式之详解与实战举例(更新)

一、Wrap组件

Wrap
以下是flutter默认给我们提供的接口

Wrap({
    Key key,
    this.direction = Axis.horizontal,
    this.alignment = WrapAlignment.start,
    this.spacing = 0.0,
    this.runAlignment = WrapAlignment.start,
    this.runSpacing = 0.0,
    this.crossAxisAlignment = WrapCrossAlignment.start,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    List<Widget> children = const <Widget>[],
  }) : super(key: key, children: children);

提供了很多属性,介绍一下属性都是干嘛的

属性 作用
direction 扩展方式 比如横向堆砌
alignment 对齐方式
spacing 主轴空隙间距
runAlignment run 的对齐方式
runSpacing run 空隙间距
crossAxisAlignment 纵轴对齐方式
textDirection 文本对齐方向
verticalDirection 确定垂直放置子元素的顺序,以及如何在垂直方向上解释开始和结束,默认down children 需要放置的组件列表

当选中该金额项目时,触发点击事件和样式,如下用Wrap实现,for循环遍历,拿到当前索引值

Flutter组件渲染集合的几种方式之详解与实战举例(更新)_第1张图片

int specIndex;
 Wrap(
          runSpacing: 10,
          spacing: 20,
          children: _buildMoneyItem(),
            ),
  List<Widget> _buildMoneyItem() {
    List<Widget> spectListWidget = [];
    for (int i = 0; i < list.length; i++) {
      spectListWidget.add(GestureDetector(
        onTap: () {
          selectedAccountValueSave = listValue[i];
          setState(() {
            specIndex = i;
          });
        },
        child: Container(
          height: 40,
          width: 75,
          alignment: Alignment.center,
          child: Center(
            child: Text(
              list[i],
              style: TextStyle(fontSize: 16),
            ),
          ),
          // padding: EdgeInsets.only(left: 10, right: 10),
          decoration: BoxDecoration(
              border: Border(
                top: BorderSide(
                    width: 1.0, color: specIndex == i ? colorRed : colorGrey),
                left: BorderSide(
                    width: 1.0, color: specIndex == i ? colorRed : colorGrey),
                right: BorderSide(
                    width: 1.0, color: specIndex == i ? colorRed : colorGrey),
                bottom: BorderSide(
                    width: 1.0, color: specIndex == i ? colorRed : colorGrey),
              ),
              color: Color(0xFFf7f7f7),
              borderRadius: BorderRadius.all(Radius.circular(2))),
        ),
      ));
    }
    return spectListWidget;
  }
二、GridView.count

控件网格的主轴方向是它滚动的方向( scrollDirection)。 最常用的网格布局是GridView.count,它创建了一个在横轴上具有固定数量 网格块 的平铺的布局

GridView源码

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,
  })

属性 值类型 说明
scrollDirection Axis 设置滚动的方向,horizontal(水平)或vertical(垂直)
reverse bool 是否翻转
controller ScrollController 用来控制滚动位置及监听滚动事件
shrinkWrap bool 是否根据子widget的总长度来设置GridView的长度
padding EdgeInsetsGeometry 间距
gridDelegate SliverGridDelegate 控制子Widget如何进行布局
children List 子控件

gridDelegate

该属性接收一个SliverGridDelegate类型的值,主要是用来控制子Widget如何进行布局。

Flutter组件渲染集合的几种方式之详解与实战举例(更新)_第2张图片
他有如下两个实现类
SliverGridDelegateWithMaxCrossAxisExtent和SliverGridDelegateWithFixedCrossAxisCount
构造方法

 const SliverGridDelegateWithMaxCrossAxisExtent({
    @required this.maxCrossAxisExtent, //子控件的最大宽度,实际宽度是根据交叉轴的值进行平分,也就是说最大宽度并不一定是实际宽度,很有可能子控件的实际宽度要小于设置的最大宽度
    this.mainAxisSpacing = 0.0, //主轴之间的间距
    this.crossAxisSpacing = 0.0,//交叉轴之间的间距
    this.childAspectRatio = 1.0,//子控件的宽高比
  }
GridView(
      scrollDirection: Axis.vertical,
      gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 100, //子控件最大宽度为100
        childAspectRatio: 0.5,//宽高比为1:2
        crossAxisSpacing: 10,
        mainAxisSpacing: 10,
      ),
      padding: EdgeInsets.all(10),
      children: List.generate(
        20,
        (index) {
          return Box(index + 1);
        },
      ),
    );

List.generate()

List.generate(images.length, (i){
  return Container(
    margin: EdgeInsets.only(left:20.0),
      child: 
        Image.network("${images[i]}",
          width: 375.0,
          fit: BoxFit.fitWidth,
        ),
   );
}),

实战举例

GridView.count(
        shrinkWrap: true,
        physics: NeverScrollableScrollPhysics(),
        crossAxisSpacing: 20,
        crossAxisCount: 3,
        children: menuList.map((e) {
          return InkWell(
            onTap: () {
              jumpToTargetPage(e.tag);
            },
            child: Column(
              children: [
                Image.asset(
                  e.icon,
                  height: 36,
                  width: 36,
                ),
                SizedBox(height: 10),
                Text(
                  e.title,
                  style: TextStyle(fontSize: 12, color: Colours.textBlack32),
                ),
              ],
            ),
          );
        }).toList(),
      )
  void jumpToTargetPage(String tag) {
    String pageName;
    Map arguments;
    switch (tag) {
      case "1":
        pushNamedPage(PublishRoute, arg: arguments);
        break;
      case "2":
        break;
    }
    if (pageName != null) {
      pushNamedPage(pageName, arg: arguments);
    }
  }
三、ListView.builder

ListView.builder 是一种构建列表的方法,其中的子 Widget 可以按需构建。但是,与返回静态 Widget 不同的是,它会多次调用(基于 itemCount)一个生成函数,并可在每次调用时返回不同的 Widget。

无限循环列表

ListView.builder(
  itemBuilder: (context, index) {
    return ListTile(
      leading: Icon(Icons.shopping_cart),
      title: Text('product $index'),
      subtitle: Text('price: ${Random().nextInt(100)} USD'),    
    );
  }
)
ListView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            itemBuilder: (ctx, index) {
              NewsModel news = accountViewModel.newsList[index];
              return InkWell(
                onTap: () {
                },
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 10),
                  child: Row(
                    children: [
                      Image.asset(
                        "resource/images/temp_news.png",
                        width: 110,
                        height: 70,
                        fit: BoxFit.fill,
                      ),
                      SizedBox(width: 10),
                      Expanded(
                        child: Container(
                          height: 70,
                          child: Column(
                            mainAxisSize: MainAxisSize.max,
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                news.title,
                                style: TextStyle(
                                    fontSize: 14, color: Colours.textBlack32),
                                overflow: TextOverflow.ellipsis,
                                softWrap: true,
                                maxLines: 2,
                              ),
                              Text(
                                news.pubDate,
                                style: TextStyle(
                                    fontSize: 12, color: Color(0xFFA3A0A0)),
                              ),
                            ],
                          ),
                        ),
                      )
                    ],
                  ),
                ),
              );
            },
            itemCount: accountViewModel.newsList.length,
          )

解决Flutter ListView 或者SingleChildScrollView 嵌套 ListView.builder滑动冲突

原因
SingleChildScrollView 和 ListView 都有滚动属性physics 他们默认是都是可以滚动的,
ListView 嵌套 ListView.builder 需要后者shrinkWrap = true,不然报错;
解决方式
禁用 ListView 的滚动physics 保留 SingleChildScrollView 的滚动
Listview 执行 physics 属性 new NeverScrollableScrollPhysics(), //禁用

new ListView.builder(
              shrinkWrap: true,
              physics: new NeverScrollableScrollPhysics(),
)

你可能感兴趣的:(Flutter移动开发,flutter)