【问题标题】:setState does not update the UIsetState 不更新 UI
【发布时间】:2021-02-19 10:06:41
【问题描述】:

我正在使用CustomScrollView 并尝试在SliverAppBar 操作中添加一个赞按钮,通过点击它,它的形状会发生变化。我正在setState 内部进行更改。但是尽管调用了 build 方法,但 UI 并未更新。

TextButton(
  onPressed: () {
     bool added = courseStore.addToUserFavoriteCourses(widget.courseDetails);
     added ?
       setState(() {
         iconData = Icons.favorite;
       }) :
       setState(() {
         iconData = Icons.favorite_border;
       });
  },
  child: Icon(
     iconData,
     size: 20,
     color: Colors.white,
  ),
)

【问题讨论】:

  • 你能打印吗(添加)。如果您使用 courseStore.addToUserFavoriteCourses 切换添加,我会感到困惑?另外,你看到了什么图标,Icons.favorite 或 favorite_border?
  • 我想查看整个代码,以便我能理解到底出了什么问题。因为你分享的当前代码没有任何问题。
  • @YoBo 每次用户点击图标时,“add”的值都应该改变。它正在按预期发生。这意味着如果我点击图标,将应用第一个 setState,下次按下它时,将应用第二个 setState。

标签: flutter setstate sliverappbar


【解决方案1】:

上面的代码还没有保存iconData的状态。

like/unlike 的状态需要up 移动到 parent 小部件范围内。然后可以在 children 中像 TextButton 一样在 below 中引用它的值。

当 TextButton 被重建(从不喜欢变为喜欢 & 返回)时,它可以使用在它上面持续存在的状态。

请注意下面iconData 如何存在于状态小部件中。此小部件旨在为其子级保存状态。

您可以将此代码复制粘贴到 Flutter/Dart 文件中进行测试:

import 'package:flutter/material.dart';

// ↓ Use this as your button
class StatefulButton extends StatefulWidget {
  final double size;
  final Color color;

  StatefulButton({this.size = 20, this.color = Colors.black});

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

class _StatefulButtonState extends State<StatefulButton> {
  IconData iconData = Icons.favorite_border;
  // ↑ Move your state up to here

  @override
  Widget build(BuildContext context) {
    return Center(
      child: TextButton(
        child: Icon(
          iconData,
          size: widget.size,
          color: widget.color,
        ),
        onPressed: toggleLike,
      ),
    );
  }

  void toggleLike() {
    setState(() {
      iconData = iconData == Icons.favorite ? Icons.favorite_border : Icons.favorite;
    });
  }
}


/// Just a container page for the example above
class TextButtonStatePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TextButtonState'),
      ),
      body: StatefulButton()
    );
  }
}

这是在 CustomScrollView 中使用上述 StatefulButton 的示例。我偷的 CustomScrollView 代码straight from the Flutter docs website。我所做的唯一编辑是将上面的 StatefulButton 添加到每个条子中,以显示它在单击时更改其状态。

/// Flutter code sample for CustomScrollView

import 'package:flutter/material.dart';
import 'text_button_state.dart';

/// This is the stateful widget that the main application instantiates.
class CustomScrollviewPage extends StatefulWidget {
  CustomScrollviewPage({Key key}) : super(key: key);

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

/// This is the private State class that goes with MyStatefulWidget.
class _CustomScrollviewPageState extends State<CustomScrollviewPage> {
  List<int> top = [];
  List<int> bottom = [0];

  @override
  Widget build(BuildContext context) {
    const Key centerKey = ValueKey('bottom-sliver-list');
    return Scaffold(
      appBar: AppBar(
        title: const Text('Press on the plus to add items above and below'),
        leading: IconButton(
          icon: const Icon(Icons.add),
          onPressed: () {
            setState(() {
              top.add(-top.length - 1);
              bottom.add(bottom.length);
            });
          },
        ),
      ),
      body: CustomScrollView(
        center: centerKey,
        slivers: <Widget>[
          SliverList(
            delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  color: Colors.blue[200 + top[index] % 4 * 100],
                  height: 100 + top[index] % 4 * 20.0,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                    Text('Item: ${top[index]}'),
                    StatefulButton() // ← STATEFUL BUTTON HERE
                  ],),
                );
              },
              childCount: top.length,
            ),
          ),
          SliverList(
            key: centerKey,
            delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  color: Colors.blue[200 + bottom[index] % 4 * 100],
                  height: 100 + bottom[index] % 4 * 20.0,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text('Item: ${bottom[index]}'),
                      StatefulButton()  // ← STATEFUL BUTTON HERE
                    ],
                  ),
                );
              },
              childCount: bottom.length,
            ),
          ),
        ],
      ),
    );
  }
}

【讨论】:

  • 感谢您的回答。我正在做你在示例中所做的事情。但它不起作用。我想也许 setState 没有应用于 CustomScrollView。
  • CustomScrollView 本身是一个StatelessWidget,所以它本身没有 setState 方法。但这不应影响滚动视图中的小部件如何保持其状态。我从 Flutter 文档网站中获取了 CustomScrollView 的示例,并将 StatefulButton 添加到每个 sliver 中。希望这会有所帮助。
猜你喜欢
  • 2019-07-03
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
相关资源
最近更新 更多