skip to Main Content

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:

beforeClickingOneTile

[afterClickingOneTile2

I used the in built onExpansionChange of the ExpansionTile.

2

Answers


  1. You have to manage each childrens state separatory.
    I think it’s best to manage them in filteredFAQ by adding

    bool isExpanded
    

    property there. but you can achive by manage them as separated property like

    final items = List<bool>.generate(filteredFAQ.length, (index) => false);
    

    and change their state when they’re expanded

    items[index] = !items[index]
    

    here’s a sample complete code

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

    And don’t forget to initalize items at where you initialize filteredFAQ

    If you provide a whole code in the widget I can complete it if you need more information

    Login or Signup to reply.
  2. 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,
                  ),
                ],
              );
            }),
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search