三段代码打造好看的流式布局,flutter之wrap【flutter20个实例之七】

原创
2020/08/13 15:05
阅读数 6.9K

一、老套路,先看样式

左起图一是我业务中的样式,左起图二是下方源码展示样式(复制可直接运行,无额外组件引入)

    

二、讲解

1.结构拆分

首先,页面是个滚动列表,所以一定需要一个listview来容纳

然后每一个item,有个标题,比如精选

标题下方是一个流式布局,可自动切换行,用到了flutter的wrap组件

结构清晰后,无非就三段代码

2.首界面和数据加载

list是我们要循环的列表,这个列表是一级分类的数据

然后里面还有个topic字段,是二级分类的列表数据

也就是说这个_list字段是二维数组感慨念

    if (_list.isEmpty) {
      return Text('加载中....');
    } else {
      return ListView.builder(
        itemBuilder: (context, index) {
          return getItem(_list[index]);
        },
        itemCount: _list.length,
      );
    }

3.每一个item的设置

这里通过column来设置,一个组件就是标题,第二个组件就是wrap流式布局

4.wrap流式布局

我们重要来说这个

Wrap可以为子控件进行水平或者垂直方向布局,且当空间用完时,Wrap会自动换行,也是常说的流式​布局。

Wrap(
    alignment: WrapAlignment.spaceBetween,
    spacing: 10,
    children: List.generate(item['topic'].length, (i) {
        return _childList(item['topic'][i]);
        }
     ),
)

direction属性控制布局方向,默认为水平方向,设置方向为垂直代码如下:

Wrap(
	direction: Axis.vertical,
	...
)

alignment属性控制主轴对齐方式,crossAxisAlignment属性控制交叉轴对齐方式,对齐方式只对有剩余空间的行或者列起作用,例如水平方向上正好填充完整,则不管设置主轴对齐方式为什么,看上去的效果都是铺满。

Wrap(
	alignment: WrapAlignment.spaceBetween,
	...
)

spacingrunSpacing 属性控制Wrap主轴方向和交叉轴方向子控件之间的间隙

verticalDirection属性表示Wrap交叉轴方向上子控件的方向,取值范围是up(从上到下)和down(从下到上)

三、源码(可直接运行调试)

import 'package:flutter/material.dart';

class Mytest extends StatefulWidget {
  Mytest({Key key}) : super(key: key);
  _MytestState createState() => _MytestState();
}

class _MytestState extends State<Mytest> {
  List _list = [];

  @override
  void initState() {
    super.initState();
    this._getData();
  }

  _getData() async {
    //这里后面要换成数据请求
    List ret = [
      {
        'title': '精选',
        'topic': [
          {
            'title': '标题',
            'icon':
                'http://n1.c.imoxiu.com/85b4d9acec1b23abf499387f4fe4dd979483f46a/100'
          }
        ]
      }
    ];
    setState(() {
      this._list = ret;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: getHome(),appBar: AppBar(title: Text('流式布局'),elevation: 0.0,),);
  }

  Widget getHome() {
    if (_list.isEmpty) {
      return Text('加载中....');
    } else {
      return ListView.builder(
        itemBuilder: (context, index) {
          return getItem(_list[index]);
        },
        itemCount: _list.length,
      );
    }
  }

  Widget getItem(item) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Padding(
          padding: const EdgeInsets.fromLTRB(20, 10, 0, 10),
          child: Text(item['title'], style: TextStyle(color: Colors.black38)),
        ),
        Padding(
          padding: const EdgeInsets.fromLTRB(20, 10, 0, 10),
          child: item['topic'].length > 0
              ? Wrap(
                  alignment: WrapAlignment.spaceBetween,
                  spacing: 10,
                  children: List.generate(item['topic'].length, (i) {
                    return _childList(item['topic'][i]);
                  }),
                )
              : Container(),
        ),
      ],
    );
  }

  Widget _childList(topicItem) {
    return GestureDetector(
      onTap: () {},
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
            height: 20,
            child: Image.network(
              topicItem['icon'],
              fit: BoxFit.cover,
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(2, 0, 0, 0),
            child: Text(
              topicItem['title'],
              style: TextStyle(fontSize: 12, color: Colors.black),
            ),
          )
        ],
      ),
    );
  }
}

 

支持更新中......

展开阅读全文
打赏
1
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部