Flutter(四):SingleChildScrollView、GridView

SingleChildScrollView、GridView 遇到的问题

以下代码会报错:

dart 复制代码
class GridViewPage extends StatefulWidget {
  const GridViewPage({super.key});

  @override
  State<GridViewPage> createState() => _GridViewPage();
}

class _GridViewPage extends State<GridViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView 布局')),
      body: SingleChildScrollView(
        child: GridView.count(
          crossAxisCount: 1,
          children: [
            Container(color: Colors.red),
            Container(color: Colors.green),
            Container(color: Colors.blue),
            Container(color: Colors.black),
            Container(color: Colors.grey),
          ],
        ),
      ),
    );
  }
}

修改方案一

存在问题:给定一个高度的方法虽然能解决报错问题,但是滚动区域会固定在所给高度内,无法自适应高度

dart 复制代码
class GridViewPage extends StatefulWidget {
  const GridViewPage({super.key});

  @override
  State<GridViewPage> createState() => _GridViewPage();
}

class _GridViewPage extends State<GridViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView 布局')),
      body: SizedBox(
        height: 500,
        child: GridView.count(
          crossAxisCount: 1,
          children: [
            Container(color: Colors.red),
            Container(color: Colors.green),
            Container(color: Colors.blue),
            Container(color: Colors.black),
            Container(color: Colors.grey),
          ],
        ),
      ),
    );
  }
}

修改方案二

存在问题:页面不能滚动

shrinkWrap: true: 自适应GridView高度

dart 复制代码
class GridViewPage extends StatefulWidget {
  const GridViewPage({super.key});

  @override
  State<GridViewPage> createState() => _GridViewPage();
}

class _GridViewPage extends State<GridViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView 布局')),
      body: SingleChildScrollView(
        child: GridView.count(
          crossAxisCount: 1,
          shrinkWrap: true,
          children: [
            Container(color: Colors.red),
            Container(color: Colors.green),
            Container(color: Colors.blue),
            Container(color: Colors.black),
            Container(color: Colors.grey),
          ],
        ),
      ),
    );
  }
}

解决页面不能滚动问题

physics: const NeverScrollableScrollPhysics(): 禁用GridView自带的滚动

dart 复制代码
class GridViewPage extends StatefulWidget {
  const GridViewPage({super.key});

  @override
  State<GridViewPage> createState() => _GridViewPage();
}

class _GridViewPage extends State<GridViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView 布局')),
      body: SingleChildScrollView(
        child: GridView.count(
          crossAxisCount: 1,
          shrinkWrap: true,
          physics: const NeverScrollableScrollPhysics(),
          children: [
            Container(color: Colors.red),
            Container(color: Colors.green),
            Container(color: Colors.blue),
            Container(color: Colors.black),
            Container(color: Colors.grey),
          ],
        ),
      ),
    );
  }
}

实现 GridView 布局

属性 描述
shrinkWrap 自适应宽高
scrollDirection 布局方向
childAspectRatio 主轴、交叉轴 比
mainAxisSpacing 主轴间距
crossAxisSpacing 交叉轴间距
crossAxisCount 交叉轴列数
maxCrossAxisExtent 交叉轴列最尺寸
dart 复制代码
import 'package:flutter/material.dart';

class TitleWidget extends StatelessWidget {
  final String title;

  const TitleWidget(this.title, {super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.fromLTRB(10, 5, 10, 5),
      padding: const EdgeInsets.only(left: 5),
      decoration: const BoxDecoration(
        border: Border(left: BorderSide(color: Colors.lightBlue, width: 5)),
      ),
      child: Text(title),
    );
  }
}

class ContainerWidget extends StatelessWidget {
  final Color color;
  final String title;

  const ContainerWidget({super.key, required this.color, required this.title});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: color,
        borderRadius: const BorderRadius.all(Radius.circular(5)),
      ),
      child: Center(child: Text(title)),
    );
  }
}

