目录

Flutter -- 基础组件MaterialApp

特性:

常见属性:

基础组件 - Scaffold组件

总结:

Flutter自定义组件 - 无状态组件和有状态组件

定义:

分类:

无状态组件 - StatelessWidget

定义:

要点:

场景:

有状态组件 - StatefulWidget

定义:

实现1:

实现2:

要点:

总结:

快捷键创建组件:

组件生命周期 - 无状态组件

组件生命周期 - 有状态组件

总结:

事件 - 点击事件GestureDetector

事件 - 组件点击事件

状态更新 - setState

语法:

案例:

布局组件:

基础容器 - Container

基础容器 - Center - 居中组件

基础容器 - Align - 对齐组件

基础组件 - Padding - 内边距组件

线性布局 - Column.

作用:

线性布局 - Row

作用:

弹性布局 - Flex

作用:

子组件:

弹性布局 - Flex/Expanded/Flexible

Flex实例:

流失布局 - Wrap

作用:

场景:

层叠布局 - Stack/Positioned

作用:

搭档:

文本组件 - Text

作用:

文本组件 - Text/TextSpan

图片组件 - Image

作用:

图片分类:

步骤:

Image.network 网络图片

文本输入组件 - TextField

作用:

常用滚动组件

常用滚动组件 - SingleChildScrollView

控制滚动 - SingleChildScrollView

常用滚动组件 - ListView

ListView - builder模式

ListView - separate模式

常用滚动组件 - GridView

自定义滚动容器 - CustomScrollView

整页滚动容器 - PageView


Flutter -- 基础组件MaterialApp
特性:

整个应用被MaterialApp包裹,方便对整个应用进行整体设计

常见属性:
  • title:用来展示窗口的标题内容
  • theme:用来设置整个应用的主题
  • home:用来展示窗口的主体内容
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MaterialApp(
    title: 'Flutter Demo',
    theme: ThemeData(scaffoldBackgroundColor: Colors.blue),
    home: Scaffold(),
  ));
}
基础组件 - Scaffold组件

Scaffold:用于构建Material Design风格页面的核心布局组件,提供标准,灵活配置的页面骨架

属性

主要作用说明

appBar

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

body

页面的主要内容区域,可以放置任何其他组件,是页面的核心

bottomNavigationBar

底部导航栏,方便用户在不同核心功能页面间切换

backgroundColor

设置整个 Scaffold 的背景颜色

floatingActionButton

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

...

其他

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MaterialApp(
    title: 'Flutter Demo',
    // theme: ThemeData(scaffoldBackgroundColor: Colors.blue),
    home: Scaffold(
      appBar: AppBar(
        title: Center(
          child: Text("头部区域"),
        ),
      ),
      body: Container(
        child: Center(
          child: Text("中部区域"),
        ),
      ),
      bottomNavigationBar: Container(
        height: 80.3,
        child: Center(
          child: Text("底部区域"),
        ),
      ),
    ),
  ));
}
总结:
  • MaterialApp包裹整个应用形成统一的Material Design风格
  • Scoffold组件可以快速搭建页面骨架,如appBar,body,bottomNavigationBar等
  • Container用来作为容器,设置高度(height),child用来存放子组件
  • Text是用来显示文本的组件
Flutter自定义组件 - 无状态组件和有状态组件
定义:

根据自己的特点的需求创建自己的widget

分类:
  • 无状态组件
  • 有状态组件

特性

StatelessWidget(无状态)

StatefulWidget(有状态)

核心特征

一旦创建,内部状态不可变

持有可在其生命周期内改变的状态

使用场景

静态内容展示,外观仅由配置参数决定

交互式组件,如计数器、可切换开关、表单输入框

生命周期

相对简单,主要是构建(build)

更为复杂,包含状态创建、更新和销毁

代码结构

单个类

两个关联的类:Widget本身和单独的State类

无状态组件 - StatelessWidget
定义:

创建一个新的类,继承StatelessWidget类并实现build方法

要点:

build返回一个Widget

场景:

纯展示型组件,没有用户交互操作

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter初体验-无状态组件",
      home: Scaffold(
          appBar: AppBar(
            title: Text("头部区域"),
          ),
          body: Container(
            child: Center(
              child: Text("中部区域"),
            ),
          ),
          bottomNavigationBar: Container(
            height: 80,
            child: Center(
              child: Text("底部区域"),
            ),
          )),
    );
  }
}
有状态组件 - StatefulWidget
定义:

