Flutter - 布局

目录

[Flutter -- 基础组件MaterialApp](#Flutter -- 基础组件MaterialApp)

特性:

常见属性:

[基础组件 - Scaffold组件](#基础组件 - Scaffold组件)

总结:

[Flutter自定义组件 - 无状态组件和有状态组件](#Flutter自定义组件 - 无状态组件和有状态组件)

定义:

分类:

[无状态组件 - StatelessWidget](#无状态组件 - StatelessWidget)

定义:

要点:

场景:

[有状态组件 - StatefulWidget](#有状态组件 - StatefulWidget)

定义:

实现1:

实现2:

要点:

总结:

快捷键创建组件:

[组件生命周期 - 无状态组件](#组件生命周期 - 无状态组件)

[组件生命周期 - 有状态组件](#组件生命周期 - 有状态组件)

总结:

[事件 - 点击事件GestureDetector](#事件 - 点击事件GestureDetector)

[事件 - 组件点击事件](#事件 - 组件点击事件)

[状态更新 - setState](#状态更新 - setState)

语法:

案例:

布局组件:

[基础容器 - Container](#基础容器 - Container)

[基础容器 - Center - 居中组件](#基础容器 - Center - 居中组件)

[基础容器 - Align - 对齐组件](#基础容器 - Align - 对齐组件)

[基础组件 - Padding - 内边距组件](#基础组件 - Padding - 内边距组件)

[线性布局 - Column.](#线性布局 - Column.)

作用:

[线性布局 - Row](#线性布局 - Row)

作用:

[弹性布局 - Flex](#弹性布局 - Flex)

作用:

子组件:

[弹性布局 - Flex/Expanded/Flexible](#弹性布局 - Flex/Expanded/Flexible)

Flex实例:

[流失布局 - Wrap](#流失布局 - Wrap)

作用:

场景:

[层叠布局 - Stack/Positioned](#层叠布局 - Stack/Positioned)

作用:

搭档:

[文本组件 - Text](#文本组件 - Text)

作用:

[文本组件 - Text/TextSpan](#文本组件 - Text/TextSpan)

[图片组件 - Image](#图片组件 - Image)

作用:

图片分类:

步骤:

[Image.network 网络图片](#Image.network 网络图片)

[文本输入组件 - TextField](#文本输入组件 - TextField)

作用:

常用滚动组件

[常用滚动组件 - SingleChildScrollView](#常用滚动组件 - SingleChildScrollView)

[控制滚动 - SingleChildScrollView](#控制滚动 - SingleChildScrollView)

[常用滚动组件 - ListView](#常用滚动组件 - ListView)

[ListView - builder模式](#ListView - builder模式)

[ListView - separate模式](#ListView - separate模式)

[常用滚动组件 - GridView](#常用滚动组件 - GridView)

[自定义滚动容器 - CustomScrollView](#自定义滚动容器 - CustomScrollView)

[整页滚动容器 - PageView](#整页滚动容器 - 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

相关推荐
吴声子夜歌9 小时前
Java数据结构与算法——数论问题
java·开发语言
栈与堆9 小时前
数据结构篇(1) - 5000字细嗦什么是数组!!!
java·开发语言·数据结构·python·算法·leetcode·柔性数组
满栀5859 小时前
基于 jQuery 实现商品列表增删改查与数据统计
前端·javascript·jquery
Mr -老鬼9 小时前
Electron 与 Tauri 全方位对比指南(2026版)
前端·javascript·rust·electron·nodejs·tauri
yuanmenghao9 小时前
自动驾驶中间件iceoryx - 同步与通知机制(一)
开发语言·网络·驱动开发·中间件·自动驾驶
企鹅会滑雪9 小时前
【无标题】
开发语言·python
幻云20109 小时前
Next.js 之道:从全栈思维到架构实战
开发语言·javascript·架构
阿豪学编程9 小时前
【Linux】线程同步和线程互斥
linux·开发语言
寻星探路9 小时前
【Python 全栈测开之路】Python 进阶:库的使用与第三方生态(标准库+Pip+实战)
java·开发语言·c++·python·ai·c#·pip