首页 > 解决方案 > Flutter Checkbox Stepper如何实现?

问题描述

我正在尝试实现以下布局

在此处输入图像描述

我尝试使用 Stepper,但它并没有真正解决我的问题,所以我尝试使用 vanilla dart 代码本身

Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Checkbox(value: true, onChanged: (value) {}),
              Text("Complaint Received"),
            ],
          ),
          Padding(
            padding: const EdgeInsets.only(
              left: 20,
            ),
            child: Container(
              padding: const EdgeInsets.all(0),
              width: 2,
              height: 80,
              color: Colors.black,
            ),
          ),
          Row(
            children: <Widget>[
              Checkbox(value: true, onChanged: (value) {}),
              Text("Complaint Received"),
            ],
          ),
          Container(
            width: 2,
            height: 10,
            color: Colors.black,
          ),
          Row(
            children: <Widget>[
              Checkbox(value: true, onChanged: (value) {}),
              Text("Complaint Received"),
            ],
          ),
          Container(
            width: 2,
            height: 10,
            color: Colors.black,
          ),
          Row(
            children: <Widget>[
              Checkbox(value: true, onChanged: (value) {}),
              Text("Complaint Received"),
            ],
          ),
          Container(
            width: 2,
            height: 10,
            color: Colors.black,
          ),
        ],
      ),

以下是我实现的ui

在此处输入图像描述

我不明白为什么前两行和容器之间有填充

标签: flutterdart

解决方案


在 Flutter 中,复选框并不是StatelessWidget我们习惯的那种纯粹的小部件。

CheckboxRenderObject通过'方法绘制它的边界、一个带有圆边的框和“复选”标记本身paint,有点像 HTML5 Canvas(如果你熟悉的话)。

这一事实使得自定义 Flutter 复选框变得很困难,甚至改变了诸如围绕它的填充之类的琐碎的东西。


我的解决方案并没有以您尝试的方式解决您的问题,但它确实提供了一个很棒的视图,就像您想要实现的那样。

final double barsHeight = 40.0;
final double barsWidth = 3.0;
final Color inactiveBarColor = Colors.grey;
final Color activeBarColor = Colors.blue;

Map<String, bool> steps = {
  "Complaint Received": true,
  "Engineer Assigned": true,
  "Engineer On the way": false,
  "Complaint Done": false,
};

@override
Widget build(BuildContext context) {
  double rowPadding = (barsHeight - kRadialReactionRadius) / 2;
  double _barHeight = barsHeight;
  if (rowPadding < 0) {
    rowPadding = 0;
    _barHeight = kRadialReactionRadius;
  }
  return Padding(
    padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
    child: Stack(fit: StackFit.loose, children: <Widget>[

      Positioned(
        left: kRadialReactionRadius - barsWidth / 2,
        top: kRadialReactionRadius + rowPadding,
        bottom: kRadialReactionRadius + rowPadding,
        width: barsWidth,
        child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: List.generate(steps.length - 1, (i) =>
          Container(
            margin: EdgeInsets.symmetric(vertical: kRadialReactionRadius / 2 - 2),
            height: _barHeight + 4,
            color: steps.values.elementAt(i) && steps.values.elementAt(i + 1) ? activeBarColor : inactiveBarColor,
          )
        ))
      ),
      Theme(
        data: Theme.of(context).copyWith(disabledColor: inactiveBarColor, unselectedWidgetColor: inactiveBarColor),
        child: Column(mainAxisSize: MainAxisSize.min, children: steps.keys.map((key) =>
          Padding(
            padding: EdgeInsets.symmetric(vertical: rowPadding),
            child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
              Checkbox(
                value: steps[key],
                onChanged: steps[key] ? (_) {} : null,
                activeColor: activeBarColor,
                materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
              ),
              Text(key),
            ])
          )
        ).toList())
      )

    ]),
  );
}

简而言之,它是如何工作的:

  • CheckboxkRadialReactionRadius对其大小和填充使用常量。这就是我们知道其确切大小的方式,现在我们可以在每个复选框行之间绘制条形图。
  • Column使用 复选框在 下方绘制垂直条Stack
  • 复选框的默认边框颜色被Theme小部件覆盖。

要更改复选框状态 - 只需修改steps变量中的值。例如

setState(() {
  steps[steps.keys.elementAt(/*checkbox index*/)] = true;
});

最后结果:

最后结果

让我知道这是否有帮助。


推荐阅读