Flutter:如何让含PageView、ListView、GridView的Column整体垂直滚动
解决方案:让Column包含的组件实现整体垂直滚动
问题分析
你遇到的内容消失问题,核心原因是:
SingleChildScrollView的父级不能用Expanded,且其子组件中不能存在依赖父组件尺寸的Expanded(SingleChildScrollView本身没有固定高度,Expanded无法获取可用空间)GridView未设置shrinkWrap: true,即使禁用了滚动,它依然会试图占满剩余空间,导致布局冲突
关键修改点
- 移除
SingleChildScrollView外层的Expanded,直接将SingleChildScrollView作为body的子组件 - 去掉
PageView外层多余的Expanded(已经用SizedBox固定了高度) - 给
GridView添加两个属性:shrinkWrap: true:让GridView根据子项总高度收缩自身尺寸physics: NeverScrollableScrollPhysics():禁用GridView的独立垂直滚动
- 确保所有需要固定高度的组件(如PageView、水平ListView)都通过
SizedBox明确设置高度,避免布局歧义
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'listing.dart'; class TrackPage extends StatelessWidget { final _controller = PageController(initialPage: 0); TrackPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color.fromARGB(255, 224, 174, 113), appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, leading: BackButton( color: Colors.black, onPressed: () { Navigator.pop(context); }, ), centerTitle: true, title: const Text('Vouchers', style: TextStyle(color: Colors.black)), ), body: SingleChildScrollView( child: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), child: SizedBox( height: 200, // 移除多余的Expanded child: PageView( controller: _controller, children: [ Container( color: const Color(0xFFE2D240), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Image.asset('lib/images/x.png', width: 150), Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Center(child: Text('35% Off')), SizedBox(height: 20), Text('Super Cool') ], ), ], ), ), Container( color: Colors.red, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Image.asset('lib/images/x.png', width: 150), Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Center(child: Text('30% Off')), SizedBox(height: 20), Text('Super Cool') ], ), ], ), ), Container( color: Colors.green, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Image.asset('lib/images/x.png', width: 150), Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Center(child: Text('25% Off')), SizedBox(height: 20), Text('Super Cool') ], ), ], ), ), ], ), ), ), SmoothPageIndicator( controller: _controller, count: 3, effect: const WormEffect( dotColor: Colors.blueGrey, activeDotColor: Colors.blue, dotWidth: 8, dotHeight: 8, ), ), const SizedBox(height: 20), // Tags in list view SizedBox( height: 50, child: ListView( scrollDirection: Axis.horizontal, children: const [ Listing(text: 'Test'), Listing(text: 'Test'), Listing(text: 'Test'), Listing(text: 'Test', onTap: null), Listing(text: 'Test'), Listing(text: 'Test'), ], ), ), const SizedBox(height: 20), // 修改GridView的配置 GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: 6, padding: const EdgeInsets.symmetric(horizontal: 5), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 15, crossAxisSpacing: 15, ), itemBuilder: (context, index) { return Container( color: Colors.white, ); }, ), // Gallery pictures in grid view Image.asset('lib/images/x.png', width: 20), ], ), ), bottomNavigationBar: BottomNavigationBar( currentIndex: 0, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Test'), BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Test'), BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Test'), ], ), ); } }
验证效果
修改后:
- 整个页面可以垂直滚动,PageView和水平ListView保留各自的水平滚动功能
- GridView不再独立滚动,会随页面整体垂直移动
- 所有内容正常显示,没有布局错误
内容的提问来源于stack exchange,提问作者Im Onforum
相关产品推荐
相关产品推荐

