Flutter开发:实现社交APP滚动时顶部Story消失的列表布局
问题
正在克隆一款社交APP设计,已实现两个可正常运行的ListView:
- 水平滚动的UserStory(用户故事)列表
- 垂直滚动的UserPost(用户帖子)列表
需求是将二者整合到单个可滚动列表中,Story置于顶部,帖子在下方,滚动时Story可滑出视野,仅显示帖子。
当前遇到的问题:
- 用Column包裹两个组件时,滚动时Story固定在顶部无法滑出
- 尝试直接用ListView包裹body时出现大量错误,内容无法显示
解决方案
核心问题在于UserPost组件里用了Expanded包裹内部ListView,当把它放到外层ListView里时,Expanded会因为缺少父级约束而报错。同时需要把整个页面的滚动统一交给外层ListView,禁用内部垂直ListView的滚动能力。
修改步骤
- 调整UserPost组件:移除外层的Expanded,给内部ListView添加
shrinkWrap: true(让ListView根据内容自适应高度)和physics: const NeverScrollableScrollPhysics()(禁用自身滚动,交给外层ListView控制) - 替换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
相关产品推荐
相关产品推荐

