Flutter Using ListView.Builder:如何在我选择的所有项目上仅更改一项的背景颜色

Posted

技术标签:

【中文标题】Flutter Using ListView.Builder:如何在我选择的所有项目上仅更改一项的背景颜色【英文标题】:Flutter Using ListView.Builder: how can i change background color of only one item on all items with i selected it 【发布时间】:2021-01-01 11:33:37 【问题描述】: 我使用 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,
                                ),
                                SizedBox(
                                  width: 5,
                                ),
                                Text('(max 7 persons)',
                                    style: TextStyle(
                                      color: Colors.white,
                                    )),
       
....

【问题讨论】:

【参考方案1】:

所以问题的关键是 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'),

【讨论】:

【参考方案2】:

创建单独的类

class Slot 
  String time;
  bool isSelected;

  Slot(this.time, this.isSelected);

创建上述类的槽列表

 var slots = [
    Slot('09:00AM', false),
    Slot('10:00AM', false),
    Slot('11:00AM', false),
    Slot('12:00PM', false),
    //... 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;

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

【讨论】:

以上是关于Flutter Using ListView.Builder:如何在我选择的所有项目上仅更改一项的背景颜色的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 项目 Your app isn't using AndroidX错误

Flutter + Firebase Throwing Unhandled Exception: This widget has been unmounted Error Using Navigato

flutter解决 dart:html 只支持 flutter_web 其他平台编译报错 Avoid using web-only libraries outside Flutter web(代码片段

Flutter Using ListView.Builder:如何在我选择的所有项目上仅更改一项的背景颜色

Flutter环境搭建

Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.