flutter架 构项目基础
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
/// ============================================================
|
||||
/// GridView 网格布局演示页
|
||||
///
|
||||
/// 一、两种使用方式:
|
||||
/// 1. 直接运行本页面:runApp(const MaterialApp(home: GridDemoPage()))
|
||||
/// 2. 复制某段核心代码到任意 Scaffold 的 body 中。
|
||||
///
|
||||
/// 二、三个常用构造:
|
||||
/// GridView.count : 固定列数,写死 children(一次性全部创建)
|
||||
/// GridView.builder : 懒加载,itemCount + itemBuilder,大量数据首选
|
||||
/// GridView.extent : 按"每项最大宽度"自适应列数(屏幕越宽列越多)
|
||||
///
|
||||
/// 三、核心参数:
|
||||
/// crossAxisCount : 列数(GridView.count 专用)
|
||||
/// maxCrossAxisExtent: 每项最大宽度(GridView.extent 专用)
|
||||
/// mainAxisSpacing : 主轴(上下行)间距
|
||||
/// crossAxisSpacing : 交叉轴(左右列)间距
|
||||
/// childAspectRatio : 每项 宽:高 比例,默认 1(正方形)
|
||||
///
|
||||
/// 四、高频坑:
|
||||
/// 1. GridView 放 Column 必须 SizedBox 定高或 Expanded(同 ListView);
|
||||
/// 2. childAspectRatio 太小(如 0.5)时文字会被挤压溢出,调比例或缩小字号。
|
||||
///
|
||||
/// 五、和 CustomScrollView(Sliver) 的本质区别(重点记忆):
|
||||
/// GridView = CustomScrollView + 1 个 SliverGrid(框架内部自动包的)。
|
||||
/// SDK 源码:GridView extends BoxScrollView,而 ScrollView.build()
|
||||
/// 返回的就是 CustomScrollView——所以 GridView 是"只有网格这一种内容"
|
||||
/// 的简化套餐,两者都是"单个滚动 + 懒加载"。
|
||||
/// · 页面只有网格 → body: GridView.builder(...) 直接用
|
||||
/// · 页面要混排 AppBar + 网格 + 列表 → CustomScrollView + slivers
|
||||
/// · 本页外层 SingleChildScrollView 只是"展示台":为并排演示 3 种构造,
|
||||
/// 内部塞的是固定高 GridView(嵌套滚动)。真实网格页别学这个外层!
|
||||
/// ============================================================
|
||||
class GridDemoPage extends StatelessWidget {
|
||||
const GridDemoPage({super.key});
|
||||
|
||||
// 网格配色(循环使用)
|
||||
static const List<Color> _colors = [
|
||||
Color(0xFF3B82F6), Color(0xFF8E6FE8), Color(0xFFF05252),
|
||||
Color(0xFFFF9800), Color(0xFF4CAF50), Color(0xFF00BCD4),
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('GridView 网格 Demo')),
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const _SectionTitle('Demo1:GridView.count 固定 3 列'),
|
||||
Text(
|
||||
'写死 children,一次性全创建,适合少量固定网格',
|
||||
style: TextStyle(fontSize: 13.sp, color: Color(0xFF888888)),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
SizedBox(
|
||||
height: 260.h,
|
||||
child: GridView.count(
|
||||
crossAxisCount: 3, // 列数
|
||||
mainAxisSpacing: 8.w, // 上下间距
|
||||
crossAxisSpacing: 8.w, // 左右间距
|
||||
childAspectRatio: 1, // 宽:高 = 1:1 正方形
|
||||
children: [
|
||||
for (int i = 0; i < 12; i++) _GridItem(index: i),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
|
||||
const _SectionTitle('Demo2:GridView.builder 懒加载'),
|
||||
Text(
|
||||
'itemCount: 100,只创建可见的格子,滚到哪建到哪',
|
||||
style: TextStyle(fontSize: 13.sp, color: Color(0xFF888888)),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
SizedBox(
|
||||
height: 260.h,
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4, // 4 列小格子
|
||||
mainAxisSpacing: 8.w,
|
||||
crossAxisSpacing: 8.w,
|
||||
childAspectRatio: 1,
|
||||
),
|
||||
itemCount: 100, // 假装 100 个格子
|
||||
itemBuilder: (context, index) => _GridItem(index: index),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
|
||||
const _SectionTitle('Demo3:GridView.extent 自适应列宽'),
|
||||
Text(
|
||||
'maxCrossAxisExtent: 120 → 每项最多 120 宽,屏幕越宽列数自动变多',
|
||||
style: TextStyle(fontSize: 13.sp, color: Color(0xFF888888)),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
SizedBox(
|
||||
height: 260.h,
|
||||
child: GridView.extent(
|
||||
maxCrossAxisExtent: 80.w, // 每项最多 80 宽
|
||||
mainAxisSpacing: 8.w,
|
||||
crossAxisSpacing: 8.w,
|
||||
childAspectRatio: 1,
|
||||
children: [
|
||||
for (int i = 0; i < 12; i++) _GridItem(index: i),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 单个网格项:彩色方块 + 序号
|
||||
class _GridItem extends StatelessWidget {
|
||||
const _GridItem({required this.index});
|
||||
|
||||
final int index;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: GridDemoPage._colors[index % GridDemoPage._colors.length],
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'$index',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 区块标题
|
||||
class _SectionTitle extends StatelessWidget {
|
||||
const _SectionTitle(this.title);
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 4.h),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF333333),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user