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,
            ),
          ],
        ),
      ),
    );
  }
}
相关推荐
程序员Ctrl喵17 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
前端不太难19 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡20 小时前
flutter列表中实现置顶动画
flutter
始持20 小时前
第十二讲 风格与主题统一
前端·flutter
始持20 小时前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持20 小时前
第十三讲 异步操作与异步构建
前端·flutter
新镜21 小时前
【Flutter】 视频视频源横向、竖向问题
flutter
黄林晴1 天前
Compose Multiplatform 1.10 发布:统一 Preview、Navigation 3、Hot Reload 三箭齐发
android·flutter
Swift社区1 天前
Flutter 应该按功能拆,还是按技术层拆?
flutter
肠胃炎1 天前
树形选择器组件封装
前端·flutter