Flutter GridView设置宽高

5,664 阅读1分钟

一、问题场景

我们在使用GridView的时候 child在列表中所占大小宽高是一致的,但是往往我们需求不是的。

二、解决方案

方案一 每个孩子的横轴与主轴范围的比率。 child的宽高比childAspectRatio

var itemWidth = (MediaQuery.of(context).size.width - 30) / 2;
var itemHeight = 255.0;
childAspectRatio = itemWidth / itemHeight;

 GridView.builder(
    padding: EdgeInsets.all(0),
    itemCount: itemList.length,
    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
      /// 纵轴间距
      mainAxisSpacing: 10.0,
      /// 横轴间距
      crossAxisSpacing: 10.0,
      /// 横轴元素个数
      crossAxisCount: 2,
      /// 宽高比
      childAspectRatio: childAspectRatio,
    ),
    itemBuilder: (context, index) =>
        GoodsItemWidget(itemList[index])),

方案二 继承 SliverGridDelegate,来重写它的布局

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class SliverGridDelegateWithFixedSize extends SliverGridDelegate {
  /// 宽
  final double width;

  /// 高
  final double height;

  /// 纵轴间距
  final double mainAxisSpacing;

  /// 横轴间距
  final double crossAxisSpacing;

  SliverGridDelegateWithFixedSize(this.width, this.height,
      {this.mainAxisSpacing = 0.0, this.crossAxisSpacing = 0.0});

  @override
  SliverGridLayout getLayout(SliverConstraints constraints) {
    final crossAxisCount = constraints.crossAxisExtent ~/ width;
    final crossAxisSpacing;
    if (this.crossAxisSpacing == 0.0) {
      crossAxisSpacing =
          (constraints.crossAxisExtent - width * crossAxisCount) /
              (crossAxisCount - 1);
    } else {
      crossAxisSpacing = this.crossAxisSpacing;
    }

    return SliverGridRegularTileLayout(
      crossAxisCount: crossAxisCount,
      mainAxisStride: height + mainAxisSpacing,
      crossAxisStride: width + crossAxisSpacing,
      childMainAxisExtent: height,
      childCrossAxisExtent: width,
      reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
    );
  }

  @override
  bool shouldRelayout(SliverGridDelegateWithFixedSize oldDelegate) {
    return oldDelegate.width != width ||
        oldDelegate.height != height ||
        oldDelegate.mainAxisSpacing != mainAxisSpacing;
  }
}

示例

GridView.builder(
    padding: EdgeInsets.all(0),
    itemCount: itemList.length,
    gridDelegate: SliverGridDelegateWithFixedSize(
      itemWidth,
      itemHeight,
      mainAxisSpacing: mainAxisSpacing,
    ),
    itemBuilder: (context, index) =>
        GoodsItemWidget(itemList[index])),