Flutter交错网格视图指定位置如何显示不同字号文本

问题描述
当前使用flutter_staggered_grid_view 0.9.0版本,需要在交错网格视图的指定位置显示不同字号的文本:初始布局下索引为0、5、8、13...的位置文本字号设为19,其余位置文本字号为12。交错网格瓦片的布局有固定规则,每21个元素为一组重复该布局模式,即第二组(索引22至42区间)的字号设置规则和第一组完全一致,核心需求为大尺寸瓦片对应大字号文本、小尺寸瓦片对应小字号文本。
当前实现代码如下:
GridView.custom( padding: EdgeInsets.only(left: 24, right: 24, bottom: 24), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverQuiltedGridDelegate( crossAxisCount: 3, mainAxisSpacing: 8, crossAxisSpacing: 8, repeatPattern: QuiltedGridRepeatPattern.inverted, pattern: [ QuiltedGridTile(2, 2), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 3), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 3), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 3), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(2, 2), QuiltedGridTile(1, 1), ], ), childrenDelegate: SliverChildBuilderDelegate( (context, index) => SizedBox(), childCount: con.userPinsList.length, ), )
列表数据从API获取,为动态长度列表,需要可落地的实现方案。
实现方案
布局每21个元素为一个重复周期,直接通过取模运算匹配每个索引在周期内的位置,再判断对应位置的瓦片尺寸即可,适配任意长度的动态列表,不需要硬编码维护大字号索引列表:
- 提前将布局pattern提取为常量,避免每次build重复创建对象
- 构建item时,对当前index做
index % 布局pattern长度运算,得到该item在单个布局周期内的偏移位置 - 取出对应位置的
QuiltedGridTile配置,只要瓦片的主轴占比或跨轴占比大于1,就是大尺寸瓦片,对应设置19号字号,其余小尺寸瓦片统一设置12号字号
修改后的完整可运行代码示例:
// 提前提取布局pattern为常量,周期长度等于pattern.length = 21 const _gridPattern = [ QuiltedGridTile(2, 2), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 3), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 3), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 3), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(1, 1), QuiltedGridTile(2, 2), QuiltedGridTile(1, 1), ]; // 网格组件实现 GridView.custom( padding: const EdgeInsets.only(left: 24, right: 24, bottom: 24), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverQuiltedGridDelegate( crossAxisCount: 3, mainAxisSpacing: 8, crossAxisSpacing: 8, repeatPattern: QuiltedGridRepeatPattern.inverted, pattern: _gridPattern, ), childrenDelegate: SliverChildBuilderDelegate( (context, index) { // 计算当前索引在周期内的位置 final patternIndex = index % _gridPattern.length; // 取出对应位置的瓦片配置 final currentTile = _gridPattern[patternIndex]; // 判断是否为大尺寸瓦片 final isLargeTile = currentTile.crossAxisCellCount > 1 || currentTile.mainAxisCellCount > 1; // 匹配对应字号 final fontSize = isLargeTile ? 19.0 : 12.0; // 替换为你的实际业务item组件 return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: Colors.grey[200], ), alignment: Alignment.center, child: Text( con.userPinsList[index].title, style: TextStyle( fontSize: fontSize, fontWeight: isLargeTile ? FontWeight.w600 : FontWeight.normal, ), ), ); }, childCount: con.userPinsList.length, ), )
该方案后续如果调整布局pattern,字号匹配逻辑会自动适配,不需要额外修改判断代码,完全适配API返回的任意长度动态列表。
内容的提问来源于stack exchange,提问作者Vrusti Patel
相关产品推荐
相关产品推荐

