首页 > 解决方案 > 小部件可以有一个“联合”状态吗?

问题描述

我想实现一个自定义单选按钮,但我可以选择所有这些,当然,“单选”的意思是,我只能选择一个。

我的代码:


class RadioSelect extends StatefulWidget {
  const RadioSelect(this.text, this.index, {Key key}) : super(key: key);
  final String text;
  final int index;
  @override
  _RadioSelectState createState() => _RadioSelectState();
}

class _RadioSelectState extends State<RadioSelect> {
  int sizeIndex = 0;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        setState(() {
          sizeIndex = widget.index;
        });
      },
      child: Container(
        alignment: Alignment.center,
        padding: EdgeInsets.fromLTRB(12, 8, 12, 8),
        margin: EdgeInsets.only(right: 8, top: 8),
        width: 70,
        height: 55,
        decoration: BoxDecoration(
            color: Colors.white,
            border: Border.all(
              width: 3,
              color: sizeIndex == widget.index
                  ? Color.fromARGB(255, 139, 195, 74)
                  : Colors.white,
            ),
            borderRadius: BorderRadius.all(
                Radius.circular(10) //         <--- border radius here
            )),
        child: Text(
          widget.text,
          style: TextStyle(
            fontSize: 18,
            color: Colors.black,
          ),
          textAlign: TextAlign.center,
        ),
      ),
    );
  }
}

我知道这是因为每个RadioSelect()都是不同的实例,但我怎样才能让它工作呢?

标签: flutter

解决方案


您可以根据Radio小部件执行此操作:

  1. 将您的小部件更改为StatelessWidget.
class RadioSelect extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // ...
  }
}
  1. 创建一个isSelected属性并基于此属性设置小部件布局。
class RadioSelect extends StatelessWidget {
  final bool isSelected;

  const RadioSelect({this.isSelected});

  @override
  Widget build(BuildContext context) {
    return Container(
      // Some logic based on isSelected
      color: isSelected ? Colors.red : Colors.white,
    );
  }
}
  1. 创建一个onChanged属性,每次用户点击它时,调用这个属性。
class RadioSelect extends StatelessWidget {
  final void Function() onChanged;
  final bool isSelected;

  const RadioSelect({this.isSelected, this.onChanged});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      // Use onChanged as callback
      onTap: () => onChanged(),
      child: Container(
        color: isSelected ? Colors.red : Colors.white,
      ),
    );
  }
}

现在,当您必须使用它的多个实例时,您可以使用索引来跟踪当前选择的收音机:

class _MainWidgetState extends State<MainWidget> {
  // Keeping track of the number of ratios you are using
  final int _numRadios = 10;
  int _currentIndex;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        for (int i = 0; i < _numRatios; i++)
          RadioSelect(
            // The radio is select if the current index of this widget
            // is equal to the current index of this child in the Column
            isSelected: _currentIndex == i,
            // When the user taps one ratio, updte the current index
            // of this widget and set a new state
            onChanged: () => setState(() => _currentIndex = i),
          )
      ]
    );
  }
}

注意:上面的代码认为所有比率的布局都是相等的。例如,如果每个比率都必须有自己的文本,则可以替换_numRatios为字符串列表或更具描述性的数据对象:

class _MainWidgetState extends State<MainWidget> {
  final List<String> texts = ["radio1", "radio2", "radio3", "radio4"];
  int _currentIndex;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        for (int i = 0; i < texts.length; i++)
          RadioSelect(
            // Supposing you have a text property in your RadioSelect
            // Access the text of the current child in the list of strings
            text: texts[i],
            isSelected: _currentIndex == i,
            onChanged: () => setState(() => _currentIndex = i),
          )
      ]
    );
  }
}

推荐阅读