Flutter使用ListView.Builder:如何在选择了所有项目的情况下更改仅一项的背景颜色

问题描述

  • 我使用Listviewbuilder渲染了一个时隙列表,我需要的是只能选择其中的一项,当我选择它时,我只需要更改该项的背景,然后显示保留细节,但实际要做的是将所有项目背景更改为另一种颜色

[![This is image that before select a one time slot][1]][1][![And this when i try to select one item all items are selected and then the reservation details appear when i preesed the time slot][1]][1]

[![And this when i try to select one item all items are selected and then the reservation details appear when i preesed the time slot][1]][1]
class _ReservationSlotsWidgetState extends State<ReservationSlotsWidget> {
  var _isExpanded = false;
  var slots = [
    '09:00AM','10:00AM','11:00AM','12:00PM','01:00PM','02:00PM','03:00PM','04:00PM',];

  @override
  Widget build(BuildContext context) {
    final deviceSize = MediaQuery.of(context).size;
    return Scaffold(
      extendBodyBehindAppBar: true,....

 Expanded(
                  child: ListView.builder(
                itemCount: slots.length,scrollDirection: Axis.horizontal,itemBuilder: (ctx,index) {
                  var slot = slots[index];
                  return GestureDetector(
                    onTap: () {
                      setState(() {
                        _isExpanded = !_isExpanded;
                      });
                    },child: Container(
                        padding: EdgeInsets.all(4),margin: EdgeInsets.all(4),decoration: Boxdecoration(
                            color: _isExpanded
                                ? Theme.of(context).primaryColor
                                : parseColor('#2A2E43'),borderRadius:
                                BorderRadius.all(Radius.circular(10))),child: SlotsWidget())
                        );
                        }
              )),],),SizedBox(
          height: deviceSize.height * 0.00025,if (_isExpanded)
          Container(
              padding: EdgeInsets.all(16),margin: EdgeInsets.all(16),height: deviceSize.height * 0.2,decoration: Boxdecoration(
                  color: Theme.of(context).primaryColorDark,borderRadius: BorderRadius.all(Radius.circular(10))),child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
                            Row(
                              children: <Widget>[
                                Icon(
                                  Icons.person_add,color: Colors.white,SizedBox(
                                  width: 5,Text('Number of persons',style: TextStyle(
                                      color: Colors.white,)),SizedBox(
                                  height: 5,Row(
                              children: <Widget>[
                                Icon(
                                  Icons.person_add,color: Colors.transparent,Text('(max 7 persons)',....

解决方法

因此,您问题的关键是您的 ListView Builder 的索引。 当前操作方式是将一个布尔值设置为true或false,该布尔值适用于列表中的每个元素。 您需要做的就是保存展开的小部件的索引。

更改

onTap: () {
     setState(() {
         _isExpanded = !_isExpanded;
     });
},

收件人

int _expandedIndex;
...
onTap: () {
    setState(() {
       _expandedIndex = index
    });
},

然后改变

color: _isExpanded
       ? Theme.of(context).primaryColor
       : parseColor('#2A2E43'),

收件人

color: _expandedIndex == index
       ? Theme.of(context).primaryColor
       : parseColor('#2A2E43'),
,

创建类似的单独类

class Slot {
  String time;
  bool isSelected;

  Slot(this.time,this.isSelected);
}

创建上述类别的广告位列表

 var slots = [
    Slot('09:00AM',false),Slot('10:00AM',Slot('11:00AM',Slot('12:00PM',//... Rest of the items
  ];

从列表中获取广告位对象(应位于Listview.Builder内)

var slot = slots[index];
var time = slot.time; // Get the time from slot object

点击列表项,将isSelected标记为true

slot.isSelected = true;

OR

slot.isSelected = !slot.isSelected; // Vice versa