Flutter学习笔记

本文参考Flutter课程导学_哔哩哔哩_bilibili

1. 创建项目

复制代码
flutter create --platforms web flutter_demo

注意如果执行命令后什么都不显示,可能是权限不足,使用管理员身份运行PowerShell

看到All done!即可创建成功

2. 运行项目

复制代码
cd flutter_demo
flutter run -d chrome

进入项目根目录,运行 Web 项目(指定 Chrome 浏览器)

如果遇到该情况(启动失败,打开浏览器,但浏览器显示不出结果),可能是Flutter 启动 Chrome 时的参数组合和浏览器权限冲突。

解决:

用「web-server」模式绕开浏览器启动(最快速验证)

先不通过 Flutter 直接启动浏览器,改用「web 服务器」模式,手动在 Chrome 中打开页面:

复制代码
# 启动 web 服务器(不自动打开浏览器)
flutter run -d web-server

注意如果执行命令后什么都不显示,可能是权限不足,使用管理员身份运行PowerShell

启动成功后,会输出类似http://localhost:62825 的地址,手动复制这个地址到 Chrome 中打开即可访问项目。

3. 组件学习

3.1基础组件

3.1.1 MaterialAPP

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

复制代码
void main(List<String> args) {
  runApp(
    MaterialApp(
      title: "materialAPP 体验",//展示标题
      theme: ThemeData(scaffoldBackgroundColor: Colors.blueAccent),//设置主题
      home: Scaffold(),//展示主体内容, Scaffold()骨架组件
    ),
  );
}

注意如果修改代码后浏览器页面还没有变化,终端输入r实现热重载,再刷新浏览器即可得到修改后的页面展示。

3.1.2 Scaffold

代码展示:

复制代码
runApp(
    MaterialApp(
      title: "materialAPP 体验",
      theme: ThemeData(
        //设置中部与底部主题
        scaffoldBackgroundColor: const Color.fromARGB(255, 127, 147, 183),
      ),
      home: Scaffold(
        appBar: AppBar(title: Text("头部区域"), centerTitle: true),

        body: Container(child: Center(child: Text("中部区域"))),

        bottomNavigationBar: Container(
          height: 80, //设置底部大小,不然中部与底部无法分开,看不到底部效果
          child: Center(child: Text("底部区域")),
        ),
      ),
    ),
  );

效果展示:

3.2 自定义组件

3.2.1无状态组件

无状态组件:创建新的类,继承 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: "materialAPP 体验",
      theme: ThemeData(
        //设置中部与底部主题
        scaffoldBackgroundColor: const Color.fromARGB(255, 127, 147, 183),
      ),
      home: Scaffold(
        appBar: AppBar(title: Text("头部区域"), centerTitle: true),

        body: Container(child: Center(child: Text("中部区域"))),

        bottomNavigationBar: Container(
          height: 80, //设置底部大小,不然中部与底部无法分开,看不到底部效果
          child: Center(child: Text("底部区域")),
        ),
      ),
    );
  }
}
3.2.2有状态组件

有状态组件管理变化的内部状态,当状态改变时,组件回更新显示内容

第一个类负责向外接收参数,第二个类向内管理状态

复制代码
import 'package:flutter/material.dart';

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

//第一个类,创建State对象(接收外部参数)
class MainPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    //返回第二个类的对象
    return _MainPageState();
  }
}

//第二个类 内部类(私有)继承State<第一个类名>,负责管理数据 处理业务逻辑 渲染视图
class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "materialAPP 体验",
      theme: ThemeData(
        //设置中部与底部主题
        scaffoldBackgroundColor: const Color.fromARGB(255, 4, 85, 238),
      ),
      home: Scaffold(
        appBar: AppBar(title: Text("头部区域"), centerTitle: true),

        body: Container(child: Center(child: Text("中部区域"))),

        bottomNavigationBar: Container(
          height: 80, //设置底部大小,不然中部与底部无法分开,看不到底部效果
          child: Center(child: Text("底部区域")),
        ),
      ),
    );
  }
}

3.3 组件生命周期

3.3.1 无状态组件

唯一阶段:build()方法

当组件被创建或父组件状态变化导致其需要重新构建时,build方法会被调用

3.3.2 有状态组件

InheritedWidget:全局状态(如路由),专门用于Widget树中自顶向下高效地共享数据,顶层组件提供数据,子孙节点直接获取

所有方法均在第二个类中实现(如AState)

3.4 点击事件

3.4.1 GestureDelector

GestureDelector是Flutter中最常用、功能最丰富的手势检测组件

onTap:点击 onDoubleTap:双击 等以on开头的方法

用法:GestureDelector包裹被点击的元素,传入方法(以on开头)

复制代码
body: Container(
          child: Center(
            child: GestureDetector(//包裹
              // onTap: () { //点击事件
              //   print("点击了该区域");
              // },
              onDoubleTap: () {
                print("双击该区域");
              },
              child: Text("中部区域"),//被点击的元素
            ),
          ),
        ),
3.4.2 组件点击事件
复制代码
 body: Container(
          child: Center(
            child: TextButton(
              onPressed: () {
                //处理点击逻辑
                print("组件点击");
              },
              child: Text("文本按钮"),
            ),
          ),
        ),

