如何在onTap上为选定的ListItem着色

时间:2018-08-31 09:00:19

标签: listview flutter selecteditem

我想用颜色从ListView中选择值:

enter image description here

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

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])
                    ),
                  ),
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

这就是我所实现的,都是彩色的:

enter image description here

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

3 个答案:

答案 0 :(得分:2)

您应该为列表中的每个项目都拥有一个isSelected值,然后,当用户单击列表中的一个项目时,您将只为录音项目索引和构建语句更改isSelected值应该根据传入索引

的isSelected值执行操作

这是示例:

enter image description here

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 Value,如下例所示:

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});
}

出于性能方面的考虑,我认为第二个选项更好

答案 1 :(得分:0)

您需要做的是重构代码,以使传递到ListView builder函数中的小部件拥有自己的StatefulWidget。因此,将构建器函数内的窗口小部件树移至其自己的单独StatefulWidget中,并在那里处理状态操纵逻辑,而不是ProcedureList。之所以会出现这种行为,是因为通过将逻辑移动到单独的ListView.builder中,每个从isSelected生成的实例都将处于相同的状态值StatefulWidget之下,每个实例将有自己的状态。

答案 2 :(得分:0)

对不起,您的答复很晚。我有一个更好的解决方案,并且我更改了您的代码

    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