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

Flutter中点击SliverAppBar按钮实现SliverList动态最小化

解决方案

核心思路

  • 状态提升:将列表最小化的状态放在父组件_MyHomePageState中统一管理,解决跨组件状态同步问题
  • 动画实现:通过TweenAnimationBuilder实现列表项高度、透明度的平滑过渡效果
  • 事件透传:将最小化按钮的点击事件回调到父组件修改状态

完整修改代码

1. 修改主类代码

class _MyHomePageState extends State<MyHomePage> {
  // 控制列表是否最小化的状态
  bool _isListMinimized = false;

  // 切换最小化状态的方法
  void _toggleMinimizeList() {
    setState(() {
      _isListMinimized = !_isListMinimized;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          CustomTitleAppbar(
            title: 'Sliver List',
            // 传入点击回调
            onMinimizeTap: _toggleMinimizeList,
          ),
          // 传入最小化状态给列表组件
          CustomSliverListView(isMinimized: _isListMinimized),
        ],
      ),
    );
  }
}

2. 修改SliverAppBar组件代码

class CustomTitleAppbar extends StatefulWidget {
  const CustomTitleAppbar({
    Key? key,
    required this.title,
    // 新增点击回调参数
    required this.onMinimizeTap,
  }) : super(key: key);
  final String title;
  final VoidCallback onMinimizeTap;

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

class _CustomTitleAppbarState extends State<CustomTitleAppbar> {
  @override
  Widget build(BuildContext context) {
    return SliverAppBar(
      title: Text(widget.title),
      pinned: true,
      snap: false,
      backgroundColor: Colors.lightGreen,
      actions: [
        IconButton(
          onPressed: () {
            // 调用父组件传入的回调
            widget.onMinimizeTap();
          },
          icon: const Icon(Icons.minimize_rounded),
        ),
      ],
    );
  }
}

3. 修改SliverList组件代码

class CustomSliverListView extends StatelessWidget {
  const CustomSliverListView({
    Key? key,
    // 新增最小化状态参数
    required this.isMinimized,
  }) : super(key: key);
  final bool isMinimized;

  @override
  Widget build(BuildContext context) {
    return SliverList(
      delegate: SliverChildListDelegate(
        List.generate(5, (index) => TweenAnimationBuilder<double>(
          // 动画时长300毫秒,可自行调整
          duration: const Duration(milliseconds: 300),
          // 动画曲线,平滑效果
          curve: Curves.easeInOut,
          tween: Tween<double>(
            // 正常状态下列表项高度,默认ListTile高度约为70
            begin: 70,
            // 最小化状态下高度为0,完全隐藏
            end: isMinimized ? 0 : 70,
          ),
          builder: (context, height, child) {
            return SizedBox(
              height: height,
              // 配合透明度动画让过渡更自然
              child: Opacity(
                opacity: height / 70,
                child: child,
              ),
            );
          },
          child: ListTile(
            leading: CircleAvatar(
              child: Text('${index + 1}'),
              backgroundColor: Colors.lightGreen,
              foregroundColor: Colors.white,
            ),
            title: Text('Row ${index + 1}'),
            subtitle: Text('Subtitle ${index + 1}'),
            trailing: const Icon(Icons.star_border_outlined),
          ),
        )),
      ),
    );
  }
}

自定义调整说明

  • 如果不需要完全隐藏,只需要缩小列表项,可以把end: isMinimized ? 0 : 70里的0改成你想要的最小高度,比如30,同时可以调整子组件的显示样式,比如最小化时隐藏副标题
  • 动画时长可以修改Duration(milliseconds: 300)里的数值调整快慢
  • 动画效果可以修改curve参数,比如Curves.fastOutSlowIn等实现不同的动效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:21:02