有状态组件是构建动态交互界面的核心,能够管理变化的内部状态,当状态改变时,组件会更新显示内容

实现1:

创建两个类,第一个类继承StatefulWidget类,主要接收和定义最终参数,核心作用是创建State对象

实现2:

第二个类继承State<第一个类名>,负责管理所有可变的数据和业务逻辑,并实现build构建方法

要点:

build方法需要返回一Widget

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

// 第一个类 有状态组件
class MainPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MainPageState();
  }
}

// 第二个类 内部类 负责管理数据 处理业务逻辑 并且渲染视图
class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter初体验-有状态组件",
      home: Scaffold(
          appBar: AppBar(
            title: Text("头部区域"),
          ),
          body: Container(
            child: Center(
              child: Text("中部区域"),
            ),
          ),
          bottomNavigationBar: Container(
            height: 80,
            child: Center(
              child: Text("底部区域"),
            ),
          )),
    );
  }
}
总结:

快捷键创建组件:
  • stl - 无状态组件
  • stf - 有状态组件
组件生命周期 - 无状态组件
  • 无状态组件 - 唯一阶段
  • 当组件被创建或父组件状态变化导致其重新构建时,build方法会被重新调用

build方法会被重新执行

组件生命周期 - 有状态组件
  • 创建阶段
  • 更新阶段
  • 销毁阶段

生命周期阶段

函数名

调用时机与核心任务

创建阶段

createState()

Widget初始化调用,创建State对象

initState()

State对象插入Widget树立刻执行,仅执行一次

didChangeDependencies()

initState后立刻执行,当所依赖的InheritedWidget更新时调用,可能多次

构建与更新阶段

build()

构建UI方法,初始化或更新后多次调用

didUpdateWidget()

父组件传入新配置时调用,用于比较新旧配置

销毁阶段

deactivate()

当State对象从树中暂时移除时调用

dispose()

当State对象被永久移除时调用,释放资源,仅执行一次

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  State<MainPage> createState() {
    print("createState阶段");
    return _MainPageState();
  }
}

class _MainPageState extends State<MainPage> {
  @override
  void initState() {
    print("initState阶段执行");
    // TODO: implement initState
    super.initState();
  }
  
  // didChangeDependencies
  @override
  void didChangeDependencies() {
    print("didChangeDependence");
    super.didChangeDependencies();
  }
  
  // didUpdateWidget
  @override
  void didUpdateWidget(covariant MainPage oldWidget) {
    print("didUpdateWidget阶段执行");
    super.didUpdateWidget(oldWidget);
  }
  
  // deactivate
  @override
  void deactivate() {
    print("deactivatet阶段执行");
    super.deactivate();
  }
  
  // deactivate
  @override
  void dispose() {
    print("dispose阶段执行");
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    print("build阶段");
    return  Container(
      child: null,
    );
  }
}
总结:
  • 无状态组件 - build
  • 有状态组件(创建阶段):createState -> initState -> didChangeDependencies -> build
  • 有状态组件(更新阶段):didUpdateWidget -> build
  • 有状态组件(销毁阶段):deactivate -> dispose
  • 执行一次函数:createState,initState,dispose
  • inheritedWidget:专门用于在Widget树中自顶向下高效地共享数据,顶层组件提供数据,子孙节点直接获取
事件 - 点击事件GestureDetector
  • 事件:各种动作
  • 点击事件:当点击某个元素触发地动作
  • 常规方案:GestureDetector是Flutter常用,功能最丰富的手势检测组件
  • 方法:使用GestureDetector包裹被点击的元素,传入onTab方法
body: Container(
            child: Center(
              child: GestureDetector(
                onDoubleTap: () => print("双击了该区域"),
                // 点击事件
                onTap: () => print("点击了该区域"),
                child: Text("中部区域"),
              ),
            ),
          ),
事件 - 组件点击事件

组件:Flutter提供了多种方式为组件添加点击交互

组件类别

核心组件

主要特点/使用场景

专用按钮组件

ElevatedButton、TextButton、OutlineButton、FloatingActionButton

内置点击动画和样式,通过 onPressed 参数处理点击逻辑

视觉反馈组件

InkWell

提供点击事件(onTap),有 Material Design 风格的水纹扩散效果

其他交互组件

IconButton、Switch、Checkbox

