美文网首页
flutter 中如何使用Wrap实现流布局

flutter 中如何使用Wrap实现流布局

作者: 小木虫666 | 来源:发表于2021-11-26 15:01 被阅读0次

Wrap使用笔记

Wrap是一个可以使子控件自动换行的控件,默认的方向是水平的,使用起来也很简单。

首先看下他的构造方法:

  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,   //textDirection水平方向上子控件的起始位置
    this.verticalDirection = VerticalDirection.down,  //垂直方向上子控件的其实位置
    List<Widget> children = const <Widget>[],   //要显示的子控件集合
  })

使用🌰(数据模型代码没贴出):

// MARK - Option Alert
Widget _buildOptionView(Dispatch dispatch, OptionState state) {
  return Container(
    decoration: const BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.only(
          topLeft: (Radius.circular(16)), topRight: (Radius.circular(16))),
    ),
    child: Column(
      children: [
        _buildAppbar(),
        Expanded(
          child: ListView.builder(
              itemCount: state.optionTitles.length,
              itemBuilder: (BuildContext context, int index) {
                return _buildOptionCard(state, index);
              }),
        ),
        MaterialButton(
          height: 50,
          minWidth: Screen.width - 32,
          shape: const RoundedRectangleBorder(
            side: BorderSide.none,
            borderRadius: BorderRadius.all(Radius.circular(25)),
          ),
          onPressed: () {
            dispatch(OptionActionCreator.onCompleteAction());
          },
          color: const Color.fromRGBO(51, 55, 88, 1),
          child: const Text(
            '完成',
            style: TextStyle(
              color: Colors.white,
              fontSize: 16,
            ),
          ),
        ),
        const SizedBox(height: 24),
      ],
    ),
  );
}

Widget _buildAppbar() {
  return Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: [
      SizedBox(
        width: 60,
        child: MaterialButton(
          onPressed: () {
            _dispatch(OptionActionCreator.onResetAction());
          },
          child: const Text(
            '重置',
            style: TextStyle(fontSize: 14),
          ),
        ),
      ),
      const Text(
        '全部筛选',
        style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
      ),
      SizedBox(
        width: 60,
        child: MaterialButton(
          onPressed: () {
            // SmartDialog.dismiss();
            Navigator.of(_viewService.context).pop();
          },
          child: Container(
            margin: const EdgeInsets.only(left: 16),
            child: const Image(
              image: AssetImage('images/close@3x.png'),
              width: 12,
              height: 12,
            ),
          ),
        ),
      ),
    ],
  );
}

Widget _buildOptionCard(OptionState state, int index) {
  String key = state.optionTitles[index];
  List optionItems = state.optionInfo[key];

  OptionModel model = state.options[index];

  return Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Container(
        margin: const EdgeInsets.only(left: 16),
        child: Text(
          key,
          textAlign: TextAlign.left,
          style: const TextStyle(
            fontSize: 14,
          ),
        ),
      ),
      Container(
        margin: const EdgeInsets.only(left: 16),
        child: Wrap(
          spacing: 8,
          children: List.generate(optionItems.length, (itemIndex) {
            return buildChoiceButton(model, index, itemIndex);
          }).toList(),
        ),
      ),
      const SizedBox(height: 20),
    ],
  );
}

Widget buildChoiceButton(OptionModel model, int optionIndex, int itemIndex) {
  bool selected = false;

  if (model.single) {
    selected = model.selectedIndex == itemIndex;
  } else {
    selected = model.selectedIndexes.contains(itemIndex);
  }

  Color bgColor = selected ? model.selectedBgColor : model.normalBgColor;
  Color textColor = selected ? model.selectedTextColor : model.normalTextColor;

  BorderSide selectedSide =
      BorderSide(color: model.selectedTextColor, width: 1);

  return MaterialButton(
    onPressed: () {
      // Update state
      _state.optionSelectedIndex = optionIndex;
      _state.optionItemSelectedIndex = itemIndex;

      _dispatch(OptionActionCreator.onClickOptionCardItem());
    },
    height: 32,
    minWidth: 105,
    color: bgColor,
    shape: RoundedRectangleBorder(
      side: selected ? selectedSide : BorderSide.none,
      borderRadius: const BorderRadius.all(Radius.circular(16)),
    ),
    child: Text(
      model.optionItems[itemIndex],
      style: TextStyle(fontSize: 14, color: textColor),
    ),
  );
}

类似效果如图:

Screenshot_1637909919.png

相关文章

网友评论

      本文标题:flutter 中如何使用Wrap实现流布局

      本文链接:https://www.haomeiwen.com/subject/qgxxxrtx.html