【问题标题】:How manage state of different widgets in ListView flutter?ListView flutter 中如何管理不同小部件的状态?
【发布时间】:2022-01-17 13:42:17
【问题描述】:

我正在构建一个 Flutter 应用程序,其中使用 ListView 显示列表。它返回一个带有用户信息的 ListTile。 ListTile 包含 leadingtitlesubtitle,其中 trailing 设置为 ElevatedButton

如下所示:

我想点击“邀请按钮”并更改 ListTile 中的 colortextsubtitle

点击后应该是这个样子。

我该怎么做?这是我写的代码。但它正在改变每个列表项的状态。

class InviteFriends extends StatefulWidget {
  const InviteFriends({Key? key}) : super(key: key);

  @override
  State<InviteFriends> createState() => _InviteFriendsState();
}

class _InviteFriendsState extends State<InviteFriends> {

  bool isSelected = false;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }
}

ListView.builder下的UI:

                       ListTile(
                            title: const Text('Haris'),
                            subtitle: const Text(
                              isSelected ? 'Invitation Sent' : 'Not Invited Yet',
                            ),
                            leading: CircleAvatar(
                              backgroundImage: NetworkImage(
                                _userProfile!.profilePhoto.toString(),
                              ),
                            ),
                            trailing: ElevatedButton(
                              style: ElevatedButton.styleFrom(
                                elevation: 0.0,
                                primary: isSelected ? Colors.orange : Colors.green,
                                side: BorderSide.none,
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(10.0),
                                ),
                              ),
                              child: const Text(
                                isSelected ? 'Invited': 'Invite',
                              ),
                              onPressed: () {
                                setState(() {
                               isSelected = !isSelected;
                                });
                              },
                            ),
                          );

我也在 ListTile 中使用 ValueKey(index) 尝试了 Keys,但它也没有工作。我该怎么办?谢谢

【问题讨论】:

    标签: flutter listview flutter-listview flutter-state


    【解决方案1】:
             return ListView.builder(
                 itemCount: itemCount.length
                  itemBuilder: (BuildContext context, int index) {
                  return Friend(
                  //arg if available
                  );
        });
    
    class Friend extends StatefulWidget {
      const Friend({Key? key}) : super(key: key);
    
      @override
      _FriendState createState() => _FriendState();
    }
    
    class _FriendState extends State<Friend> {
      bool isSelected = false;
      @override
      Widget build(BuildContext context) {
    //put ListTile detail here
        return Row(
          children: [
            FlatButton(//deprecated but other buttons work
                   key: PageStorageKey('random num'),//if you are interested in keeping the state of the button while navigating
                onPressed: () {
                  setState(() {
                    isSelected = !isSelected;
                  });
                },
                child: Text(isSelected ? "INVITED" : "INVITE"))
          ],
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      您创建一个列表,说“i”(变量)以了解每个图块的状态,并使用 false 进行初始化。点击时将状态更改为 true。

      final List&lt;bool&gt; selected = List.generate(20, (i) =&gt; false);

      将列表“i”传递给 listview.builder,例如:-

                  itemBuilder: (BuildContext context, i) 
      

      查看完整代码

      import 'package:flutter/material.dart';
      
      class InviteFriends extends StatefulWidget {
        const InviteFriends({Key? key}) : super(key: key);
      
        @override
        State<InviteFriends> createState() => _InviteFriendsState();
      }
      
      class _InviteFriendsState extends State<InviteFriends> {
        bool isSelected = false;
      
        @override
        void initState() {
          super.initState();
        }
      
        @override
        void dispose() {
          super.dispose();
        }
      
        final List<bool> selected = List.generate(20, (i) => false);
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            body: Padding(
              padding: const EdgeInsets.only(top: 60),
              child: ListView.builder(
                  // itemCount: i,
                  itemBuilder: (BuildContext context, i) {
                return ListTile(
                  title: const Text('Haris'),
                  subtitle: Text(
                    selected[i] ? 'Invitation Sent' : 'Not Invited Yet',
                  ),
                  leading: const CircleAvatar(
                    backgroundImage: AssetImage('assets/profile.gif'),
                  ),
                  trailing: ElevatedButton(
                      style: ElevatedButton.styleFrom(
                        elevation: 0.0,
                        primary: selected[i] ? Colors.orange : Colors.green,
                        side: BorderSide.none,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(10.0),
                        ),
                      ),
                      child: Text(
                        selected[i] ? 'Invited' : 'Invite',
                      ),
                      onPressed: () {
                        setState(() => selected[i] = !selected[i]);
                        // setState(() {
                        //   isSelected = !isSelected;
                        // });
                      }),
                );
              }),
            ),
          );
        }
      }
      
      

      谢谢

      输出

      【讨论】:

      • 与使用单独的 Stateful Widget 有何不同。单独的小部件工作正常,但我不确定使用哪一个。有什么不同吗?
      【解决方案3】:

      您需要为 listtiles 创建不同的类。执行以下操作:

       ListView.builder(
              itemCount: 3,
              shrinkWrap: true,
              itemBuilder: (ctx, i) {
                return MyListItems();
              }))
      

      然后是 MyListItems。

          class MyListItems extends StatefulWidget {
        @override
        MyListState createState() => MyListState();
      }
      
      class MyListState extends State<MyListItems> {
        bool isSelected = false;
      
        @override
        Widget build(BuildContext context) {
          return ListTile(
            title: const Text('Haris'),
            subtitle: Text(
              isSelected ? "Invitation Sent" : 'Not Invited Yet',
            ),
            leading: const CircleAvatar(
              backgroundImage: NetworkImage(
                  'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYtfZRhbGQtq2BapB2MXJfWIO2QriO5Wx3qQ&usqp=CAU'),
            ),
           // use your image here
            trailing: ElevatedButton(
              style: ElevatedButton.styleFrom(
                elevation: 0.0,
                primary: isSelected ? Colors.orange : Colors.green,
                side: BorderSide.none,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10.0),
                ),
              ),
              child: Text(
                isSelected ? 'Invited' : 'Invite',
              ),
              onPressed: () {
                setState(() {
                  isSelected = !isSelected;
                });
              },
            ),
          );
        }}
      

      【讨论】:

        【解决方案4】:

        将 Tile 作为单独的 StatefulWidget 取出,以便每个都有自己的状态。 不要修改 State List.builder。 并且你对所有 Tile 使用一个 isSelected 字段,你都会参考这个条件。

        请提供更多代码,我可以提供帮助。以便我了解全貌

        【讨论】:

          猜你喜欢
          • 2020-03-10
          • 2021-10-08
          • 1970-01-01
          • 2018-11-13
          • 2021-09-28
          • 2021-06-17
          • 2021-05-19
          • 1970-01-01
          • 2019-06-10
          相关资源
          最近更新 更多