1. 准备工作

需要 java 环境

1. 安装 IED Android Studio

下载 Android Studio 和应用工具 - Android 开发者 | Android Developers

1.2 下载插件

  1. Dart
  2. Flutter
  3. Flutter Snippets (Flutter 提示词)

安装完成后重启再 project 页 出现 New Flutter Project 即为成功

image-20250817155149398

2. Flutter SDK

2.1 安装 Flutter

归档列表 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

选择最新即可

解压

2.2 配置环境变量

将解压出来 Flutter/bin 放到环境变量 Path

image-20250817154255591

2.3 配置国内镜像(可选)

参考: 在中国网络环境下使用 Flutter | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

添加环境变量 :

image-20250817154831875

image-20250817154924042

2.4 更改 Android SDK 目录(可选)

默认的 SDK 目录在 C 盘更 可以选择更改

  1. 在你想放 SDK 的目录创建文件夹 Android -> Sdk
  2. 打开 Android Studio
  3. 打开设置 -> Languages & Frameworks -> Android SDK
  4. 招到 Android SDK Location 右边的 Edit 点击 随后在新弹出的窗口内更改位置
    image-20250818115258051

2.5 检查是否安装成功

使用管理员权限打开 cmd 或者 powershell 输入

flutter doctor

image-20250817161712749

如果出现这种错误 需要解决 方法如下

  1. 打开 Android Studio

  2. 打开设置(setting) -> Languages & Frameworks -> Android SDK

  3. 选择 SDK Tools

  4. 将 Android SDK Command-line Tools(last) 勾选
    image-20250817162004030

  5. 点击确定等待安装
    image-20250817162052636

  6. 再次在 cmd 或者 powershell 输入

    flutter doctor
    

    如果你修改过 Android SDK 位置的可能需要输入 flutter config --android-sdk:<你的 Android SDK 地址 绝对路径> 随后就可以再次运行 flutterdoctor

    image-20250817162155379

    如果还提示image-20250817163139250

    再继续运行

    flutter doctor --android-licenses
    

    全部选择 y

3. 新建 Flutter 项目

点击 New Flutter project

image-20250817164617353

选择 Flutter 并选择 Flutter SDK 安装位置

image-20250817164748300

选择工程名称(全小写)、路径、平台

image-20250817165030230

4. 运行项目

首先左上角 Flie -> Open 招到该项目的 Android 文件打开

image-20250817172618171

第一次进来可能要下 10min 左右

image-20250817172627497

随后链接手机 -> 打开开发者选项 -> 打开 USB 调试 -> 打开 USB 安装

随后在项目内点击启动即可

image-20250817172854495

5. 真机调试

打开 cmd 或者 PowShell cd 进你的项目内(不是 Android 文件夹)

使用

flutter devices

检查当前的链接设备

flutter run

将项目运行起来

6. 虚拟机调试

  1. 使用 Android Studio 自带的虚拟机
  2. 使用第三方虚拟机

6.1 使用 Android Studio 虚拟机

  1. 打开 Android Studio

  2. 点击左上角三个点 -> Tool -> Device Manager
    image-20250818110839390

  3. 或者直接侧边栏
    image-20250818110925995

  4. 点击加号 -> Create Virtual Device
    image-20250818111034073

  5. 随后随便找一个和自己电脑分辨率相同的设备
    image-20250818111610289

  6. 这里可以选择 Android 版本
    image-20250818111658004

  7. 选好后点击 Finish 即可开始下载

  8. 下载好后就可看到这里的设备
    image-20250818111759363

  9. 点击启动稍等一会儿即可进入虚拟机桌面(第一次要装系统所以很慢)
    image-20250818111917621

  10. 在 PowShell 或者 CMD 中输入

    flutter devices
    

    可以看到真机和虚拟机

    image-20250818112055096

    使用

    flutter run -d all
    

    可以将项目运行到所有设备中

7. 使用 VsCode 开发 Flutter

7.1 下载 Flutter 对应插件

  1. Dart
  2. Flutter
  3. Flutter Widget Snippets (提示工具)
  4. Awesome Flutter Snippets (提示工具)

Tpis: Vscode 打开父工程 Android Studio 打开父工程下的 Android

7.2 常用快捷键

在项目运行时 直接再终端输入
image-20250828142522636

  1. r 热加载
  2. R 热重启
  3. p 打开网格
  4. o 切换 Android 和 iOS 的预览
  5. q 退出预览模式 也就是结束运行

2.开发教程

1. Container 容器组件

