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

Flutter基于Sliver实现特定嵌套滚动布局的方案咨询

Flutter 复杂滚动行为实现方案

针对你提出的三个滚动阶段需求,结合sliver_tools库,下面是具体实现方案,核心是重构滚动结构消除嵌套冲突,同时实现粘性面板:

关键改动思路

  • 移除Content组件内部的SingleChildScrollView,将内容直接整合到根CustomScrollView中,实现滚动联动
  • 用SliverPinnedHeader实现红、绿面板的顶部固定
  • 标题部分保持原有结构,随滚动自然移出视口

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:sliver_tools/sliver_tools.dart';

Widget build(context) {
  return Stack(
    children: [
      Container(
        color: const Color(0xFF1A237E), // 替换为你的FPColors.primaryDarker
        height: 400,
        width: double.infinity,
        child: const Placeholder(), // 替换为你的SvgPicture
      ),
      CustomScrollView(
        slivers: [
          // 标题区域:随滚动移出视口
          const SliverToBoxAdapter(
            child: SizedBox(
              height: 370,
              child: Center(
                child: Text(
                  "Title",
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                    fontSize: 24,
                  ),
                ),
              ),
            ),
          ),
          // 红、绿面板区域:滚动到顶部后固定
          SliverPinnedHeader(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // 绿色面板(占3份宽度)
                  Expanded(
                    flex: 3,
                    child: Container(
                      decoration: BoxDecoration(
                        color: Colors.green,
                        borderRadius: BorderRadius.circular(8),
                      ),
                      padding: const EdgeInsets.all(16),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Row(
                            children: const [
                              Text('Sommaire'),
                              Spacer(),
                              Icon(Icons.search),
                            ],
                          ),
                          const SizedBox(height: 8),
                          const Column(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Text('Introduction'),
                              SizedBox(height: 8),
                              Text('Chapter 1'),
                              SizedBox(height: 8),
                              Text('Chapter 2'),
                              SizedBox(height: 8),
                              Text('Chapter 3'),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                  const SizedBox(width: 16),
                  // 红色面板(占1份宽度)
                  Expanded(
                    flex: 1,
                    child: Container(
                      decoration: const BoxDecoration(color: Colors.red),
                      height: double.infinity, // 随绿色面板高度自适应
                    ),
                  ),
                ],
              ),
            ),
          ),
          // 可滚动的内容区域(TabBar下方的文本)
          SliverToBoxAdapter(
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: Column(
                children: [
                  const TabBar(
                    tabs: [
                      Tab(text: 'Content', icon: Icon(Icons.article)),
                      Tab(text: 'Quiz', icon: Icon(Icons.quiz)),
                      Tab(text: 'Commentaire', icon: Icon(Icons.comment)),
                    ],
                    labelColor: Colors.black,
                    unselectedLabelColor: Colors.grey,
                  ),
                  const SizedBox(height: 8),
                  // 文本内容:直接作为根滚动的一部分
                  Text(
                    List.generate(10, (index) => '''
                    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
                    ''').join(' '),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    ],
  );
}

细节说明

  1. 初始滚动阶段:标题居中显示,红、绿面板随根滚动一起下移
  2. 标题移出阶段:当滚动距离超过标题高度(370)时,标题完全移出视口
  3. 面板固定阶段:红、绿面板通过SliverPinnedHeader固定在视口顶部,下方文本内容继续滚动
  4. 滚动联动解决:移除内部SingleChildScrollView,所有可滚动内容归属根CustomScrollView,彻底解决嵌套滚动不联动问题

如果需要TabBar切换不同内容,可将对应内容封装为Sliver组件,结合TabBarView和NestedScrollView的body部分扩展实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 09:41:00