Search code examples
flutterlistviewdartbuilderprovider

Flutter Using ListView.Builder: how can i change background color of only one item on all items with i selected it


  • I used ListViewBuilder to render a list of time slots, and What i need is to be able to select only one item of them, and when i selected it i need to change the background of only this item and then appear the reservation details, but what actually done is that the all items background changed to another color

[![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,
                                    )),
       
....

Solution

  • So the key to your question is the index of your ListView Builder. The way you are currently doing it, is you are setting a single boolean to be true or false, which applies to every element of your list. What you need to do, is save the index of your expanded widget.

    Change

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

    To

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

    And change

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

    To

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