名称功能说明
alignment子元素对齐方式
- topCenter:顶部居中对齐
- topLeft:顶部左对齐
- topRight:顶部右对齐
- center:水平垂直居中对齐
- centerLeft:垂直居中、水平居左
- centerRight:垂直居中、水平居右
- bottomCenter:底部居中对齐
- bottomLeft:底部居左对齐
- bottomRight:底部居右对齐
decoration设置容器的样式
- color:背景颜色,如 Colors.blue
- border:边框,如 Border.all(color: Colors.red, width: 2.0)
- borderRadius:圆角,如 BorderRadius.circular(8)
- boxShadow:阴影,如 BoxShadow(color: Colors.blue, offset: Offset(2.0, 2.0), blurRadius: 10.0)
- 渐变背景LinearGradient 线性渐变 / RadialGradient 径向渐变
margin容器与外部组件的距离,如 EdgeInsets.all(20.0)
padding容器与子元素之间的内边距,如 EdgeInsets.all(10.0)
transform容器的变换,如旋转:Matrix4.rotationZ(0.2)
height容器高度
width容器宽度
child容器的子元素

2. Text 组件

2.1Text 常用属性

名称功能说明
textAlign文本对齐方式
- center:居中
- left:左对齐
- right:右对齐
- justify:两端对齐
textDirection文本方向
- ltr:从左至右
- rtl:从右至左
overflow文本超出屏幕后处理方式
- clip:裁剪
- fade:渐隐
- ellipsis:省略号
textScaleFactor字体显示倍率(放大或缩小字体)
maxLines文本显示的最大行数
style文本样式,使用 TextStyle 设置

2.2TextStyle 常用属性

名称功能说明
decoration文字装饰线
- none:无装饰
- lineThrough:删除线
- overline:上划线
- underline:下划线
decorationColor装饰线颜色
decorationStyle装饰线风格
- dashed:虚线
- dotted:点线
- double:双实线
- solid:单实线
- wavy:波浪线
wordSpacing单词间距(负值会更紧凑)
letterSpacing字母间距(负值会更紧凑)
fontStyle字体样式
- italic:斜体
- normal:正常体
fontSize字体大小
color字体颜色
fontWeight字体粗细
- bold:粗体
- normal:正常体

3. 图片组件

​ Flutter 中,我们可以通过Image组件来加载并显示图片Image的数据源可以是 asset、文件、内存以及 网络

  1. Image.asset : 本地图片

    1. 首先先将图片放入 images 文件夹下 没用则创建

    2. 找到 pubspec.yaml 并修改

      # The following section is specific to Flutter packages.
      flutter:
        # The following line ensures that the Material Icons font is
        # included with your application, so that you can use the icons in
        # the material Icons class.
        uses-material-design: true
      
        # To add assets to your application, add an assets section, like this:
        assets:
          - images/2.0x/a.jpeg
          - images/3.0x/a.jpeg
          - images/a.jpeg
      

      image-20250829120633642

    class LocalImage extends StatelessWidget {
      const LocalImage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Container(
          width: 200,
          height: 200,
          decoration: BoxDecoration(color: Colors.blueAccent),
          child: Image.asset("images/a.jpeg", fit: BoxFit.cover),
        );
      }
    }
    
  2. Image.network : 远程图片

    class MyImg extends StatelessWidget {
      const MyImg({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Container(
            width: 100,
            height: 100,
            child: Image.network(
              "https://xiayh.top/upload/thumbnails/2025/w800/DM20250828171248001.png",
              scale: 2,
              fit: BoxFit.cover,
            ),
          ),
        );
      }
    }
    

Image 组件的常用属性

名称类型功能说明
alignmentAlignment图片的对齐方式(如 Alignment.centerAlignment.topLeft 等)
color + colorBlendModeColor + BlendMode设置图片背景色并与图片颜色混合
示例:绿色背景 + 红色图片 = 颜色混合效果
fitBoxFit控制图片的拉伸与缩放方式
- fill:图片拉伸并充满容器,可能变形
- contain:等比例缩放,完整显示,可能留空隙
- cover:等比例缩放,充满容器,可能裁剪
- fitWidth:宽度充满,可能裁剪
- fitHeight:高度充满,可能裁剪
- scaleDown:类似 contain,但不会超过原图大小
repeatImageRepeat图片平铺方式
- repeat:横向纵向都重复
- repeatX:仅横向重复
- repeatY:仅纵向重复
widthdouble图片宽度(常与 ClipOval 搭配裁剪成圆形)
heightdouble图片高度(常与 ClipOval 搭配裁剪成圆形)

