【问题标题】:Maintaining state in Listview.Builder() of Stateful widget (a progress bar) problem在有状态小部件(进度条)问题的 Listview.Builder() 中保持状态
【发布时间】:2019-10-24 23:12:24
【问题描述】:

我正在使用 listview.builder 创建一个列表视图。每个视图都是一张卡片,上面有一个按钮和一个进度条(见截图)

每张卡片都是一个有状态的小部件。当您按下按钮时,进度条会启动 5 秒计时器。当计时器结束时,对象会从 LinkedHashMap 中移除,这也会从屏幕上消失。如果在显示的列表中仅按下一个按钮,则此方法有效。如果按下一个按钮并在 2 秒后按下第二个或/和第三个按钮,则可以在所有三个按钮上看到进度条的动画,但是一旦第一个按钮从屏幕上消失,第二个和子序列就会出现重新绘制后,它们会处于松散状态,并且看起来好像它们的按钮从未被按下过。

我想要做的是,保持它们的状态独立并保持它们的动画独立。当一张卡片消失时,其他卡片会相应地向上/向下移动,但进度动画会继续保持当前状态,它们似乎会在未按下/原始状态下重新绘制自己。

我的卡代码如下:

class _DeliveryCardsViewState extends State<DeliveryCardsView> {
  double percentage = 1.0;
  bool countdownStarted = false;
  String buttonText = "CLAIM ORDER";

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
      child: Container(
        padding: EdgeInsets.only(top: 10.0, bottom: 10.0, left: 10.0, right: 10.0),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.all(Radius.circular(10.0)),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
              Text('#'+widget.delivery.uID),
              GestureDetector(
                onTap: () async {
                  if (!countdownStarted) {
                    countdownStarted = true;
                    setState(() {
                      buttonText = 'UNDO';
                    });
                    int j = 100;
                    while (j > 0) {
                      await Future.delayed(Duration(milliseconds: 50)); // Duration in seconds (50/10) = 5 seconds
                      j -= 1;
                      setState(() {
                        if (countdownStarted){
                          percentage = (j / 100).toDouble();
                        } else {
                          percentage = 1.0;
                        }
                      });
                      if (!countdownStarted){
                        setState(() {
                          buttonText = 'CLAIM ORDER';
                        });
                        break;
                      }
                    }
                    //Try to claim it now
                    if (countdownStarted) tryClaimOnFirebase();
                  } else {
                    countdownStarted = false;
                  }
                },
                child: Container(
                  padding: EdgeInsets.all(10.0),
                  child: Column(
                    children: <Widget>[
                      Text(buttonText,style: TextStyle(color: Colors.white),),
                      SizedBox(height: 5.0,),
                      LinearPercentIndicator(
                        width: 100.0,
                        lineHeight: 7.0,
                        percent: percentage,
                        backgroundColor: Colors.green,
                        progressColor: Colors.red,
                      ),
                    ],
                  ),
                  decoration: BoxDecoration(
                    color: mainGrey,
                    borderRadius: BorderRadius.all(Radius.circular(5.0)),
                  ),
                )
              ),
              ],
            ),
          ],
        ),
      ),
    );
  }

而我的Listview.builder代码如下:

return Container(color: Colors.grey[350],
      child: ListView.builder(
        key: UniqueKey(),
        itemCount: deliveriesAvailable.length,
        controller: _controller,
        scrollDirection: Axis.vertical,
        reverse: false,
        shrinkWrap: true,
        itemBuilder: (context,position){
          return GestureDetector(
            child: DeliveryCardsView(delivery: deliveriesAvailable.values.elementAt(position),),
            onTap: (){},
          );
    }),
    );

错误记录:

【问题讨论】:

  • 如何将j 声明为全局变量。每次状态更改时,它都会重建视图。所以每个字段都有初始值而不是当前值。您可以将其声明为全局字段或构造函数中的参数
  • 谢谢。但这会解决问题,因为每个对象都有自己的“j”计数器。

标签: flutter


【解决方案1】:

现在工作。 好吧,我想我了解发生了什么。整个有状态小部件正在被处置和重建,因此有状态小部件的“逻辑”“内部”也正在重置。我所做的如下:

1) 在“对象”中添加了几个额外的变量 2) 当视图再次构建时,它会检查这些变量,然后“恢复”它上次处理的状态,其中包括进度条计数器的值。

显然,为了实现这一点,整个逻辑从 onTap() 中取出并添加到一个新的异步方法中。

简单:)

【讨论】:

    猜你喜欢
    • 2021-09-29
    • 2021-09-15
    • 2021-05-19
    • 2020-04-15
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    相关资源
    最近更新 更多