Flutter:如何实现单页面连续滚动的两个GridView
解决方案
要实现两个GridView整体滚动的效果,需要做以下关键修改:
核心修改点
- 用
SingleChildScrollView作为外层容器,替代原Column+Expanded结构,实现页面内容统一滚动 - 给每个
GridView.builder添加physics: NeverScrollableScrollPhysics(),禁用GridView自身滚动能力 - 保留
shrinkWrap: true,让GridView根据内容自动计算高度 - 优化网络请求:在
initState中初始化Future,避免每次build重复发起请求
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class GetUserData extends StatefulWidget { const GetUserData({super.key}); @override State<GetUserData> createState() => _GetUserDataState(); } class _GetUserDataState extends State<GetUserData> { late Future<List> _userDataFuture; Future<List> getUserData() async { String url = 'https://telugu-signaler.000webhostapp.com/get_user.php'; var response = await http.post(Uri.parse(url), body: ''); var allUserData = jsonDecode(response.body.toString()); return allUserData; } @override void initState() { super.initState(); // 初始化Future,避免重复请求 _userDataFuture = getUserData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Get User Data'), ), body: SafeArea( child: SingleChildScrollView( child: Column( children: <Widget>[ // 第一个crossAxisCount=1的GridView FutureBuilder<List<dynamic>>( future: _userDataFuture, builder: (context, snapshot) { if (snapshot.hasData) { return Padding( padding: const EdgeInsets.all(8.0), child: GridView.builder( shrinkWrap: true, // 禁用自身滚动,交给外层SingleChildScrollView physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 1, mainAxisExtent: 150.0, ), itemCount: snapshot.data!.length, itemBuilder: (context, index) { String userFirstName = snapshot.data![index]['user_first_name']; String userLastName = snapshot.data![index]['user_last_name']; return Column( children: [ Container( color: Colors.lightBlue, child: Text( 'First Name: $userFirstName', style: TextStyle(fontSize: 30), ), ), Container( color: Colors.lightBlue, child: Text( 'Last Name: $userLastName', style: TextStyle(fontSize: 30), ), ), ], ); }, ), ); } return const Center( child: CircularProgressIndicator(), ); }, ), // 第二个crossAxisCount=2的GridView FutureBuilder<List<dynamic>>( future: _userDataFuture, builder: (context, snapshot) { if (snapshot.hasData) { return Padding( padding: const EdgeInsets.all(8.0), child: GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisExtent: 150.0, ), itemCount: snapshot.data!.length, itemBuilder: (context, index) { String userDistrict = snapshot.data![index]['user_district']; String userState = snapshot.data![index]['user_state']; return Column( children: [ Container( color: Colors.lightGreen, child: Text( 'District: $userDistrict', style: TextStyle(fontSize: 30), ), ), Container( color: Colors.lightGreen, child: Text( 'State: $userState', style: TextStyle(fontSize: 30), ), ), ], ); }, ), ); } return const Center( child: CircularProgressIndicator(), ); }, ), ], ), ), ), ); } }
关键修改说明
- SingleChildScrollView:作为最外层滚动容器,包裹两个GridView所在的Column,实现整体滚动
- NeverScrollableScrollPhysics:禁用GridView自身的滚动功能,防止内外滚动冲突
- shrinkWrap: true:让GridView根据子元素的总高度确定自身高度,避免无限空间下无法计算尺寸的错误
- Future初始化优化:在initState中创建Future实例,避免每次build重建时重复发起网络请求,提升性能
内容的提问来源于stack exchange,提问作者Ajit Kumar Dutta
相关产品推荐
相关产品推荐