更多属性参考:https://api.flutter.dev/flutter/widgets/Image-class.html

4. 图标组件

4.1 使用官方组件

Material Design 所有图标可以在其官网查看:https://material.io/tools/icons/

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(height: 20),
        Icon(Icons.adobe, size: 60, color: Colors.pinkAccent),
        SizedBox(height: 10),
        Icon(
          CupertinoIcons.link_circle_fill,
          size: 60,
          color: Colors.blueAccent,
        )
      ],
    );
  }
}

4.2 导入外部 Icon 图标

在阿里巴巴矢量图标库内有许多图标可以下载并导入使用

  1. 官网地址: https://www.iconfont.cn/

  2. 选择好图标后选择下载代码

  3. 将文件内的.ttf.json文件放入项目根目录下的 fonts/

  4. 找到 pubspec.yaml -> fonts 打开并修改

      fonts:
      	# 取名
        - family: myIcon
          fonts:
          	# .ttf 的位置
            - asset: fonts/iconfont.ttf
    

    也可以配置多个字体文件:

    fonts:
      - family: myIcon
        fonts:
          - asset: fonts/iconfont.ttf
      - family: myIcon2
        fonts:
          - asset: fonts/kcgfks8r4ciconfont.ttf
    
  5. 为了方便使用 定义一个 MyIcon 类(名字任取

    import 'package:flutter/material.dart';
    
    class Myfont {
      static const IconData steam = IconData(
        // 0x+json文件的unicode字段 表示为16
        0xe61b,
        fontFamily: "myIcon",
        matchTextDirection: true,
      );
    
      static const IconData apex = IconData(
        0xe691,
        fontFamily: "myIcon",
        matchTextDirection: true,
      );
    
      static const IconData warframe = IconData(
        0xe602,
        fontFamily: "myIcon",
        matchTextDirection: true,
      );
    }
    
  6. 使用

    class MyIcon extends StatelessWidget {
      const MyIcon({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            SizedBox(height: 10),
            Icon(Myfont.steam, size: 20, color: Colors.deepPurpleAccent),
            SizedBox(height: 10),
            Icon(Myfont.apex, size: 50, color: Colors.deepPurpleAccent),
            SizedBox(height: 10),
            Icon(Myfont.warframe, size: 50, color: Colors.deepPurpleAccent),
          ],
        );
      }
    }
    

5. Flutter 列表组件

列表布局是我们项目开发中最常用的一种布局方式。Flutter 中我们可以通过 ListView 来定义列表项,支 持垂直和水平方向展示。通过一个属性就可以控制列表的显示方向。列表有以下分类:

  1. 垂直列表
  2. 垂直图文列表
  3. 水平列表
  4. 动态列表

常用属性