class GridViewPage extends StatefulWidget {
  const GridViewPage({super.key});

  @override
  State<GridViewPage> createState() => _GridViewPage();
}

class _GridViewPage extends State<GridViewPage> {
  List<ContainerWidget> containerWidgetList = const [
    ContainerWidget(color: Colors.red, title: 'RED'),
    ContainerWidget(color: Colors.orange, title: 'ORANGE'),
    ContainerWidget(color: Colors.yellow, title: 'YELLOW'),
    ContainerWidget(color: Colors.green, title: 'GREEN'),
    ContainerWidget(color: Colors.cyan, title: 'CYAN'),
    ContainerWidget(color: Colors.blue, title: 'BLUE'),
    ContainerWidget(color: Colors.purple, title: 'PURPLE'),
    ContainerWidget(color: Colors.grey, title: 'GREY'),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('GridView 布局')),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const TitleWidget('GridView.count'),
            SizedBox(
              height: 160,
              child: GridView.count(
                scrollDirection: Axis.horizontal,
                crossAxisCount: 1,
                padding: const EdgeInsets.only(left: 10, right: 10),
                crossAxisSpacing: 0,
                mainAxisSpacing: 10,
                childAspectRatio: 0.6,
                children: containerWidgetList,
              ),
            ),
            const TitleWidget('GridView.extent'),
            GridView.extent(
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              scrollDirection: Axis.vertical,
              maxCrossAxisExtent: 200,
              childAspectRatio: 0.8,
              padding: const EdgeInsets.only(left: 10, right: 10),
              mainAxisSpacing: 10,
              crossAxisSpacing: 10,
              children: containerWidgetList,
            ),
            const TitleWidget('SliverGridDelegateWithFixedCrossAxisCount'),
            SizedBox(
              height: 330,
              child: GridView(
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  crossAxisSpacing: 10,
                  mainAxisSpacing: 10,
                  childAspectRatio: 0.6,
                ),
                scrollDirection: Axis.horizontal,
                padding: const EdgeInsets.only(left: 10, right: 10),
                children: containerWidgetList,
              ),
            ),
            const TitleWidget('SliverGridDelegateWithMaxCrossAxisExtent'),
            GridView(
              gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200,
                childAspectRatio: 2,
                mainAxisSpacing: 10,
                crossAxisSpacing: 10,
              ),
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              scrollDirection: Axis.vertical,
              padding: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
              children: containerWidgetList,
            ),
          ],
        ),
      ),
    );
  }
}
相关推荐
梦想的颜色9 小时前
AI 时代小白 VibeCoding 做 APP:UniApp(含 Uni‑X)、Flutter 与 React Native+Expo全维度技术选型对比指南
flutter·react native·app·uniapp·vibecoding·unippx·app产品
坚果的博客12 小时前
Flutter-OH 3.44.9-dev 悄然上线|首个 OpenHarmony Canary 预览版上线
flutter
大龄秃头程序员12 小时前
Flutter 动画随笔:业务里真正高频的几类控件
flutter
天空之城--14 小时前
Android Flutter行业最新动态与实用参考(2026年8月第2周)
android·flutter
恋猫de小郭14 小时前
Flutter 3.47 发布,快来看看有什么更新吧
android·前端·flutter
大龄秃头程序员1 天前
一次 Flutter 动画 Demo 的整理与复盘
flutter
AlexMaybeBot1 天前
躺在沙发上开发 Openclaw 的移动端APP
前端·flutter
天空之城--1 天前
Android Flutter行业动态与学习参考(2026年8月)
android·flutter
FungLeo1 天前
Flutter Web token 存储陷阱:crypto.subtle 在非安全上下文失效排查实录
前端·安全·flutter
FungLeo1 天前
Flutter Web 中文字体困境与渲染器选择:CanvasKit vs HTML renderer 实战
前端·flutter·html