三段程式碼打造好看的流式佈局,flutter之wrap【flutter20個例項之七】

蔥頭來過發表於2021-08-16

一、老套路,先看樣式

圖一是我業務中的樣式,圖二是下方原始碼展示樣式(複製可直接執行,無額外元件引入)

二、講解

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),
            ),
          )
        ],
      ),
    );
  }
}
複製程式碼

支援更新中......

相關文章