具有特定功能的交互式控件,支持点击事件(onPressed)

 body: Container(
            child: Center(
              child: TextButton(onPressed: () {
                print("按钮的点击事件");
              }, child: Text("按钮"))
            ),
          ),
状态更新 - setState
语法:

数据的变化更新UI视图,需要执行setState方法,setState方法会造成build的重新执行

案例:

实现一个计数器案列

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

// 有状态组件
class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Center(
        child: Row(
          children: [
            TextButton(
                onPressed: () {
                  setState(() {
                    count -= 1;
                  });
                },
                child: Text("减")),
            Text(count.toString()),
            TextButton(
                onPressed: () {
                  setState(() {
                    count += 1;
                  });
                },
                child: Text("加")),
          ],
        ),
      )),
    );
  }
}
布局组件:

基础容器 - Container

定义:

Container是功能丰富的布局组件,是一个多功能组合容器

尺寸控制:
可通过多种方式定义大小

优先级:

明确宽高 > constraints约束 > 父组件约束 > 自适应大小

装饰系统:

通过decoration属性实现视觉效果,但和color属性互斥

布局控制:
提供内外边距和对齐方式

可选变化:

支持绘制时进行矩阵变化。

常见属性:

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Center(
        child: Container(
          alignment: Alignment.center,
          margin: EdgeInsets.all(50),
          width: 200,
          height: 200,
          transform:Matrix4.rotationZ(0.05), // 弧度 而非角度
          // color: Colors.blue,
          decoration: BoxDecoration(
              border: Border.all(width: 3,color: Colors.yellow),
              color: Colors.blue, borderRadius: BorderRadius.circular(15)),
              child: Text(
                "Hello ,Container",
                style: TextStyle(color: Colors.white, fontSize: 20),
              ),
        ),
      )),
    );
  }
}
基础容器 - Center - 居中组件

Center:将其子组件在父容器的空间内进行水平和垂直方向上的居中排列

应用场景:页面内容整体居中,如登陆表单

注意事项:Cneter不能设置宽高,Center的最终大小取决于其父组件传递给它的约束,Center会向它的父组件申请可能大的空间

实现固定高度且居中的组件:Center去包裹一个具有固定宽高的子组件。Container/SizeBox

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Center代码示例"),
          ),
          body: Center(
            child:Container(
              alignment: Alignment.center,
              width: 100,
              height: 100,
              decoration: BoxDecoration(
                color: Colors.blue
              ),
              child: Text("居中内容",style: TextStyle(color: Colors.white)),
            )
          )),
    );
  }
}
基础容器 - Align - 对齐组件

作用:精确控制其子组件在父容器空间内的对齐位置

alignment(对齐方式):子组件在父容器内的对齐方式

widthFactor(宽度因子):Align的宽度将是子组件宽度乘以该因子

heightFactor(高度因子):Align的高度将是子组件高度乘以该因子

与Center组件的区别:Center是Align的一个特例

使用场景:当需要将一个组件放置在父容器的特定角落,Align是理想选择。

动态尺寸:通过widthFactor和heightFactor,可以创建出与子组件大小成比例的容器,动态布局很有用。

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Align代码示例"),
          ),
          body: Align(
            alignment: Alignment.center,
            widthFactor: 1,
            heightFactor: 1,
            child: Icon(Icons.star, size: 120, color: Colors.amber),
          )),
    );
  }
}
基础组件 - Padding - 内边距组件

作用:为其子组件添加内边距

线性布局 - Column.

Column不支持宽高,是子组件撑开的

作用:

用于垂直排列其子组件的核心布局容器

  • 设置主轴

  • 交叉轴

  • 使用场景:

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Align代码示例"),
          ),
          body: Container(
            width: double.infinity, // 正无穷大
            height: double.infinity, // 正无穷大
            decoration: BoxDecoration(color: Colors.amber),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Container(
                  width: 100,
                  height: 100,
                  margin: EdgeInsets.only(bottom: 10),
                  color: Colors.blue,
                ),
                Container(
                  width: 100,
                  height: 100,
                  margin: EdgeInsets.only(bottom: 10),
                  color: Colors.blue,
                ),
                Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                )
              ],
            ),
          )),
    );
  }
}
线性布局 - Row
作用:

用于水平排列其子组件的核心布局容器

弹性布局 - Flex
作用:

允许一个主轴(水平或垂直)排列其子组件,灵活控制这些子组件在主轴上的尺寸比列和空间分配

子组件:

Flex的子组件常用Expanded或Flexible来控制空间分配

