【问题标题】:Reload ListView from its child card in Flutter在 Flutter 中从子卡重新加载 ListView
【发布时间】:2020-05-21 06:57:13
【问题描述】:

我开发了一个应用程序,它有一个带有卡片的LisView。当用户点击ListView 中的项目时,我想重新加载/刷新整个ListView

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<String> itemsList = [
    "item0",
    "item1",
    "item2",
    "item3",
    "item4",
    "item5"
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: ListView.builder(
              itemCount: itemsList.length,
              itemBuilder: (context, index) {
                return ListItemCard(item: itemsList[index]);
              })),
    );
  }
}

class ListItemCard extends StatefulWidget {
  final String item;
  ListItemCard({this.item});
  _ListItemCardState createState() => _ListItemCardState();
}

class _ListItemCardState extends State<ListItemCard> {
  @override
  Widget build(BuildContext context) {
    return Card(
        elevation: 10,
        child: Padding(
            padding: EdgeInsets.all(0.0),
            child: Container(
                child:
              Align(
              alignment: Alignment.centerRight,
              child:Text(
                  widget.item,
                  style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                ),),
                width: 100,
                height: 100,
                color: Colors.red)));
  }
}

我正在使用 Flutter 1.17。我想在用户点击时选择一个项目。我的问题是在选择第二个项目时,应该取消选择已选择的项目。为此,我需要更新整个列表。我的点击事件处理程序位于 _ListItemCardState 类中,调用 setState() 只会更新我理解的特定卡片。

【问题讨论】:

  • 如何将 selectedItem 变量保持为类的全局变量并在卡片项目中使用 setState{} 更新它,并在 ternary(?:) 运算符中使用 selectedItem 变量来调节卡片中的卡片项目选择状态查看

标签: listview flutter dart


【解决方案1】:

为了解决这个问题,您可以在使用 ListView.builder 时为每张卡片指定一个唯一的 ID。 如,

第一张卡片的 id 为 0,

第二张卡片的 ID 为 1,

第三张卡片的 id 为 2, .. . 等等。

 body: Center(
      child: ListView.builder(
          itemCount: itemsList.length,
          itemBuilder: (context, index) {
            return ListItemCard(item: itemsList[index],id:index);
          })),
);

现在当卡片被点击时,你可以在 _MyHomePageState 类中有一个回调函数,可以从 _ListItemCardState 类中调用。并将卡片的 id 作为参数传递。

所以,你的主类知道点击了哪张卡片,因此使用 setState 重建 ui 并向 ListItemCard 传递一个布尔值,说明卡片是否被点击(真)或没有(假)。

child: ListView.builder(
          itemCount: itemsList.length,
          itemBuilder: (context, index) {
            bool amIclicked = false;
            if (index == clickedCardId) {
              amIclicked = true;
            }
            return ListItemCard(
              item: itemsList[index],
              id: index,
              callbackFunction: this.callbackFunction,
              amIClicked: amIclicked,
            );
          })

回调函数如下:

int clickedCardId = -1;
void callbackFunction(cardId) {
setState(() {
  clickedCardId = cardId;
});

}

整个代码供参考:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<String> itemsList = [
    "item0",
    "item1",
    "item2",
    "item3",
    "item4",
    "item5"
  ];
  int clickedCardId = -1;
  void callbackFunction(cardId) {
    setState(() {
      clickedCardId = cardId;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: ListView.builder(
              itemCount: itemsList.length,
              itemBuilder: (context, index) {
                bool amIclicked = false;
                if (index == clickedCardId) {
                  amIclicked = true;
                }
                return ListItemCard(
                  item: itemsList[index],
                  id: index,
                  callbackFunction: this.callbackFunction,
                  amIClicked: amIclicked,
                );
              })),
    );
  }
}

class ListItemCard extends StatefulWidget {
  final String item;
  int id;
  var callbackFunction;
  bool amIClicked;
  ListItemCard(
      {this.item, this.id, this.callbackFunction, this.amIClicked = false});
  _ListItemCardState createState() => _ListItemCardState(
      callbackFunction: callbackFunction, id: id, amIClicked: amIClicked);
}

class _ListItemCardState extends State<ListItemCard> {
  int id;
  var callbackFunction;
  bool amIClicked;
  _ListItemCardState({this.callbackFunction, this.id, this.amIClicked = false});
  //here you finally get "amIClicked" variable with either false or true
  //Based on that , you can show different colors to your card clicked and 
  //-non-clicked
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: callbackFunction(id),
      child: Card(
          elevation: 10,
          child: Padding(
              padding: EdgeInsets.all(0.0),
              child: Container(
                  child: Align(
                    alignment: Alignment.centerRight,
                    child: Text(
                      widget.item,
                      style:
                          TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                  ),
                  width: 100,
                  height: 100,
                  color: Colors.red))),
    );
  }
}

希望这会有所帮助!

【讨论】:

  • 谢谢。我认为会有一些直接的方法来执行此操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-27
  • 2020-09-13
  • 2014-05-18
  • 2020-03-26
  • 2019-03-21
  • 2018-09-05
相关资源
最近更新 更多