名称类型说明
scrollDirectionAxis滚动方向
- Axis.horizontal:水平列表
- Axis.vertical:垂直列表(默认)
paddingEdgeInsetsGeometry内边距,如:EdgeInsets.all(10)
reversebool是否反向排序
- false:正序(默认)
- true:反序(列表内容从尾到头显示)
childrenList<Widget>列表子元素(一般是 List<Widget>

5.1 垂直列表

// List列表
class MyIcon extends StatelessWidget {
  const MyIcon({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: const <Widget>[
        ListTile(
            title: Text("我是一个标题"),
        ),
        ListTile(
            title: Text("我是一个标题"),
        ),
        ListTile(
            title: Text("我是一个标题"),
        ),
        ListTile(
            title: Text("我是一个标题"),
        ),
      ],
    );
  }
}

5.1.1 垂直图标和图文列表

  1. 图标列表

    class MyIcon extends StatelessWidget {
      const MyIcon({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: const <Widget>[
            ListTile(
              leading: Icon(Icons.home),
              title: Text("主页"),
              trailing: Icon(Icons.chevron_right),
            ),
            Divider(),
            ListTile(
              leading: Icon(Icons.assignment),
              title: Text("订单"),
              trailing: Icon(Icons.chevron_right),
            ),
            Divider(),
          ],
        );
      }
    }
    
  2. 图文列表

    class news extends StatelessWidget {
      const news({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
          children: <Widget>[
            ListTile(
              leading: Image.network(
                "https://img-s.msn.cn/tenant/amp/entityid/AA1LbsBs.img?w=768&h=327&m=6",
              ),
              title: Text("微信悄悄上线AI播客,“真人”唠嗑给你讲新闻"),
            ),
            Divider(),
            ListTile(
              title: Text("AI重塑新闻版图:人类编辑与AI共舞的新时代"),
              trailing: Image.network(
                "https://img-s.msn.cn/tenant/amp/entityid/AA1L8o2z.img?w=400&h=300&m=6",
              ),
            ),
            Divider(),
            ListTile(
              leading: Image.network(
                "https://img-s.msn.cn/tenant/amp/entityid/AA1Lcm9i.img?w=400&h=300&m=6",
              ),
              title: Text("微信AI播客新功能:双主播对话形式,让新闻更“动听”"),
            ),
            Divider(),
          ],
        );
      }
    }
    
    class ListImg extends StatelessWidget {
      const ListImg({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
          children: <Widget>[
            Image.network("https://www.itying.com/images/flutter/1.png"),
            Container(
              margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
              height: 44,
              child: Text(
                "I am Flutter Title",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 22),
              ),
            ),
            Image.network("https://www.itying.com/images/flutter/2.png"),
            Container(
              margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
              height: 44,
              child: Text(
                "I am Flutter Title",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 22),
              ),
            ),
            Image.network("https://www.itying.com/images/flutter/3.png"),
            Container(
              margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
              height: 44,
              child: Text(
                "I am Flutter Title",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 22),
              ),
            ),
            Image.network("https://www.itying.com/images/flutter/4.png"),
            Container(
              margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
              height: 44,
              child: Text(
                "I am Flutter Title",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 22),
              ),
            ),
            Image.network("https://www.itying.com/images/flutter/5.png"),
            Container(
              margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
              height: 44,
              child: Text(
                "I am Flutter Title",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 22),
              ),
            ),
            Image.network("https://www.itying.com/images/flutter/6.png"),
            Container(
              margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
              height: 44,
              child: Text(
                "I am Flutter Title",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 22),
              ),
            ),
            Image.network("https://www.itying.com/images/flutter/7.png"),
            Container(
              margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
              height: 44,
              child: Text(
                "I am Flutter Title",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 22),
              ),
            ),
          ],
        );
      }
    }
    

5.1.2 水平列表

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

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 2000,
      child: ListView(
        scrollDirection: Axis.horizontal,
        padding: EdgeInsets.all(5),
        children: <Widget>[
          Container(
            width: 150,
            padding: EdgeInsets.fromLTRB(0, 0, 5, 0),
            child: Column(
              children: [
                Image.network(
                  "https://www.itying.com/images/flutter/1.png",
                  fit: BoxFit.cover,
                ),
                Text("¥ 1000", style: TextStyle(fontSize: 22)),
              ],
            ),
          ),
          Container(
            width: 150,
            padding: EdgeInsets.fromLTRB(0, 0, 5, 0),
            child: Column(
              children: [
                Image.network(
                  "https://www.itying.com/images/flutter/2.png",
                  fit: BoxFit.cover,
                ),
                Text("¥ 1000", style: TextStyle(fontSize: 22)),
              ],
            ),
          ),
          Container(
            width: 150,
            padding: EdgeInsets.fromLTRB(0, 0, 5, 0),
            child: Column(
              children: [
                Image.network(
                  "https://www.itying.com/images/flutter/3.png",
                  fit: BoxFit.cover,
                ),
                Text("¥ 1000", style: TextStyle(fontSize: 22)),
              ],
            ),
          ),
          Container(
            width: 150,
            padding: EdgeInsets.fromLTRB(0, 0, 5, 0),
            child: Column(
              children: [
                Image.network(
                  "https://www.itying.com/images/flutter/4.png",
                  fit: BoxFit.cover,
                ),
                Text("¥ 1000", style: TextStyle(fontSize: 22)),
              ],
            ),
          ),
          Container(
            width: 150,
            padding: EdgeInsets.fromLTRB(0, 0, 5, 0),
            child: Column(
              children: [
                Image.network(
                  "https://www.itying.com/images/flutter/5.png",
                  fit: BoxFit.cover,
                ),
                Text("¥ 1000", style: TextStyle(fontSize: 22)),
              ],
            ),
          ),
          Container(
            width: 150,
            padding: EdgeInsets.fromLTRB(0, 0, 5, 0),
            child: Column(
              children: [
                Image.network(
                  "https://www.itying.com/images/flutter/6.png",
                  fit: BoxFit.cover,
                ),
                Text("¥ 1000", style: TextStyle(fontSize: 22)),
              ],
            ),
          ),
        ],
      ),
    );
  }
}