弹性布局 - Flex/Expanded/Flexible
  1. Expanded/flexible作为Flex的子组件通过flex属性来分配Flex组件空间
Flex(
	direction: Axis.horizontal,
	children: [
		Expanded(
			flex: 2,
			child: Container(
				width: 100,
				height: 100,
				color: Colors.blue,
			)),
		Expanded(
			flex: 1,
			child: Container(
				width: 100,
				height: 100,
				color: Colors.red,
			)),
		Expanded(
			flex:1,
			child: Container(
				width: 100,
				height: 100,
				color: Colors.green,
			))
	],
),

常用Expanded组件

  1. Flex布局受其父组件传递的约束影。确保父组件提供了适当的布局约束
  2. Expanded与Flexible的区别:Expanded强制子组件填满所有剩余空间,Flexible根据自身大小调整,不强制沾满空间。
Flex实例:

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Flex代码示例"),
          ),
          body: Container(
            color: Colors.amber,
            child: Flex(
              direction: Axis.vertical,
              children: [
                Container(
                  color: Colors.blue,
                  height: 100,
                ),
                Expanded(child:
                  Container(color: Colors.grey),
                ),
                Container(
                  height: 100,
                  color: Colors.red,
                )
              ],
            ),
          )),
    );
  }
}
流失布局 - Wrap
作用:

流式布局组件,当子组件在主轴方向上排列不下时,他会自动换行(或换列)

Column/Row/Flex内容超过不会换行

Wrap组件更像是Flex组件加了换行

场景:
  • 当子组件内容是根据数据动态生成时,使用wrap可以确保布局始终适配

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  List<Widget> getLsit() {
    return List.generate(10, (index) {
      return Container(
        color: Colors.blue,
        width: 100,
        height: 100,
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Wrap代码示例"),
          ),
          body: Container(
              width: double.infinity,
              height: double.infinity,
              color: Colors.amber,
              child: Wrap(
                spacing: 10,
                runSpacing: 10,
                alignment: WrapAlignment.center,
                direction: Axis.horizontal,
                children: getLsit(),
              ))),
    );
  }
}

层叠布局 - Stack/Positioned
作用:

层叠布局组件,允许你将多个子组件按照Z轴(深度方向)进行叠加排列

搭档:

Positioned组件时Stack的黄金搭档,对子组件进行精确定位控制。Positioned必须作为Stack的直接子组件

Positioned通过left,right,top,bottom来将子组件“钉”在Stack的某个角落或边缘

@override
Widget build(BuildContext context) {
	return MaterialApp(
		home: Scaffold(
			appBar: AppBar(
				title: Text("Stack代码示例"),
			),
			body: Stack(
				alignment: AlignmentDirectional.center,
				children: [
					Container(
						width: 300,
						height: 300,
						color: Colors.blue,
					),
					Container(
						width: 200,
						height: 200,
						color: Colors.red,
					),
					Container(
						width: 100,
						height: 100,
						color: Colors.green,
					)
				],
			)),
	);
}
Positioned(
	left:0,
	bottom:0,
	child:Container(
		width:100,
		height:100,
		color:Colors.blue
	)
)

Positioned必须搭配Stack

Stack中子组件的层叠顺序由其在children列表中的顺序决定

明确尺寸约束,父组件的大小直接影响Stack的最终大小和子组件的布局行为

文本组件 - Text
作用:

在用户界面中显示文本的基础组件

 @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Stack代码示例"),
          ),
          body: Container(
            alignment: AlignmentDirectional.center,
            width: double.infinity,
            height: double.infinity,
            color: Colors.amber,
            child: Text("Hello Flutter",
                style: TextStyle(
                    fontSize: 30,
                    color: Colors.blue,
                    fontStyle: FontStyle.italic,
                    fontWeight: FontWeight.bold,
                    decoration: TextDecoration.underline,
                    decorationColor: Colors.red
                )),
          )),
    );
  }
文本组件 - Text/TextSpan

如果需要在同一段文本中显示不同样式,可用Text.rich构造函数配合TextSpan来实现

 child: Text.rich(
                TextSpan(
                text: "HELLO ",
                children: [TextSpan(text: "FLUTTER",style: TextStyle(color: Colors.green))],
                style: TextStyle(
                    color: Colors.red,
                    fontSize: 40,
                    fontWeight: FontWeight.bold)
                )
            ),

