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

Flutter实现滚动时固定行内组件至屏幕的布局方案问询

Flutter Windows/Web 布局实现方案

基础布局说明:顶部为红色头部区域,下方通过黑色分隔线连接左右两栏,左侧蓝色区域、右侧绿色区域,两者高度都可能超出屏幕。

你的需求核心是实现头部滚动消失+左侧区域固定自适应+右侧区域独立滚动,单一的SingleChildScrollView没法满足,推荐用NestedScrollView结合SliverAppBar来实现,下面是完整方案:

核心实现思路

  1. 用NestedScrollView协调头部滚动和内容区域的交互,实现头部折叠消失
  2. 监听头部展开状态,动态调整左侧蓝色区域的高度:头部可见时保持初始高度,头部收起后占满屏幕剩余空间
  3. 右侧绿色区域用独立滚动控制器,保证不受左侧布局影响,可自由滚动

完整代码

import 'package:flutter/material.dart';

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

  @override
  State<AdaptiveLayout> createState() => _AdaptiveLayoutState();
}

class _AdaptiveLayoutState extends State<AdaptiveLayout> {
  bool _isHeaderVisible = true;
  final ScrollController _rightScrollCtrl = ScrollController();

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

  @override
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height;
    return Scaffold(
      body: NestedScrollView(
        headerSliverBuilder: (context, innerScrolled) {
          return [
            SliverAppBar(
              pinned: true,
              expandedHeight: 150,
              toolbarHeight: 0,
              backgroundColor: Colors.transparent,
              flexibleSpace: FlexibleSpaceBar(
                background: _buildHeader(),
                collapseMode: CollapseMode.pin,
              ),
              // 监听头部展开状态
              leading: Builder(
                builder: (ctx) {
                  final appBar = SliverAppBar.of(ctx);
                  WidgetsBinding.instance.addPostFrameCallback((_) {
                    setState(() {
                      _isHeaderVisible = appBar.currentHeight == appBar.expandedHeight;
                    });
                  });
                  return const SizedBox.shrink();
                },
              ),
            ),
            SliverToBoxAdapter(
              child: Container(height: 5, color: Colors.black),
            ),
          ];
        },
        body: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 左侧蓝色区域:自适应高度
            Expanded(
              child: Container(
                color: Colors.blue,
                height: _isHeaderVisible ? 400 : screenHeight,
                child: _buildLeftContainer(),
              ),
            ),
            // 右侧绿色区域:独立滚动
            Expanded(
              child: SingleChildScrollView(
                controller: _rightScrollCtrl,
                child: _buildRightContainer(),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildHeader() {
    return Container(
      height: 150,
      color: Colors.red,
      alignment: Alignment.center,
      child: const Text('头部选择区域', style: TextStyle(color: Colors.white, fontSize: 20)),
    );
  }

  Widget _buildRightContainer() {
    return Container(
      height: 1000,
      color: Colors.green,
      alignment: Alignment.center,
      child: const Text('绿色滚动内容区', style: TextStyle(color: Colors.white, fontSize: 20)),
    );
  }

  Widget _buildLeftContainer() {
    // 替换为你的选择列表组件
    return ListView.builder(
      itemCount: 20,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text('选项 ${index + 1}'),
          tileColor: index % 2 == 0 ? Colors.blue[200] : Colors.blue[300],
        );
      },
    );
  }
}

关键细节解释

  • SliverAppBar设置pinned: true+toolbarHeight:0,实现头部滚动到底部后完全隐藏,不会留 toolbar 高度
  • 通过SliverAppBar.of(context)获取当前头部高度,判断是否完全展开,动态切换左侧区域高度
  • 右侧区域用独立SingleChildScrollView,确保滚动不受左侧布局干扰,适配任意高度内容
  • 针对Windows/Web平台,直接适配;窗口尺寸过小时,可通过MediaQuery.of(context).size.width判断,切换为移动端垂直布局

备选方案:手动滚动监听

如果不想用NestedScrollView,可以用SingleChildScrollView+ScrollController:

  1. 监听滚动偏移量,当偏移超过头部总高度(150+5)时,标记头部已隐藏
  2. 用Stack布局,将左侧蓝色区域设为Positioned,根据标记切换位置和高度
  3. 右侧区域放在Stack上层,保持滚动

但这种方式需要处理滚动同步、布局重绘等问题,不如NestedScrollView方案简洁稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:43:27