Flutter GridView双向滚动问询:固定宽单元格横竖滚动实现需求
实现固定宽度单元格的双向滚动网格
要实现支持水平+垂直滚动、固定宽度单元格的30×30网格,你需要调整原有的CustomScrollView结构,增加水平滚动的外层容器,同时明确控制网格的总宽度来保证单元格尺寸固定。下面是两种可行的方案:
方案1:基于CustomScrollView(保留原Sliver结构)
这种方案延续你原有的SliverGrid实现,通过外层水平滚动容器扩展横向空间,适配你的现有代码习惯:
import 'dart:math'; import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'test', home: Scaffold( // 外层:水平滚动容器,处理横向滚动需求 body: SingleChildScrollView( scrollDirection: Axis.horizontal, child: SizedBox( // 固定总宽度:30列 × 单元格宽度(这里设为100,可按需调整) width: 30 * 100.0, // 内层:保留原有的垂直滚动CustomScrollView child: CustomScrollView( slivers: <Widget>[ SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 30, // 每行固定显示30个单元格 childAspectRatio: 0.5, // 宽高比=100/200,确保单元格高度为200 ), delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { // 生成30×30=900个单元格,满足最少行列要求 if (index >= 900) return null; return Container( width: 100.0, // 明确固定单元格宽度,避免自适应缩放 height: 200.0, color: _randomColor(index), ); }, ), ), ], ), ), ), ), ); } // 辅助函数:根据index生成固定颜色,避免滚动时颜色闪烁 Color _randomColor(int index) { final random = Random(index); return Color.fromRGBO( random.nextInt(256), random.nextInt(256), random.nextInt(256), 1.0, ); } }
方案2:基于GridView.builder(性能更优,适合大量数据)
如果单元格数量远超200,推荐使用GridView.builder——它支持懒加载,只会创建可见区域的单元格,能有效降低内存占用:
import 'dart:math'; import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'test', home: Scaffold( body: SingleChildScrollView( scrollDirection: Axis.horizontal, child: SizedBox( width: 30 * 100.0, // 30列×100宽度,保证单元格尺寸固定 child: GridView.builder( shrinkWrap: true, // 让GridView高度自适应内容,避免多余空白 physics: const AlwaysScrollableScrollPhysics(), // 保持垂直滚动能力 gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 30, childAspectRatio: 0.5, ), itemCount: 900, // 30×30=900个单元格 itemBuilder: (context, index) { return Container( width: 100.0, height: 200.0, color: _randomColor(index), ); }, ), ), ), ), ); } Color _randomColor(int index) { final random = Random(index); return Color.fromRGBO( random.nextInt(256), random.nextInt(256), random.nextInt(256), 1.0, ); } }
关键细节说明:
- 水平滚动实现:用
SingleChildScrollView设置scrollDirection: Axis.horizontal作为外层容器,让整个网格可以横向滑动。 - 固定单元格宽度:通过
SizedBox固定网格总宽度为30×单元格宽度,再配合crossAxisCount:30,确保每个单元格的宽度完全符合你设置的固定值,不会自适应缩放。 - 垂直滚动保持:内层的
CustomScrollView或GridView负责垂直滚动,保留原有的流畅滚动体验。 - 性能优化:如果单元格数量极大,优先选择
GridView.builder的懒加载模式,避免一次性创建所有单元格导致内存压力过大。
内容的提问来源于stack exchange,提问作者John Mcfetridge
相关产品推荐
相关产品推荐