Text组件本身和TextStyle中都可能有overflow等属性,Text组件属性优先级更高

假如文本过长请务必设置maxLines和overflow

大量重复使用文本样式,建议统一定义

图片组件 - Image
作用:

在用户界面中显示图片的核心部件

图片分类:

步骤:
  1. 配置pubspec.yaml文件
  2. 打开assets选项
  3. 注意缩近格式
@override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Text代码示例"),
          ),
          body: Container(
            alignment: AlignmentDirectional.center,
            width: double.infinity,
            height: double.infinity,
            color: Colors.amber,
            child: Image.asset("lib/images/Myteam.png",width: 100,height: 100,fit: BoxFit.cover,),
          )),
    );
  }
Image.network 网络图片

Android/ios使用image.network需要配置网络权限

文本输入组件 - TextField
作用:

实现文本输入功能的核心组件

  • 使用有状态组件
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {

  TextEditingController _accountController = TextEditingController();
  TextEditingController _PassWordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("登录")),
        body: Container(
          padding: EdgeInsets.all(20),
          color: Colors.white,
          child: Column(
            children: [
              TextField(
                onChanged: (value){
                  print(value);
                },
                onSubmitted: (value) {
                  print(value);
                },
                controller: _accountController,
                decoration: InputDecoration(
                    contentPadding: EdgeInsets.only(left: 20),
                    // 内容内边距
                    border: OutlineInputBorder(
                        borderSide: BorderSide.none,
                        borderRadius: BorderRadius.circular(25)),
                    hintText: "请输入账号",
                    fillColor: Colors.amber,
                    filled: true),
              ),
              SizedBox(height: 20),
              TextField(
                  controller: _PassWordController,
                  decoration: InputDecoration(
                      contentPadding: EdgeInsets.only(left: 20),
                      // 内容内边距
                      border: OutlineInputBorder(
                          borderSide: BorderSide.none,
                          borderRadius: BorderRadius.circular(25)),
                      hintText: "请输入密码",
                      fillColor: Colors.amber,
                      filled: true),
                  obscureText: true),
              SizedBox(height: 20),
              Container(
                width: double.infinity,
                height: 50,
                decoration: BoxDecoration(
                    color: Colors.black,
                    borderRadius: BorderRadius.circular(25)),
                child: TextButton(
                    onPressed: () {
                      print("登录${_accountController.text} - ${_PassWordController.text}");
                    },
                    child: Text(
                      "登录",
                      style: TextStyle(color: Colors.white),
                    )),
              )
            ],
          ),
        ),
      ),
    );
  }
}
  • 使用TextField必须使用有状态组件
  • decoration属性下的InputDecoration来定制
  • obsureText设置true可隐藏输入内容,用于密码输入框

常用滚动组件

常用滚动组件 - SingleChildScrollView

用法:包裹一个子组件,让单个子组件具备滚动能力

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("登录")),
        body: SingleChildScrollView(
            padding: EdgeInsets.all(20),
            child: Column(
              children: List.generate(100, (index) {
                return Container(
                  margin: EdgeInsets.only(top: 10),
                  color: Colors.blue,
                  height: 100,
                  width: double.infinity,
                  alignment: Alignment.center,
                  child: Text('我是第${index + 1}个',
                      style: TextStyle(color: Colors.white, fontSize: 30)),
                );
              }),
            )
            ),
      ),
    );
  }
控制滚动 - SingleChildScrollView

controller:给组件的controller绑定ScrollController对象

  • 子组件:

只能包含一个子组件,如果滚动多个组件,通常将其嵌套在Column或Row中

滚动方向:通过scrollDirection属性控制,默认为垂直方向,也可设置水平方向

  • 特点:

一次性构建所有子组件,如果嵌套Column或Row中包含大量子项,可能会导致性能问题,建议使用ListView

  • 控制滚动:

绑定一个ScrollController对象给controller对象,使用animateTo/JumpTo方法控制滚动

  • 滚动到顶部:

conroller.jumpTo(0)

  • 滚动到底部:

controller.jumpTo(contr.position.maxScrollExtent)

常用滚动组件 - ListView

作用:用于构建可滚动列表的核心不见,并提供流畅滚动体验

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

机制:采用按需渲染(懒加载),之构建当前可见区域的列表项,极大提升列表性能


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(title: Text("登录")),
            body: ListView(
                children: List.generate(100, (index) {
              return Container(
                color: Colors.blue,
                width: double.infinity,
                height: 80,
                margin: EdgeInsets.only(top: 10),
                alignment: Alignment.center,
                child: Text("第${index + 1}个",
                    style: TextStyle(color: Colors.white)),
              );
            }))));
  }
