• xuanxuan

    [!tip]-前言
    本人近期在自学flutter,文章纯手敲,自己有Obsidian整理,内容太多先更新一部分,后续会继续更新。
    接受各位佬批评,可自行修改错误或补充。
    鼓励佬友共建,每次可赏10 ldc。
    本文章如有问题,请联系我。

    Flutter UI

    ​Flutter widget 采用受React启发的现代框架构建。核心思想是用 widget 构建 UI。 Widget 根据当前配置和状态描述其视图应有的外观。当 widget 的状态改变时,widget 会重建其描述,框架将其与先前的描述进行 diff,以确定底层渲染树从一种状态过渡到另一种状态所需的最小变更。

    [!info] Flutter官方文档

    1. Flutter

    1.1 Flutter 是什么

    Flutter 是 Google 开发的开源 UI 框架,使用 Dart 语言编写。它的核心设计理念是一切皆 Widget。不同于其他跨平台框架依赖原生组件渲染,Flutter 自带高性能的渲染引擎 Skia(Impeller 在 iOS 上替代 Skia),直接在屏幕上绘制像素,从而实现真正的跨平台一致性。

    Flutter 的目标平台覆盖极广:iOS、Android、Web、Windows、macOS、Linux。一套代码可以在六个平台上运行,这是它最吸引人的地方。

    1.2 三层架构

    层级 |
    组成 |
    职责 |

    Framework |
    Dart 编写的 Widget 层、渲染层、动画层、手势层 |
    开发者直接交互的 API 层 |

    Engine |
    C/C++ 编写的 Skia/Impeller、Dart VM、文本渲染 |
    负责渲染、线程管理、平台通信 |

    Embedder |
    平台特定的代码(Java/Kotlin、Swift/Objective-C、C++) |
    将 Engine 嵌入到各个操作系统中 |

    1.3 热重载与热重启

    ​ Flutter 的开发体验很大程度上归功于热重载(Hot Reload)。它借助 Dart 的 JIT 编译器,在代码修改后毫秒级地将变更注入到运行中的应用,同时保持应用状态。```

    在终端中按 r 执行热重载(保留状态)

    按 R 执行热重启(重新初始化状态)

    按 q 退出

    ```> 热重载的局限

    热重载不会重新执行 main() 和 initState()。如果你修改了全局变量初始化、枚举定义、类的静态字段,或者遇到编译错误,热重载会失败,需要使用热重启。

    1.4 项目结构```
    my_app/
    ├── android/ # Android 原生工程
    ├── ios/ # iOS 原生工程
    ├── lib/ # Dart 代码(核心开发目录)
    │ └── main.dart # 应用入口
    ├── test/ # 单元测试和 Widget 测试
    ├── pubspec.yaml # 依赖管理和资源配置
    └── assets/ # 图片、字体等资源
    ``1.5 pubspec.yaml 详解``
    name: demo
    description: "A new Flutter project."
    publish_to: 'none'
    version: 0.1.0+1

    environment:
    sdk: ^3.12.2

    dependencies:
    flutter:
    sdk: flutter

    dev_dependencies:
    flutter_test:
    sdk: flutter
    flutter_lints: ^6.0.0

    flutter:
    uses-material-design: true
    ```2. Widget 基础

    2.1 Widget 了解

    在 Flutter 中,Widget 是构建 UI 的基本单位。按钮是 Widget,布局是 Widget,手势是 Widget,甚至是应用本身也是 Widget。Widget 描述的是 UI 的配置信息(即"长什么样"),而不是可变的 UI 实例。

    Widget 的核心特点:

    - 不可变(immutable):Widget 的字段都是 final 的

    - 轻量级:Widget 本身不直接绘制,只是配置描述

    - 可嵌套:通过组合多个 Widget 构建复杂 UI

    2.1.1 启动```
    void main() {
    runApp(const MainApp());
    }
    ```runApp() 函数接收给定的 Widget 并将其设为 widget 树的根。

    2.1.2 Material 组件

    ​ Flutter 提供多种 widget,帮助你构建符合 Material Design 的应用。 Material 应用以MaterialApp widget 开头,它在应用根节点构建多种实用 widget,包括Navigator——管理以字符串标识的 widget 栈,即「路由」。```
    class MainApp extends StatelessWidget {
    const MainApp({super.key});

    @override
    Widget build(BuildContext context) {
    return const MaterialApp(
    home: Scaffold(
    body: Center(
    child: Text('Hello World!'),
    ),
    ),
    );
    }
    }
    ```MainApp 是 根 widget,因为它是传入 runApp 的 widget。在这个 widget 内部,有一个 build 方法,它返回名为 MaterialApp 的另一个 widget。

    MaterialApp

    - title:用来展示窗口标题内容。

    - theme:用来展示整个应用的主题。

    • home:用来展示窗口的主题。```

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    title: 'My First App',
    theme: ThemeData(scaffoldBackgroundColor: Colors.deepPurple),
    home: Scaffold(
    body: Text("hello world"),
    ),
    );
    ```2.1.2 Scaffold 组件

    Scaffold 提供标准、灵活配置的页面骨架。

    属性 |
    作用 |

    appBar |
    页面顶部的应用栏,常用于显示标题、导航按钮和操作菜单 |

    body |
    页面主题内容,可以放置任何其他组件 |

    bottomNavigationBar |
    底部导航栏,方便用户在不同核心页面切换 |

    backgroundColor |
    设置整个Scaffold 的背景色 |

    flotingActionButtom |
    悬浮操作按钮,常用于触发页面主要动作 |

    … |
    其他 |```
    home: Scaffold(
    appBar: AppBar(
    title: Text('appbar'),
    centerTitle: true,
    ),
    body: Text("body"),
    bottomNavigationBar: BottomNavigationBar(
    items: [
    BottomNavigationBarItem(
    icon: Icon(Icons.home),
    label: 'Home',
    ),
    BottomNavigationBarItem(
    icon: Icon(Icons.search),
    label: 'Search',
    ),
    ],
    ),
    floatingActionButton: FloatingActionButton(
    onPressed: () {
    },
    child: Icon(Icons.add),
    ),
    ),
    ```2.1.3 两种核心 Widget 类型

    组件名称 |
    类型 |
    描述 |

    StatelessWidget |
    无状态组件 |
    StatelessWidget 一旦构建完成内部内容就不会再改变。它适用于纯展示型 UI,如文本、图标、静态图片等。 |

    StatefulWidget |
    有状态组件 |
    StatefulWidget 由两部分组成:Widget 本身(不可变)和 State(可变)。当状态变化时,调用 setState() 触发重建。 |

    (1)StatelessWidget 生命周期 |
    |
    |

    - StatelessWidget 非常简单:构造函数 → build()。没有额外的生命周期回调。

    • 当组件被创建或父组件状态变化导致需要重新构建时,build()会被调用。```

    class MainApp extends StatelessWidget {
    const MainApp({super.key});

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    home: Scaffold(
    body: Center(
    child: Text('Hello World!'),
    ),
    ),
    );
    }
    }
    ```> 总是使用 const 构造函数

    当 StatelessWidget 的所有字段都是编译期常量时,使用 const 构造函数可以让 Flutter 在重建时复用同一个 Widget 实例,大幅提升性能。Flutter 官方推荐==尽可能使用 const==。

    (2)StatefulWidget 生命周期

    生命周期阶段 |
    函数 |
    描述 |
    使用场景 |

    创建阶段 |
    createState() |
    widget初始化调用,创建state对象 |
    |

    创建阶段 |
    initState() |
    state对象插入widget树立刻执行,仅执行一次 |
    订阅流、初始化动画控制器、获取初始数据 |

    创建阶段 |
    didChangeDependencies() |
    initState()后立刻执行,当所依赖的InheritedsWidget更新时调用,可能多次 |
    主题、本地化 |

    构建阶段 |
    build() |
    构建UI,初始化或更新后多次调用 |
    |

    更新阶段 |
    didUpdateWidget() |
    父组件传入新配置时调用,用于比较新旧配置 |
    父 Widget 重建时,传入新配置 |

    销毁阶段 |
    deactivate() |
    当state对象从widget树暂时移除时调用 |
    |

    销毁阶段 |
    dispose() |
    当state对象从widget树永久移除时调用,释放资源,仅执行一次 |
    取消订阅、释放动画控制器、关闭资源 |```
    // 第一个类继承StatefulWidget,主要接受和定义最终参数,核心作用创建State对象
    class Counter extends StatefulWidget {
    const Counter({super.key});

    @override
    State<Counter> createState() => _CounterState();
    }

    // 第二个类继承State<第一个类类名>,负责管理可变数据和业务逻辑,并实现build方法来渲染视图。
    class _CounterState extends State<Counter> {
    int _count = 0;

    void _increment() {
    setState(() {
    _count++;
    });
    }

    @override
    Widget build(BuildContext context) {
    return ElevatedButton(
    onPressed: _increment,
    child: Text('Count: $_count'),
    );
    }
    }
    ``生命周期函数``
    补充
    ```2.2 布局组件

    Flutter 布局的核心机制是 widget。在 Flutter 中,几乎所有东西都是 widget — 甚至布局模型都是 widget。

    所有布局 widget 都具有以下任一项:

    - 一个 child 属性,如果它们只包含一个子项 — 例如 Center 和 Container

    - 一个 children 属性,如果它们包含多个子项 — 例如 Row、Column、ListView 和 Stack

    2.2.1 布局组件

    Container

    - 组合容器,整合尺寸(width/height)、装饰(decoration/color)、边距(padding/margin)、对齐(alignment)、变换(transform);

    - decoration属性:装饰器,可实现复杂背景效果,不能与color同时使用;

    - 与SizeBox区别:SizeBox只能设置尺寸,无其他属性。

    特性:

    - 不设宽高时,会尽可能占满父空间;

    - padding 内部留白,margin 外部留白;

    • 有 child 才会渲染内部内容。```

    body: Center(
    child: Container(
    width: 200, // 宽
    height: 100, // 高
    padding: EdgeInsets.all(10), // 内边距
    margin: EdgeInsets.symmetric(vertical: 20), // 外边距
    decoration: BoxDecoration(
    // 背景装饰
    color: Colors.blue,
    borderRadius: BorderRadius.circular(8),
    boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 4)],
    ),
    alignment: Alignment.center, // 内部子控件对齐
    transform: Matrix4.rotationZ(0.1), // 旋转/平移
    child: Text("Container"),
    ),
    ),

    
    - 将子组件在父容器空间内水平居中和垂直居中;
    
    - `Center = Align(alignment: Alignment.center)`,简化版居中;
    
    - 不能设置宽高,会尽可能占满父空间;```
     body: Center(
              child: Container(
                width: 200,
                height: 200,
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 4)],
                ),
                alignment: Alignment.center,
                child: Text("center"),
              ),
            ),
    • 精确控制子控件在父容器内的位置,可设置宽高因子。```

    body: Container(
    width: 300,
    height: 200,
    color: Colors.grey,
    child: Align(
    alignment: Alignment.bottomRight, // 右下角
    widthFactor: 0.5, // 自身宽度=父宽度*0.5
    heightFactor: 0.5, // 自身高度=父高度*0.5
    child: Text("右下角文字"),
    ),
    ),

    
    - 控制子控件的内边距```
    body: Container(
              color: Colors.amber,
              child: Padding(
                padding: EdgeInsets.all(20),
                child: Container(
                  color: Colors.blue,
                ),
              ),
            ),
    ```Column & Row
    
    **Column**
    
    - 线性布局,垂直排列子控件
    
    属性 |
    描述 |
    
    `mainAxisAlignment` |
    控制子控件在主轴(垂直方向)的排列方式,顶部对齐、居中。均匀分布 |
    
    `crossAxisAlignment` |
    控制子控件在交叉轴(水平方向)的排列方式,左/右对齐、拉伸填满 |
    
    `mainAxisSize` |
    决定Column在垂直方向上的尺寸策略。沾满所有空间(max),仅仅包裹子控件内容(min) |
    
    `children` |
    垂直排列子控件列表 |```
    body: Container(
              width: double.infinity,
              height: double.infinity,
              color: Colors.amber,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Container(
                    color: Colors.blue,
                    width: 200,
                    height: 200,
                    alignment: Alignment.center,
                    child: Text('111'),
                  ),
                  Container(
                    width: 200,
                    height: 200,
                    alignment: Alignment.center,
                    color: Colors.green,
                    child: Text('222'),
                  ),
                ],
              ),
            ),
    ```**Row**
    
    - 线性布局,水平排列子控件
    
    属性 |
    描述 |
    
    `mainAxisAlignment` |
    控制子控件在主轴(水平方向)的排列方式,顶部对齐、居中。均匀分布 |
    
    `crossAxisAlignment` |
    控制子控件在交叉轴(垂直方向)的排列方式,左/右对齐、拉伸填满 |
    
    `mainAxisSize` |
    决定Row在水平方向上的尺寸策略。沾满所有空间(max),仅仅包裹子控件内容(min) |
    
    `children` |
    垂直排列子控件列表 |```
    body: Container(
              width: double.infinity,
              height: double.infinity,
              color: Colors.amber,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Container(
                    color: Colors.blue,
                    width: 200,
                    height: 200,
                    alignment: Alignment.center,
                    child: Text('111'),
                  ),
                  Container(
                    width: 200,
                    height: 200,
                    alignment: Alignment.center,
                    color: Colors.green,
                    child: Text('222'),
                  ),
                ],
              ),
            ),
    ```Flex & Expended
    
    **Flex**
    
    - 弹性布局,允许沿着一个主轴(水平或垂直)排列子控件,灵活控制子控件在主轴上的尺寸比例和空间分配。相当于是`Row和Column`结合
    
    属性 |
    描述 |
    
    `direction` |
    主轴方向`Axis.horizontal`水平,`Axis.vertical垂直 |
    
    `mainAxisAlignment` |
    控制子控件在主轴(水平/垂直方向)的排列方式 |
    
    `crossAxisAlignment` |
    控制子控件在交叉轴(垂直/水平方向)的排列方式 |
    
    `mainAxisSize` |
    决定Row在水平方向上的尺寸策略。沾满所有空间(max),仅仅包裹子控件内容(min) |
    
    `children` |
    垂直排列子控件列表 |
    
    **Expended** |
    |
    
    - Expended/Flexible 作为`Flex`的子控件通过`flex`属性来分配`Flex组件`的空间。
    
    属性 |
    描述 |
    
    `flex` |
    分配子控件在`Flex组件`的空间 |
    
    `child` |
    子控件 |```
           body: Container(
              width: double.infinity,
              height: double.infinity,
              color: Colors.amber,
              child: Flex(
                direction: Axis.horizontal,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Expanded(
                    flex: 2,
                    child: Container(
                      alignment: Alignment.center,
                      color: Colors.red,
                      width: 200,
                      height: 200,
                      child: Text('111'),
                    ),
                  ),
                  Expanded(
                    flex: 1,
                    child: Container(
                      alignment: Alignment.center,
                      color: Colors.green,
                      width: 200,
                      height: 200,
                      child: Text('222'),
                    ),
                  ),
                ],
              ),
            ),

    - 流式布局,当子控件在主轴上排列不下时,它会自动换行(或换列)。

    - flex/row/column的内容超出不会自动换行

    属性 |
    描述 |

    direction |
    主轴方向Axis.horizontal水平,`Axis.vertical垂直 |

    spacing |
    控制子控件在主轴的间距 |

    runSpacing |
    控制子控件在交叉轴的间距 |

    alignment |
    控制子控件在主轴的对齐方式 |

    runAlignment |
    控制子控件在交叉轴的对齐方式 |```
    body: Container(
    width: double.infinity,
    height: double.infinity,
    color: Colors.amber,
    child: Wrap(
    direction: Axis.horizontal,
    spacing: 20,
    runSpacing: 20,
    alignment: WrapAlignment.spaceBetween,
    runAlignment: WrapAlignment.center,
    children: [
    Container(
    alignment: Alignment.center,
    color: Colors.red,
    width: 200,
    height: 200,
    child: Text('111'),
    ),
    Container(
    alignment: Alignment.center,
    width: 200,
    height: 200,
    color: Colors.green,
    child: Text('222'),
    ),
    ],
    ),
    ),
    ```Stack & Positioned

    Stack

    - 层叠布局,允许将多个子控件按Z轴方向进行叠加排序。

    属性 |
    描述 |

    alignment |
    控制非定位的子控件在Stack内的对齐方式,默认左上角 |

    fit |
    控制非定位的子控件如何适应Stack的尺寸 |

    clipBehavor |
    控制非定位的子控件在Stack超出部分的裁剪方式 |

    children |
    需要叠层子控件列表 |

    Positioned |
    |

    - 层叠布局,必须作为Stack的子控件,

    属性 |
    描述 |

    top/bottom/left/right |
    控制子控件在Stack的位置 |

    child |
    子控件 |```
    body: Container(
    width: double.infinity,
    height: double.infinity,
    color: Colors.amber,
    child: Stack(
    alignment: Alignment.center,
    children: [
    Container(
    alignment: Alignment.center,
    color: Colors.red,
    width: 200,
    height: 200,
    ),
    Positioned(
    top: 10,
    left: 10,
    child: Container(
    height: 100,
    width: 100,
    color: Colors.green
    ),
    ),
    Positioned(
    bottom: 10,
    right: 10,
    child: Container(
    height: 100,
    width: 100,
    color: Colors.blue
    ),
    ),
    ],
    ),
    ),
    ```2.2.2 滚动 & 列表 & 网格

    widget |
    特征 |
    使用场景 |

    SingleChildScrollView |
    让单个子控件可以用滚动,所有内容一次性渲染 |
    长表单,设置页、内容不固定但是总量不多的页面 |

    ListView |
    线性列表,通过builder可实现懒加载,性能优异 |
    聊天记录、新闻、常见单列滚动数据列表 |

    GridView |
    网格列表,支持懒加载,可固定列数 |
    图片墙、商品网格、应用图标列表 |

    CustomScrollView |
    复杂布局方案,通过组合多个Sliver组件实现滚动 |
    电商首页、社交app个人主页多个滚动紧密联动 |

    PageView |
    整页滚动,支持横向和纵向滚动 |
    应用引导页、图片轮播、书籍翻页 |

    SingleChildScrollView

    - 让单个子控件可以用滚动,所有内容一次性渲染

    属性 |
    描述 |

    controller |
    控制滚动,绑定一个ScrollController对象给controller对象,通过animateTo/jumpTo方法实现控制滚动 |

    scrollDirection |
    滚动方向,Axis.horizontal水平滚动,Axis.vertical垂直滚动 |```
    class _TestAppState extends State<TestApp> {
    ScrollController _scrollController = ScrollController();

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
    body: Stack(
    children: [
    SingleChildScrollView(
    controller: _scrollController,
    child: Column(
    children: List.generate(
    10,
    (index) => Container(
    height: 200,
    width: double.infinity,
    margin: EdgeInsets.all(10),
    color: Colors.red,
    alignment: Alignment.center,
    child: Text('$index'),
    ),
    ),
    ),
    ),

    Positioned(
    top: 10,
    right: 10,
    child: GestureDetector(
    onTap: () {
    _scrollController.animateTo(
    _scrollController.position.maxScrollExtent,
    duration: const Duration(milliseconds: 500),
    curve: Curves.ease,
    );
    },
    child: Container(
    height: 100,
    width: 100,
    alignment: Alignment.center,
    color: Colors.blue,
    child: Text('去底部'),
    ),
    ),
    ),

    Positioned(
    bottom: 10,
    right: 10,
    child: GestureDetector(
    onTap: () {
    _scrollController.animateTo(
    0,
    duration: const Duration(milliseconds: 500),
    curve: Curves.ease,
    );
    },
    child: Container(
    height: 100,
    width: 100,
    alignment: Alignment.center,
    color: Colors.blue,
    child: Text('去顶部'),
    ),
    ),
    ),
    ],
    ),
    ),
    );
    }
    }
    ```ListView

    - 线性列表,通过builder可实现懒加载,性能优异

    - 提供多种构造函数,如默认构造函数、ListView.builder、ListView.separated

    - 采用按需渲染懒加载,只构建当前可见区域的列表项,极大提高长列表性能

    属性 |
    描述 |

    controller |
    控制滚动,绑定一个ScrollController对象给controller对象,通过animateTo/jumpTo方法实现控制滚动 |

    scrollDirection |
    滚动方向,Axis.horizontal水平滚动,Axis.vertical垂直滚动 |

    itemCount |
    itemCount控制列表长度 |

    itemBuilder |
    itemBuilder回调函数按需构建列表项 |

    separatorbuilder |
    需在ListView.separated使用,为列表提供分割线 |```
    // ListView.builder
    class _TestAppState extends State<TestApp> {
    final ScrollController _scrollController = ScrollController();

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
    body: Stack(
    children: [
    ListView.builder(
    controller: _scrollController,
    itemCount: 10,
    itemBuilder: (context, index) => Container(
    height: 200,
    width: double.infinity,
    margin: EdgeInsets.all(10),
    color: Colors.red,
    alignment: Alignment.center,
    child: Text('$index'),
    ),
    ),
    ],
    ),
    ),
    );
    }
    }

    // ListView.separated
    class _TestAppState extends State<TestApp> {
    final ScrollController _scrollController = ScrollController();

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
    body: Stack(
    children: [
    ListView.separated(
    controller: _scrollController,
    itemCount: 10,
    separatorBuilder: (context, index) => Container(
    height: 10,
    width: double.infinity,
    color: Colors.grey,
    ),
    itemBuilder: (context, index) => Container(
    height: 200,
    width: double.infinity,
    color: Colors.red,
    margin: EdgeInsets.all(10),
    alignment: Alignment.center,
    child: Text('$index'),
    ),
    ),
    ],
    ),
    ),
    );
    }
    }
    ```GridView

    - 二维网格列表,支持懒加载,可固定列数

    - 提供多种构造函数,GridView.count(固定列数的网格布局)、GridView.extent(固定子项最大宽度/高度的网格布局)、GridView.builder(网格数量巨大或动态生成、需接收girdDelegate布局委托属性),默认构造函数使用起来复杂,很少用。

    属性 |
    描述 |

    scrollDirection |
    滚动方向,Axis.horizontal水平滚动,Axis.vertical垂直滚动 |

    controller |
    控制滚动,绑定一个ScrollController对象给controller对象,通过animateTo/jumpTo方法实现控制滚动 |

    mainAxisSpacing |
    主轴间距 |

    crossAxisSpacing |
    交叉轴间距 |

    crossAxisCount |
    需在GridView.count下使用,固定列数 |

    maxCrossAxisExtent |
    需在GridView.extent中使用,固定子项最大宽度/高度 |

    girdDelegate |
    crossAxisCount固定列数、mainAxisSpacing主轴间距、crossAxisSpacing交叉轴间距 |```
    // GridView.count
    body: GridView.count(
    crossAxisCount: 4,
    mainAxisSpacing: 10,
    crossAxisSpacing: 10,
    children: List.generate(
    20,
    (index) => Container(
    color: Colors.green,
    alignment: Alignment.center,
    child: Text('$index'),
    ),
    ),
    ),

    // GridView.extent
    body: GridView.extent(
    scrollDirection: Axis.horizontal,
    maxCrossAxisExtent: 200,
    mainAxisSpacing: 10,
    crossAxisSpacing: 10,
    children: List.generate(
    20,
    (index) => Container(
    color: Colors.green,
    alignment: Alignment.center,
    child: Text('$index'),
    ),
    ),
    ),

    // GridView.builder
    body: GridView.builder(
    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 4,
    mainAxisSpacing: 10,
    crossAxisSpacing: 10,
    ),
    itemCount: 100,
    itemBuilder: (context, index) {
    return Container(
    color: Colors.green,
    alignment: Alignment.center,
    child: Text('$index'),
    );
    },
    ),
    ```CustomScrollView

    - 复杂布局方案,组合多个滚动组件(列表、网格),通过组合多个Sliver组件实现滚动

    - sliver是描述可滚动视图内的一部分内容的子控件,它是滚动视图的切片。

    属性 |
    描述 |

    controller |
    控制滚动,绑定一个ScrollController对象给controller对象,通过animateTo/jumpTo方法实现控制滚动 |

    scrollDirection |
    滚动方向,Axis.horizontal水平滚动,Axis.vertical垂直滚动 |

    slivers |
    用于接受Sliver组件列表。 |

    slivers组件对应关系

    子控件名称 |
    对应组件 |
    作用 |

    SliverAppBar |
    AppBar |
    可折叠、悬浮、固定头部,嵌套在CustomScrollView |

    SliverPadding |
    Padding |
    给 Sliver 子组件增加内边距(不能直接包裹普通 Widget) |

    SliverToBoxAdapter |
    无直接对等组件 |
    将普通 RenderBox Widget(Container/Text 等)转为 Sliver,混合布局必备 |

    SlievrPersistentHeader |
    无直接对等组件 |
    持久吸顶头部,滚动时可以固定在顶部(自定义伸缩头部核心) |

    SliverList |
    ListView |
    列表懒加载,对应ListView.builder逻辑 |

    SliverGird |
    GridView |
    网格布局,对应GridView.builder |```
    class _TestAppState extends State<TestApp> {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
    body: CustomScrollView(
    slivers: [
    SliverAppBar(title: Text("123"), pinned: true),
    SliverToBoxAdapter(
    child: Container(height: 200.0, color: Colors.red),
    ),
    SliverList.builder(
    itemCount: 10,
    itemBuilder: (context, index) => Container(
    height: 100,
    width: double.infinity,
    color:Colors.blue,
    margin: EdgeInsets.all(10),
    child: Text("第"'$index'"个"),
    ),
    ),
    ],
    ),
    ),
    );
    }
    }
    ```PageView

    - 整页滚动,支持横向和纵向滚动,实现分页滚动视图。

    - 提供多种构造函数,默认构造函数、PageView.bulider(懒加载)

    属性 |
    描述 |

    controller |
    控制滚动,绑定一个ScrollController对象给controller对象,通过animateTo/jumpTo方法实现控制滚动 |

    scrollDirection |
    滚动方向,Axis.horizontal水平滚动,Axis.vertical垂直滚动 |```
    class _TestAppState extends State<TestApp> {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
    body: Container(
    height: 200,
    color: Colors.blue,
    child: PageView.builder(
    scrollDirection: Axis.horizontal,
    itemCount: 10,
    itemBuilder: (BuildContext context, int index) => Container(
    margin: EdgeInsets.all(10.0),
    color: Colors.red,
    alignment: Alignment.center,
    child: Text('第${(index+1)}页'),
    ),
    ),
    ),
    ),
    );
    }
    }

    
    > [!danger] ^-^启动
    主楼
  • qdd28

    万物皆widget,套又又套去,大概就是这个意思。

    #1

发表回复

登录后回复