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

Flutter需求:下滑隐藏SliverAppBar,仅顶部可展开

实现自定义滚动交互的SliverAppBar

要实现你需要的滚动行为,我们可以通过ScrollController监听滚动方向与位置,结合SliverAppBar的属性动态调整,同时限制仅在滚动到顶部时允许展开AppBar。以下是完整实现代码:

import 'package:flutter/material.dart';

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

  @override
  State<TestScreen> createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen> {
  late ScrollController _scrollController;
  bool _showAppBar = true;
  bool _isAtTop = true;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController()
      ..addListener(_handleScroll);
  }

  void _handleScroll() {
    final currentPosition = _scrollController.position.pixels;
    final direction = _scrollController.position.userScrollDirection;

    // 更新是否处于页面顶部的状态
    setState(() {
      _isAtTop = currentPosition <= 0;
    });

    // 根据滚动方向控制AppBar显示/隐藏
    if (direction == ScrollDirection.reverse) {
      // 向下滚动,隐藏AppBar
      if (_showAppBar) {
        setState(() {
          _showAppBar = false;
        });
      }
    } else if (direction == ScrollDirection.forward) {
      // 向上滚动,显示非展开状态的AppBar
      if (!_showAppBar) {
        setState(() {
          _showAppBar = true;
        });
      }
    }
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: CustomScrollView(
        controller: _scrollController,
        slivers: [
          SliverAppBar(
            expandedHeight: _isAtTop ? 300 : kToolbarHeight,
            backgroundColor: Colors.white,
            floating: false,
            pinned: _showAppBar,
            centerTitle: true,
            title: const Text(
              "Show on scroll down without expanding",
              style: TextStyle(color: Colors.black),
            ),
            // 仅在顶部时显示展开状态的内容
            flexibleSpace: _isAtTop
                ? FlexibleSpaceBar(
                    background: Container(color: Colors.grey[200]),
                  )
                : null,
          ),
          // 列表项1
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(10),
                child: Container(color: Colors.red, height: 400),
              ),
            ),
          ),
          // 列表项2
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(10),
                child: Container(color: Colors.deepPurple[400], height: 400),
              ),
            ),
          ),
          // 列表项3
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(10),
                child: Container(color: Colors.deepPurple[400], height: 400),
              ),
            ),
          ),
          // 列表项4
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(10),
                child: Container(color: Colors.deepPurple[400], height: 400),
              ),
            ),
          ),
          // 列表项5
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(10),
                child: Container(color: Colors.deepPurple[400], height: 400),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

核心逻辑说明

  • 滚动监听:通过ScrollController实时获取滚动方向与当前位置,判断用户滚动动作和是否处于页面顶部。
  • AppBar状态控制:
    • 向下滚动时,设置_showAppBar = false,让AppBar完全隐藏。
    • 向上滚动时,设置_showAppBar = true,固定显示工具栏高度的AppBar,不会自动展开。
    • 仅当滚动到页面顶部时,才允许AppBar展开到设置的expandedHeight,并显示展开状态的内容。
  • 资源管理:在组件销毁时释放ScrollController,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:53:16