ListView - builder模式

作用:

处理长列表或动态数据的首选和推荐方式

方式:

接受一个itemBuilder回调函数来按需构建列表项,通过itemCount控制列表长度

ListView - separate模式

作用:

在ListView.builder的基础上,额外提供了构建分割线的能力

方式:

需要同时提供itemBuilder、separatorBuilder、itemCount三个属性

@override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(title: Text("登录")),
          body: ListView.separated(itemBuilder: (BuildContext context,int index){
            return Container(
              // margin: EdgeInsets.only(top: 10),
              color:Colors.blue,
              width: double.infinity,
              height: 80,
              child: Text("第${index + 1}个",style: TextStyle(color: Colors.white,fontSize: 30)),
              alignment: Alignment.center,
            );
          }, separatorBuilder: (BuildContext context,int index) {
            return Container(
              height: 10,
              width: double.infinity,
              color:Colors.yellow,

            );
          }, itemCount: 100),
    ));
  }
常用滚动组件 - GridView

作用:

用于创建二维可滚动网格布局的核心组件

方式:

提供多种构建方式,GridView.count,GridView.extent,GridView.builder

自定义滚动容器 - CustomScrollView

作用:

用于组合多个可滚动组件(列表,网格),实现统一协调的滚动效果

Sliver:
Flutter中描述可滚动视图内部一部分内容的组件,他是滚动视图的切片

用法:

通过Slivers属性接受一个Sliver组件列表

Sliver组件对应关系:

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MainPage());
}

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

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(title: Text("登录")),
            body: CustomScrollView(
              slivers: [
                // 包裹普通widget组件
                SliverToBoxAdapter(
                  child: Container(
                    width: double.infinity,
                    height: 260,
                    color: Colors.blue,
                    child: Text("轮播图",
                        style: TextStyle(color: Colors.white, fontSize: 30)),
                    alignment: Alignment.center,
                  ),
                ),
                SliverToBoxAdapter(
                  child: SizedBox(
                    height: 10,
                  ),
                ),
                SliverPersistentHeader(
                    delegate: _StickyCategory(), pinned: true),
                SliverToBoxAdapter(
                  child: SizedBox(
                    height: 10,
                  ),
                ),
                // 双列排序
                SliverGrid.count(crossAxisCount: 2,crossAxisSpacing: 10,mainAxisSpacing: 10,children:List.generate(100, (index){
                  return Container(
                    color: Colors.blue,
                    alignment: Alignment.center,
                    child: Text("列表项${index + 1}",style: TextStyle(color: Colors.white,fontSize: 20),),
                  );
                }))
                // 单列排序
                // SliverList.separated(
                //     itemBuilder: (BuildContext context, int index) {
                //       return Container(
                //         color: Colors.blue,
                //         height: 100,
                //         alignment: Alignment.center,
                //         child: Text("列表项${index + 1}",style: TextStyle(color: Colors.white,fontSize: 20)),
                //       );
                //     },
                //     separatorBuilder: (BuildContext context, int index) {
                //       return SizedBox(
                //         height: 20,
                //       );
                //     })
              ],
            )));
  }
}

class _StickyCategory extends SliverPersistentHeaderDelegate {
  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      color: Colors.white,
      child: ListView.builder(
          itemCount: 30,
          scrollDirection: Axis.horizontal,
          itemBuilder: (BuildContext context, int index) {
            return Container(
              width: 100,
              margin: EdgeInsets.symmetric(horizontal: 10),
              alignment: Alignment.center,
              color: Colors.blue,
              child: Text("分类:${index + 1}",
                  style: TextStyle(color: Colors.white)),
            );
          }),
    );
  }

  @override
  // 最大展开去高度
  double get maxExtent => 80;

  @override
  // 最小折叠高度
  double get minExtent => 60;

  @override
  // 是否需要重建
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
    // TODO: implement shouldRebuild
    return false;
  }
}

整页滚动容器 - PageView

作用:

用于实现分页滚动视图的核心组件

方式:

提供多种构建方式,默认构造方式、PageView.builder等

优势:

支持懒加载(按需渲染)

控制器:PageView绑定controller属性,对象类型为PageController

切换方法:controller.jumpPage、animateToPage

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