Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Expansion tile trailing icon updates all in list on interaction with one tile. How can I only change the icon for the expanded tile?

How do I make it so that the icon will only update for the tile that was clicked? Right now, the behavior is that all icons update when clicking on one tile.

Here is the code (trimmed to only include relevant parts):

Column(children: List.generate(
    filteredFAQ.length,
    (index) => Column(
        children: [
            if(index > 0) {
                Container(
                    child: Column(
                        children: <Widget>[
                            ExpansionTile(
                            trailing: SvgPicture.string(
                                isQuestionClicked
                                    ? addPayeeArrowUp
                                    : rightArrow,
                                color: primary,
                              ),
                              onExpansionChanged:
                                  (bool expanded) {
                                setState(() {
                                  isQuestionClicked = expanded;
                                });
                              },
                            ),
                        ],
                    )
                )
            }
        ]
    )
),);

here are screenshots of the behavior:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

beforeClickingOneTile

[afterClickingOneTile2

I used the in built onExpansionChange of the ExpansionTile.

>Solution :

To only change the icon of the expanded tile, you can use this approach:

create a Map:

Map<int, bool> state = {};

and use it accordingly in your ExpansionTile to check whether it’s selected, if the value is true or false:

 List.generate(6, (index) {
          return ExpansionTile(
            title: Text('Item $index'),
            trailing: state[index] ?? false
                ? Icon(Icons.arrow_drop_up)
                : Icon(Icons.arrow_drop_down),
            onExpansionChanged: (value) {
              setState(() {
                state[index] = value;
              });
            },
            children: [
              Container(
                height: 100,
                color: Colors.red,
              ),
            ],
          );
        }),

Complete runnable example:

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  Map<int, bool> state = {};

  bool isExpanded = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Column(
        children:
            // generate 6 ExpansionTiles
            List.generate(6, (index) {
          return ExpansionTile(
            title: Text('Item $index'),
            trailing: state[index] ?? false
                ? Icon(Icons.arrow_drop_up)
                : Icon(Icons.arrow_drop_down),
            onExpansionChanged: (value) {
              setState(() {
                state[index] = value;
              });
            },
            children: [
              Container(
                height: 100,
                color: Colors.red,
              ),
            ],
          );
        }),
      ),
    );
  }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading