You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:使用SliverAppBar时Switch状态无法更新求助

问题分析与解决

你的问题核心在于自定义的_PinnedHeaderDelegate没有响应showAll状态的变化。因为SliverPersistentHeaderDelegate是独立对象,父组件调用setState更新showAll时,Delegate不会自动重建,导致内部Switch仍使用旧值,看起来状态没改变。

解决方案

需要做两个关键修改:

  • 将showAll作为参数传递给_PinnedHeaderDelegate,确保Delegate能获取最新状态
  • 重写Delegate的shouldRebuild方法,当showAll变化时返回true,触发Delegate重建

修正后的完整代码

class TransactionsPage extends StatefulWidget {
  const TransactionsPage({super.key});

  @override
  State<TransactionsPage> createState() => _TransactionsPageState();
}

class _TransactionsPageState extends State<TransactionsPage> {
  bool showAll = false;
  final List<int> numbers = [-1, 2, -3, 4, -5, 6];

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: CustomScrollView(
          slivers: [
            // SliverAppBar
            SliverAppBar(
              expandedHeight: 300,
              flexibleSpace: const FlexibleSpaceBar(
                title: Text('Transactions'),
              ),
              pinned: true,
              floating: true,
            ),

            SliverPersistentHeader(
              delegate: _PinnedHeaderDelegate(
                showAll: showAll,
                onToggle: (val) {
                  setState(() {
                    showAll = val;
                  });
                },
              ),
              pinned: true,
            ),

            // SliverList
            buildShowData(),
          ],
        ),
      ),
    );
  }

  Widget buildShowData() {
    List<int> data;
    if (showAll) {
      data = numbers;
    } else {
      data = numbers.where((element) => element > 0).toList();
    }
    return SliverList(
      delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
          final number = data[index];
          return Card(
            child: ListTile(
              title: Text(
                '$number',
                style: TextStyle(
                  color: number < 0 ? Colors.red : Colors.green,
                ),
              ),
            ),
          );
        },
        childCount: data.length,
      ),
    );
  }
}

// 修正后的Delegate实现
class _PinnedHeaderDelegate extends SliverPersistentHeaderDelegate {
  final bool showAll;
  final Function(bool) onToggle;

  _PinnedHeaderDelegate({required this.showAll, required this.onToggle});

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      height: 50,
      color: Colors.white,
      child: Row(
        children: [
          const Text('Show All Data'),
          Switch(
            value: showAll,
            onChanged: onToggle,
          ),
        ],
      ),
    );
  }

  @override
  double get maxExtent => 50;

  @override
  double get minExtent => 50;

  // 关键:当showAll变化时触发重建
  @override
  bool shouldRebuild(_PinnedHeaderDelegate oldDelegate) {
    return oldDelegate.showAll != showAll;
  }
}

关键修改点说明

  1. Delegate参数传递:把showAll和状态更新回调onToggle传入Delegate,确保内部能拿到最新状态并触发父组件的setState。
  2. shouldRebuild方法:对比新旧Delegate的showAll值,不同时返回true,通知Flutter重建PersistentHeader,同步Switch状态。
  3. 标题修正:将SliverAppBar的测试标题改为需求的Transactions。

修改后切换Switch时,showAll状态会正确更新,SliverAppBar标题、Switch状态和SliverList内容都会同步变化。

内容的提问来源于stack exchange,提问作者user22362195

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 04:22:12