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

Flutter开发:实现社交APP滚动时顶部Story消失的列表布局

问题

正在克隆一款社交APP设计,已实现两个可正常运行的ListView:

  • 水平滚动的UserStory(用户故事)列表
  • 垂直滚动的UserPost(用户帖子)列表

需求是将二者整合到单个可滚动列表中,Story置于顶部,帖子在下方,滚动时Story可滑出视野,仅显示帖子。

当前遇到的问题:

  • 用Column包裹两个组件时,滚动时Story固定在顶部无法滑出
  • 尝试直接用ListView包裹body时出现大量错误,内容无法显示
解决方案

核心问题在于UserPost组件里用了Expanded包裹内部ListView,当把它放到外层ListView里时,Expanded会因为缺少父级约束而报错。同时需要把整个页面的滚动统一交给外层ListView,禁用内部垂直ListView的滚动能力。

修改步骤

  1. 调整UserPost组件:移除外层的Expanded,给内部ListView添加shrinkWrap: true(让ListView根据内容自适应高度)和physics: const NeverScrollableScrollPhysics()(禁用自身滚动,交给外层ListView控制)
  2. 替换HomePage的body布局:用ListView替代原来的Column,将UserStory和UserPost作为ListView的子元素

修改后的UserPost组件代码

class UserPost extends StatelessWidget {
  const UserPost({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      itemCount: 10,
      itemBuilder: (context, index) {
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
          child: Column(
            children: [
              ListTile(
                leading: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                      shape: BoxShape.circle,
                      color: Colors.grey.shade200
                  ),
                ),
                title: const Text("Ava Sadie"),
                subtitle: Text("Sylhet, Bangladesh", style: Theme.of(context).textTheme.labelSmall,),
                trailing: IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.more_horiz_outlined),),
              ),
              Container(
                width: double.infinity,
                height: 250,
                margin: const EdgeInsets.only(top: 5.0),
                decoration: BoxDecoration(
                  color: Colors.grey.shade200,
                  borderRadius: BorderRadius.circular(25.0),
                ),
              ),
              const SizedBox(height: 5),
              Row(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.favorite_outline,),),
                      Text("6.2k", style: Theme.of(context).textTheme.displaySmall,),
                    ],
                  ),

                  const SizedBox(width: 20,),

                  Row(
                    children: [
                      IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.messenger_outline,),),
                      Text("2.1k", style: Theme.of(context).textTheme.displaySmall,),
                    ],
                  ),

                  const SizedBox(width: 20,),

                  Row(
                    children: [
                      IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.bookmark_border_outlined),),
                      Text("3.5k", style: Theme.of(context).textTheme.displaySmall,),
                    ],
                  ),
                ],
              )
            ],
          ),
        );
      }
    );
  }
}

修改后的HomePage组件代码

import 'package:atlas/pages/widgets/user_post.dart';
import 'package:atlas/pages/widgets/user_story.dart';
import 'package:flutter/material.dart';

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        forceMaterialTransparency: true,
        leading: IconButton(
          padding: const EdgeInsets.symmetric(horizontal: 30.0),
          onPressed: () {},
          icon: const Icon(Icons.camera_alt_outlined),
        ),
        actions: [
          IconButton(
            padding: const EdgeInsets.symmetric(horizontal: 30.0),
            onPressed: () {},
            icon: const Icon(Icons.email_outlined),
          ),
        ],
      ),
      body: ListView(
        physics: const BouncingScrollPhysics(),
        children: const <Widget>[
          UserStory(),
          UserPost(),
        ],
      ),
    );
  }
}

补充说明

  • UserStory组件无需修改,它的水平ListView不受外层垂直滚动影响,依然可以正常横向滑动
  • 修改后整个页面由外层ListView控制垂直滚动,滚动时Story会随内容一起滑出视野,完全符合需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:30:06