【问题标题】:How to color selected ListItem onTap如何为选定的 ListItem onTap 着色
【发布时间】:2019-02-06 06:43:39
【问题描述】:

我想像这样从 ListView 中为选择值着色:

问题是我在尝试时打印所有内容,代码:

class _ProcedureList extends State<ProcedureList> {

bool isSelected  = true;

   _isSelected() {
    setState(() {
      if (isSelected) {
        isSelected = false;
      } else {
        isSelected = true;
      }
    });
  }



  @override
  Widget build(BuildContext context) {
    var procedureList = widget.filteredkits
        .where((kit) => kit.brand == widget.brand)
        .map((kit) => kit.procedure)
        .toSet()
        .toList();

    return Expanded(
      flex: 2,
      child: Container(
        padding: EdgeInsets.only(left: 35.0),
        child: new ListView.builder(
          itemCount: procedureList.length,
          itemBuilder: (BuildContext context, int index) {
            return Padding(
              padding: EdgeInsets.all(6.0),
              child: Column(
                children: <Widget>[
                  new Container(
                    width: 300.0,
                    height: 30.0,
                    color: Colors.grey[700],
                    padding: EdgeInsets.all(6.0),
                    child: new Text(widget.brand),
                  ),
                  GestureDetector(
                    onTap: () => widget.getProcedureSelectedandList(procedureList[index].toString()) & _isSelected(),
                    child: Container(
                      width: 300.0,
                      padding: EdgeInsets.all(3.0),
                      color: !isSelected ? Colors.white : Colors.orange,
                      child: 
                      new Text(procedureList[index])
                    ),
                  ),
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

这就是我实现的目标,全是彩色的:

我不知道如何在事件发生时只为一个项目着色,以及我们是否可以更好地使用相同的事件更改文本颜色。

【问题讨论】:

  • isSelected 应该是filteredkit 中的成员

标签: listview flutter selecteditem


【解决方案1】:

您需要做的是重构您的代码,以便传递给ListViewbuilder 函数的小部件拥有它自己的StatefulWidget。因此,将 builder 函数内的小部件树移动到其自己单独的 StatefulWidget 中,并在其中处理状态操作逻辑,而不是 ProcedureList。您出现此行为的原因是因为从ListView.builder 生成的每个实例都暴露于isSelected 的相同状态值,方法是将您的逻辑移动到单独的StatefulWidget 中,每个实例都有自己的状态。

【讨论】:

    【解决方案2】:

    您应该对列表中的每个项目都有一个 isSelected 值,然后当用户单击列表中的其中一个项目时,您将更改 isSelected 值仅用于磁带项目索引和构建语句中您应该根据传入索引的 isSelected 值执行操作

    这是一个例子:

    class MyListWidgetState extends State<MyListWidget> {
      List<String> items = ["A", "B", "C", "D", "E", "F"];
    
      Map<int, bool> itemsSelectedValue = Map();
    
      @override
      Widget build(BuildContext context) {
        return new ListView.builder(
            itemCount: items.length,
            itemBuilder: (context, index) {
              bool isCurrentIndexSelected = itemsSelectedValue[index] == null
                  ? false
                  : itemsSelectedValue[index];
    
              Container contianer;
    
              if (isCurrentIndexSelected) {
                contianer = new Container(
                  alignment: Alignment.center,
                  height: 100.0,
                  color: Colors.blue,
                  child: new Text(
                    items[index],
                    style: new TextStyle(color: Colors.red, fontSize: 18.0),
                    textAlign: TextAlign.center,
                  ),
                );
              } else {
                contianer = new Container(
                  alignment: Alignment.center,
                  height: 100.0,
                  color: Colors.red,
                  child: new Text(
                    items[index],
                    style: new TextStyle(color: Colors.blue, fontSize: 18.0),
                    textAlign: TextAlign.center,
                  ),
                );
              }
    
              return GestureDetector(
                onTap: () {
                  print("${!isCurrentIndexSelected}");
                  itemsSelectedValue[index] = !isCurrentIndexSelected;
    
                  setState(() {
                    print("OnClick : $index + ${itemsSelectedValue[index]}");
                  });
                },
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: contianer,
                ),
              );
            });
      }
    }
    

    或者您可以创建 StateFull 小部件,为列表中的每个项目保留自己的 isSelected 值,如下例所示:

    List<String> items = [
      "A",
      "B",
      "C",
      "D",
      "E",
      "F",
      "D",
      "J",
      "K",
      "L",
      "M",
      "P"
    ];
    
    class SampleApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Sample App',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new Scaffold(
              body: new ListView.builder(
            itemCount: items.length,
            itemBuilder: (context, index) {
              return new SelectableWidget(
                new SelectableWidgetViewModel(
                  items[index],
                  isSelected: false,
                ),
              );
            },
          )),
        );
      }
    }
    
    class SelectableWidget extends StatefulWidget {
      final SelectableWidgetViewModel viewModel;
    
      SelectableWidget(this.viewModel);
    
      @override
      State<StatefulWidget> createState() {
        return SelectableWidgetState();
      }
    }
    
    class SelectableWidgetState extends State<SelectableWidget> {
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        Container container;
    
        if (widget.viewModel.isSelected) {
          container = new Container(
            alignment: Alignment.center,
            height: 100.0,
            color: Colors.blue,
            child: new Text(
              widget.viewModel.title,
              style: new TextStyle(color: Colors.red, fontSize: 18.0),
              textAlign: TextAlign.center,
            ),
          );
        } else {
          container = new Container(
            alignment: Alignment.center,
            height: 100.0,
            color: Colors.red,
            child: new Text(
              widget.viewModel.title,
              style: new TextStyle(color: Colors.blue, fontSize: 18.0),
              textAlign: TextAlign.center,
            ),
          );
        }
    
        return GestureDetector(
          onTap: () {
            setState(() {
              widget.viewModel.isSelected = !widget.viewModel.isSelected;
            });
          },
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: container,
          ),
        );
      }
    }
    
    class SelectableWidgetViewModel {
      bool isSelected;
      String title;
    
      SelectableWidgetViewModel(this.title, {this.isSelected = false});
    }
    

    出于性能原因,我认为第二种选择更好

    【讨论】:

      【解决方案3】:

      抱歉回复晚了。我有一个更好的解决方案,我已经更改了您的代码

          class _ProcedureList extends State<ProcedureList> {
      
      
      
              int isSelected  = -1; // changed bool to int and set value to -1 on first time if you don't select anything otherwise set 0 to set first one as selected. 
      
      
             _isSelected(int index) { //pass the selected index to here and set to 'isSelected'
              setState(() {
                  isSelected = index;
              });
            }
      
      
      
            @override
            Widget build(BuildContext context) {
              var procedureList = widget.filteredkits
                  .where((kit) => kit.brand == widget.brand)
                  .map((kit) => kit.procedure)
                  .toSet()
                  .toList();
      
          return Expanded(
            flex: 2,
            child: Container(
              padding: EdgeInsets.only(left: 35.0),
              child: new ListView.builder(
                itemCount: procedureList.length,
                itemBuilder: (BuildContext context, int index) {
                  return Padding(
                    padding: EdgeInsets.all(6.0),
                    child: Column(
                      children: <Widget>[
                        new Container(
                          width: 300.0,
                          height: 30.0,
                          color: Colors.grey[700],
                          padding: EdgeInsets.all(6.0),
                          child: new Text(widget.brand),
                        ),
                        GestureDetector(
                          onTap: () => widget.getProcedureSelectedandList(procedureList[index].toString()) & _isSelected(index), //pass index value to '_isSelected' 
                          child: Container(
                            width: 300.0,
                            padding: EdgeInsets.all(3.0),
                            color: isSelected != null && isSelected == index //set condition like this. voila! if isSelected and list index matches it will colored as white else orange.
                                   ? Colors.white 
                                   : Colors.orange,
                            child: 
                            new Text(procedureList[index])
                          ),
                        ),
                      ],
                    ),
                  );
                },
              ),
            ),
          );
        }
      }
      

      还是一头雾水check this blog

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-13
        • 1970-01-01
        相关资源
        最近更新 更多