【问题标题】:How to iterate through list of map and display Text widget in flutter listview?如何遍历地图列表并在颤动列表视图中显示文本小部件?
【发布时间】:2021-06-20 19:26:23
【问题描述】:

我对颤动很陌生,我试图通过 for 循环从内容列表中显示列表视图,但我能够打印一个列表行,这是一次迭代,因为 return 只触发一次。如何遍历完整列表并显示所有列表视图元素? 以下是地图内容列表

 List<Map<String, String>> users = [
    {"name": "Staff 1", "status": "Online"},
    {"name": "Staff 2", "status": "Online"},
    {"name": "Staff 3", "status": "Offline"},
    {"name": "Vehicle 1", "status": "Available"},
    {"name": "Vehicle 2", "status": "Unavailable"},
    {"name": "Team 1", "status": "Active"},
    {"name": "Team 2", "status": "Not Active"},
  ];

下面是我要显示的列表视图小部件的代码

  Widget ListViewBuilder() {
        for (var i = 0; i < users.length; i++) {
          print(i);
          return Expanded(
            child: ListView(
              children: <Widget>[
                GestureDetector(
                  onTap: () {
                    Navigator.pushNamed(
                      context,
                      '/chatscreen',
                    );
                  },
                  child: ListTile(
                      leading: CircleAvatar(
                          radius: 20,
                          backgroundImage: AssetImage("assets/profileavatar.png")),
                      title: Text(users[i]['name']),
                      subtitle: Text("User -ID"),
                      trailing: Row(
                          mainAxisAlignment:
                              MainAxisAlignment.spaceBetween, // added line
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            Text(
                              users[i]['status'],
                              style: TextStyle(
                                color: Colors.green,
                                fontSize: 20,
                          ),
                 ),                          
              ],
            ),
          );
        }
      }

这将只显示列表中的第一个元素,我怎样才能显示列表用户中存在的所有列表视图元素?任何建议都会有所帮助

【问题讨论】:

    标签: flutter listview dart widget


    【解决方案1】:

    编辑:我在你那里的那个分隔符上隔开,我同意 @Sam Chan 建议 ListView.separated 而不是我之前推荐的 ListView.builder

    对于初学者,将ListTile 提取到它自己的小部件并传入几个字符串会更干净。否则它会很快变得混乱。这是一个例子。

    class CustomListTile extends StatelessWidget {
      final String name, status;
    
      const CustomListTile({Key key, this.name, this.status}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: () {
            Navigator.pushNamed(
              context,
              '/chatscreen',
            );
          },
          child: ListTile(
            leading: CircleAvatar(
                radius: 20,
                backgroundImage: AssetImage("assets/profileavatar.png")),
            title: Text(name),
            subtitle: Text("User -ID"),
            trailing: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween, // added line
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Text(
                  status,
                  style: TextStyle(
                    color: Colors.green,
                    fontSize: 20,
                  ),
                ),
                SizedBox(
                  width: 20,
                ),
                InkWell(
                  onTap: () {
                    Navigator.pushNamed(
                      context,
                      '/viewlocation',
                    );
                  },
                  child: Icon(
                    Icons.add_location,
                    color: Colors.green,
                    size: 40,
                  ),
                ),
                SizedBox(
                  width: 20,
                ),
                Container(
                  decoration: BoxDecoration(
                      color: Colors.green,
                      border: Border.all(
                        color: Colors.green,
                      ),
                      borderRadius: BorderRadius.all(Radius.circular(20))),
                  child: InkWell(
                    onTap: () async {
                      const number = '08592119XXXX'; //set the number here
                      // bool res = await FlutterPhoneDirectCaller.callNumber(number);
                    },
                    child: Icon(
                      Icons.call,
                      color: Colors.white,
                      size: 40,
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
    

    这是一个显示地图列表的完整页面示例。

    class DemoPage extends StatelessWidget {
      DemoPage({
        Key key,
      }) : super(key: key);
    
      final List<Map<String, String>> users = [
        {"name": "Staff 1", "status": "Online"},
        {"name": "Staff 2", "status": "Online"},
        {"name": "Staff 3", "status": "Offline"},
        {"name": "Vehicle 1", "status": "Available"},
        {"name": "Vehicle 2", "status": "Unavailable"},
        {"name": "Team 1", "status": "Active"},
        {"name": "Team 2", "status": "Not Active"},
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            children: [   
              Expanded(
                child: ListView.separated(
                  separatorBuilder: (BuildContext context, int index) => Divider(
                    color: Colors.black,
                    endIndent: 10,
                    indent: 10,
                  ),
                  itemCount: users.length,
                  itemBuilder: (context, index) {
                    // parsing the maps in the list before passing them into the extracted widget
                    // the itemBuilder iterates through the list
                    final name = users[index]['name'];
                    final status = users[index]['status'];
                    return CustomListTile(name: name, status: status);
                  },
                ),
              ),
            ],
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      问题是您在每个循环中都构建了ListView。您可以使用循环构建ListTile 列表并传递给ListView

      但是我建议你使用ListView.separated,它更容易。喜欢

        Widget listViewBuilder() {
          return Expanded(
              child: ListView.separated(
                  itemCount: users.length,
                  itemBuilder: (context, i) {
                    return GestureDetector(
                      onTap: () {
                        Navigator.pushNamed(
                          context,
                          '/chatscreen',
                        );
                      },
                      child: ListTile(
                          leading: CircleAvatar(
                              radius: 20,
                              backgroundImage:
                                  AssetImage("assets/profileavatar.png")),
                          title: Text(users[i]['name']),
                          subtitle: Text("User -ID"),
                          trailing: Row(
                              mainAxisAlignment:
                                  MainAxisAlignment.spaceBetween, // added line
                              mainAxisSize: MainAxisSize.min,
                              children: <Widget>[
                                Text(
                                  users[i]['status'],
                                  style: TextStyle(
                                    color: Colors.green,
                                    fontSize: 20,
                                  ),
                                ),
                                SizedBox(
                                  width: 20,
                                ),
                                InkWell(
                                  onTap: () {
                                    Navigator.pushNamed(
                                      context,
                                      '/viewlocation',
                                    );
                                  },
                                  child: Icon(
                                    Icons.add_location,
                                    color: Colors.green,
                                    size: 40,
                                  ),
                                ),
                                SizedBox(
                                  width: 20,
                                ),
                                Container(
                                  decoration: BoxDecoration(
                                      color: Colors.green,
                                      border: Border.all(
                                        color: Colors.green,
                                      ),
                                      borderRadius:
                                          BorderRadius.all(Radius.circular(20))),
                                  child: InkWell(
                                    onTap: () async {
                                      const number =
                                          '08592119XXXX'; //set the number here
                                      bool res =
                                          await FlutterPhoneDirectCaller.callNumber(
                                              number);
                                    },
                                    child: Icon(
                                      Icons.call,
                                      color: Colors.white,
                                      size: 40,
                                    ),
                                  ),
                                )
                              ])),
                    );
                  },
                  separatorBuilder: (BuildContext context, int index) {
                    return Divider(
                      color: Colors.black,
                      endIndent: 10,
                      indent: 10,
                    );
                  }));
        }
      

      【讨论】:

        【解决方案3】:

        这里的问题是 - 您在第一个循环中返回结果。这就是为什么您只能获得列表中的第一个元素。

        您需要在 ListView 小部件中遍历您的地图。

        List<Map<String, String>> users = [
            {"name": "Staff 1", "status": "Online"},
            {"name": "Staff 2", "status": "Online"},
            {"name": "Staff 3", "status": "Offline"},
            {"name": "Vehicle 1", "status": "Available"},
            {"name": "Vehicle 2", "status": "Unavailable"},
            {"name": "Team 1", "status": "Active"},
            {"name": "Team 2", "status": "Not Active"},
          ];
        
        Widget ListViewBuilder(BuildContext context) {
              return Expanded(
                child: ListView(
                  children: <Widget>[
                    ...users.map( (u) => 
                    <Widget> [GestureDetector(
                      onTap: () {
                        Navigator.pushNamed(
                          context,
                          '/chatscreen',
                        );
                      },
                      child: ListTile(
                          leading: CircleAvatar(
                              radius: 20,
                              backgroundImage: AssetImage("assets/profileavatar.png")),
                          title: Text(u['name']),
                          subtitle: Text("User -ID"),
                          trailing: Row(
                              mainAxisAlignment:
                                  MainAxisAlignment.spaceBetween, // added line
                              mainAxisSize: MainAxisSize.min,
                              children: <Widget>[
                                Text(
                                  u['status'],
                                  style: TextStyle(
                                    color: Colors.green,
                                    fontSize: 20,
                                  ),
                                ),
                                SizedBox(
                                  width: 20,
                                ),
                                InkWell(
                                  onTap: () {
                                    Navigator.pushNamed(
                                      context,
                                      '/viewlocation',
                                    );
                                  },
                                  child: Icon(
                                    Icons.add_location,
                                    color: Colors.green,
                                    size: 40,
                                  ),
                                ),
                                SizedBox(
                                  width: 20,
                                ),
                                Container(
                                  decoration: BoxDecoration(
                                      color: Colors.green,
                                      border: Border.all(
                                        color: Colors.green,
                                      ),
                                      borderRadius:
                                          BorderRadius.all(Radius.circular(20))),
                                  child: InkWell(
                                    onTap: () async {
                                      const number =
                                          '08592119XXXX'; //set the number here
                                      bool res =
                                          await FlutterPhoneDirectCaller.callNumber(
                                              number);
                                    },
                                    child: Icon(
                                      Icons.call,
                                      color: Colors.white,
                                      size: 40,
                                    ),
                                  ),
                                )
                              ])),
                    ),
                    Divider(
                      color: Colors.black,
                      endIndent: 10,
                      indent: 10,
                    )
                    ]).expand((element) => element).toList()
                    ,
                  ],
                ),
              );
         
          }
        
        

        这里发生的事情很少:

        • users.map() 将对列表的每个元素运行提供的函数。

        • 由于您要创建两个元素的迷你列表 - GestureDetector 和 Divider,该函数将返回小部件列表

        • 您的地图功能的结果将是 [[GestureDetector, Divider], [GestureDetector, Divider],...]。这就是为什么我们运行 expand 来展平它 (https://api.dart.dev/stable/2.10.5/dart-core/Iterable/expand.html)

        • 最后,使用扩展运算符 (...) (...users.map( (u) =>) 将元素卸载到包含列表中。所以这个:

        child: ListView(
                  children: <Widget>[
              [GestureDetector, Divider, GestureDetector, Divider]]
        

        变成

        child: ListView(
                  children: <Widget>[
              GestureDetector, Divider, GestureDetector, Divider]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-01-21
          • 2020-07-13
          • 2021-03-21
          • 2022-01-13
          • 2022-01-24
          • 2020-05-18
          相关资源
          最近更新 更多