3.5 状态更新

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

复制代码
body: Center(
          child: Row(
            children: [
              TextButton(
                onPressed: () {
                  setState(() {
                    //如不加setState,则页面上count的值永远为1(UI不更新)
                    count--;
                  });
                },
                child: Text("-"),
              ),
              Text(count.toString()),
              TextButton(
                onPressed: () {
                  count++;
                  setState(() {}); //也可以这样写,setState是异步操作,最后执行
                },
                child: Text("+"),
              ),
            ],
          ),
        ),

3.6 组件

布局组件

3.6.1 Container组件

相当于HTML的div

常见属性

复制代码
return MaterialApp(
      home: Scaffold(
        body: Container(
          transform: Matrix4.rotationZ(0.05),//变换角度0.05是弧度而非角度,
          margin: EdgeInsets.all(20),//外边距
          alignment: Alignment.center,//子组件居中
          width: 200,//宽  width:double.infinity正无穷大,填满整个空间宽
          height: 200,//高
          decoration: BoxDecoration(
            color: Colors.blue,//背景颜色
            borderRadius: BorderRadius.circular(15),//圆角
            border: Border.all(width: 3,color: Colors.yellow)//边框
          ),
          child: Text(//Text内置样式
            "hello world ",
            style: TextStyle(color: Colors.white, fontSize: 20),
          ),
          //color:Colors.blue 简单的背景与颜色
        ),
      ),
    );

width:double.infinity正无穷大,填满整个空间宽

3.6.2 Center组件

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

必须有child,默认全部占用父容器空间,若子组件只占用部分父组件,则可以在child中嵌套Container

3.6.3 Align组件
3.6.4 Padding组件

属性:padding,必须有,定义内边距的大小和方向,通常使用EdgeInsets类来设置

所有方向用EdgeInsets.all(),

任意方向用EdgeInsets.only(top: ,bottom: ,left: ,right: ),

对称方向用EdgeInsets.symmetric(horizontal: ,vertical: )

child:需要被添加内边距的子组件

3.6.5 Column组件
3.6.6 Row组件
3.6.7 Flex和Expanded

Flex是Column和Row的结合体

3.6.8 Wrap换行组件
3.6.9 Stack/Position

Stack类似相对定位,后者叠在前者上(children中排列顺序)

3.6.10 Text组件
3.6.11 Image组件
3.6.12 TextField文本输入组件

onSubmitted :电脑端Enter键

注意:

写来试试

3.6.13 SingleChildScrollView组件
3.6.14 ListView组件
3.6.15 GridView组件
3.6.16 CustomScrollView组件
3.6.17 PageView组件

3.7 组件通信

3.7.1 父传子

无状态组件:Child类中定义构造函数(需要的参数),使用传入参数值,父组件的类(或对内类)调用构造函数(给出具体参数值)

有状态组件:Child对外的类接收属性(定义构造函数),Child对内的类获取属性(使用属性值,widget.参数名)

父组件类(对内类)调用构造函数(给出具体参数值)

3.7.2 子传父

删除图标可以如此写

3.8 网络请求

3.8.1 Dio基本使用

命令安装插件

复制代码
flutter pub add dio

基本使用: Dio().get(地址).then().catchError()

一般情况下,在初始化状态initState获取页面数据

3.8.2 封装Dio工具
  1. 创建工具类DioUtil

连续赋值简写(..),前提:调用函数的主体一致

  1. 构造函数中设置基础地址和超时时间
  1. 添加各类拦截器

  2. 封装统一请求方法

  1. 获取数据
  1. 解决跨域问题

3.9 路由管理

3.9.1 基本路由

每一个MaterialApp有一套路由系统

3.9.2 命名路由
3.9.3 命名路由传递参数
3.9.4 基本路由传参
3.9.5 高级路由控制
3.9.6 404路由
相关推荐
Zsnoin能3 小时前
Flutter仿ios液态玻璃效果
flutter
一枚前端小姐姐4 小时前
低代码平台表单设计系统技术分析(实战二)
低代码·架构·前端框架
傅里叶8 小时前
iOS相机权限获取
flutter·ios
Haha_bj8 小时前
Flutter—— 本地存储(shared_preferences)
flutter
心之语歌9 小时前
Flutter 存储权限:适配主流系统
flutter
恋猫de小郭10 小时前
Android 官方正式官宣 AI 支持 AppFunctions ,Android 官方 MCP 和系统级 OpenClaw 雏形
android·前端·flutter
MakeZero1 天前
Flutter那些事-布局篇
flutter
王码码20351 天前
Flutter for OpenHarmony:socket_io_client 实时通信的事实标准(Node.js 后端的最佳拍档) 深度解析与鸿蒙适配指南
android·flutter·ui·华为·node.js·harmonyos
百思可瑞教育1 天前
Vue 前端与 Node.js 后端文件上传与处理实现
前端·javascript·vue.js·前端框架·node.js·ecmascript·百思可瑞教育
zhangkai1 天前
flutter存储知识点总结
flutter·ios