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

Flutter如何实现固定Widget置于滚动视图中间层级不跟随滚动

Flutter 实现滚动视图中间层级固定元素方案

核心原理

将滚动内容拆分为上下两个独立的滚动区块,中间夹着完全固定的目标元素,两个滚动区块绑定同一个ScrollController实现滚动同步,即可让固定元素始终处在滚动内容的中间层级:下层滚动内容始终在固定元素下方滚动,上层滚动内容滚动时会覆盖在固定元素上方。

具体实现步骤

  1. 先定义全局共用的滚动控制器,提前计算好固定元素的位置、尺寸参数
  2. 使用Stack作为最外层容器,按「下层滚动区 → 固定元素 → 上层滚动区」的顺序排列子组件
  3. 上层滚动区顶部添加透明占位块,高度等于固定元素底部的Y轴坐标,保证上层初始内容在固定元素下方,滚动后再覆盖固定元素

示例代码

import 'package:flutter/material.dart';

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

  @override
  State<MiddleFixedDemo> createState() => _MiddleFixedDemoState();
}

class _MiddleFixedDemoState extends State<MiddleFixedDemo> {
  // 共用滚动控制器
  final ScrollController _scrollController = ScrollController();
  // 固定元素参数示例:垂直居中,高度80
  final double fixedElementTop = MediaQueryData.fromView(WidgetsBinding.instance.window).size.height / 2;
  final double fixedElementHeight = 80;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // 下层滚动区:内容始终在固定元素下方
          SingleChildScrollView(
            controller: _scrollController,
            child: Column(
              children: List.generate(10, (index) => Container(
                height: 200,
                color: Colors.primaries[index % Colors.primaries.length].withOpacity(0.7),
                margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                child: Center(child: Text('下层内容 $index', style: const TextStyle(fontSize: 24))),
              )),
            ),
          ),
          // 中间层:固定的品牌文本,位置完全固定不参与滚动
          Positioned(
            top: fixedElementTop,
            left: 0,
            right: 0,
            height: fixedElementHeight,
            child: const Center(
              child: Text(
                'DYNAMIC STUDIOS',
                style: TextStyle(
                  fontSize: 48,
                  fontWeight: FontWeight.bold,
                  color: Colors.black,
                ),
              ),
            ),
          ),
          // 上层滚动区:内容滚动后会覆盖在固定元素上方
          SingleChildScrollView(
            controller: _scrollController,
            child: Column(
              children: [
                // 顶部透明占位:高度等于固定元素底部坐标,初始状态完全透露出下方的固定元素和下层内容
                SizedBox(height: fixedElementTop + fixedElementHeight),
                ...List.generate(10, (index) => Container(
                  height: 200,
                  color: Colors.primaries[(index + 5) % Colors.primaries.length].withOpacity(0.7),
                  margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                  child: Center(child: Text('上层内容 $index', style: const TextStyle(fontSize: 24, color: Colors.white))),
                )),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

注意事项

  • 如果需要更复杂的滚动效果(比如吸顶、视差),可以把SingleChildScrollView替换为CustomScrollView,搭配Sliver组件实现,核心分层逻辑不变
  • 如果固定元素的位置不是静态的,可以通过LayoutBuilder动态计算位置后再赋值给上层滚动区的占位高度
  • 滚动内容高度超过屏幕高度时,两个滚动区的滚动偏移会完全同步,不会出现错位问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 19:54:03