学习 flutter 基础知识

发布于:2025-08-10 ⋅ 阅读:(24) ⋅ 点赞:(0)

一、安装项目

  • 使用命令行安装项目
# test01 项目名称,可调整
flutter create test01
  • 下载后的项目结构如下
    在这里插入图片描述

  • 启动android studio 模拟器

# 查看当前平台有多少种可调试的设备
flutter devices

在这里插入图片描述

  • 启动 web 端
# -d 指定启动的平台类型(可通过 flutter devices 获取)
flutter run -d windows
  • 资源编译完毕之后,自动打开了谷歌浏览器。
    在这里插入图片描述
  • 打开 lib/main.dart 文件,这个是 flutter 的入口文件。

二、实现hello world

2.1 基础代码

import 'package:flutter/material.dart';

// main 入口函数
void main() {
  // runApp 是 Flutter内部提供的函数,当我们启动应用程序就是从这个函数开始
  // Text 是 Flutter提供的组件,用于显示文本
  // textDirection: TextDirection.ltr 表示文本从左向右显示
  // style 属性表示文本的样式
  runApp(
    Center(
      child: Text(
          "Hello World!",
          textDirection: TextDirection.ltr,
          style: TextStyle(
            fontSize: 30,
            color: Colors.orange
          ),
        ),
    )
  );
}

2.2 Material 设计风格

  • material 是 Google 公司推行的一套设计风格,里面有非常多的设计规范,比如颜色、文字排版等。
  • 在flutter中高度集成了 Material 风格的 Widget,项目中可以直接使用这些 Widget。

2.3 实现一个完整的页面结构

import 'package:flutter/material.dart';

// main 入口函数
void main() {
  // runApp 是 Flutter内部提供的函数,当我们启动应用程序就是从这个函数开始
  // Text 是 Flutter提供的组件,用于显示文本
  // textDirection: TextDirection.ltr 表示文本从左向右显示
  // style 属性表示文本的样式
  runApp(
    MaterialApp(
      title: "显示标题", // android 切换其他程序时显示的标题
      home: Scaffold(
        // 页面的标题
        appBar: AppBar(
          title: Text("标题"),
        ),
        body: Center(
          child: Text(
            "Hello World",
            textDirection: TextDirection.ltr,
            style: TextStyle(
              fontSize: 30.0,
              color: Colors.red,
            ),
          ),
        ),
      ),
    )
  );
}

2.4 创建自己的Widget

  • flutter 开发中,可以继承 StatelessWidget 或者 StatefulWidget 来创建自己的Widget
  • StatelessWidget,没有状态改变的Widget,通常仅仅展示工作而已。
  • StatefullWidget:需要保存状态,并且可能出现状态改变的Widget
import 'package:flutter/material.dart';

// main 入口函数
void main() {
  runApp(
    MyApp()
  );
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "显示标题", // android 切换其他程序时显示的标题
      home: Scaffold(
        // 页面的标题
        appBar: AppBar(title: Text("标题")),
        body: ContentWidget(),
      ),
    );
  }
}

class ContentWidget extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Center(child: TextWidget());
  }
}

class TextWidget extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Text(
      "Hello World",
      textDirection: TextDirection.ltr,
      style: TextStyle(fontSize: 30.0, color: Colors.red),
    );
  }
}

2.5 小案例

import 'package:flutter/material.dart';

void main () {
  runApp(MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Demo'),
          centerTitle: true,
        ),
        body: HomeContent(),
      ),
    );
  }
}

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

  
  Widget build(BuildContext context) {
    // Padding 距离周边的距离
    return Padding(
      padding: EdgeInsets.all(10),
      // ListView 超出屏幕范围时,会自动滚动
      child: ListView(
        children: [
          Item("app1", "product1", "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k"),
          Item("app2", "product2", "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k"),
          Item("app3", "product3", "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k"),
        ],
      ),
    );
  }
}

class Item extends StatelessWidget {
  final String appName;
  final String productName;
  final String imageUrl;
  const Item(this.appName, this.productName, this.imageUrl, {super.key});

  
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.all(10.0),
      padding: const EdgeInsets.all(10.0),
      decoration: BoxDecoration(
        border: Border.all(color: Colors.black, width: 3),
      ),
      child: Column(
        children: <Widget>[
          Text(appName, style: TextStyle(fontSize: 24)),
          Text(productName, style: TextStyle(fontSize: 18)),
          // 设置一个高度为10的空盒子
          SizedBox(height: 10),
          Image.network(imageUrl)
        ],
      ),
    );
  }
 }

效果如下:
在这里插入图片描述

2.6 小案例

import 'package:flutter/material.dart';

void main () {
  runApp(MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Demo'),
          centerTitle: true,
        ),
        body: ContentWidget(),
        // 显示右下角按钮
        floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: () {
              print("ces");
            }),
      ),
    );
  }
}

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

  
  State<StatefulWidget> createState() {
    return ContentWidgetState();
  }
}

class ContentWidgetState extends State<ContentWidget> {
  int count = 0;

  
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        // 居中
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          // 一行
          Row(
            // 居中
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // 按钮 
              ElevatedButton(
                onPressed: () {
                  // 处理按钮点击事件
                  setState(() {
                    count--;
                  });
                },
                child: Text('点击我-1'),
              ),
              // 按钮
              ElevatedButton(
                onPressed: () {
                  // 处理按钮点击事件
                  setState(() {
                    count++;
                  });
                },
                child: Text('点击我+1'),
              ),
            ],
          ),
          Text("当前计数:$count", style: TextStyle(fontSize: 25))
        ]
      ),
    );
  }
}

显示如图所示:
在这里插入图片描述

三、基础 widget

3.1 Text文本

3.1.1 示例

Text(
  'Hello World \n 测试1 \n 测试2',
  style: TextStyle(
      fontSize: 24,
      // Color(0xargb)  透明度a 红色r 绿色g 蓝色b
      color: Color(0xffff0000),
  ),
  textAlign: TextAlign.center, // 文字居中
  maxLines: 2, // 最大行数
  overflow: TextOverflow.ellipsis, // 超出显示省略号
  textScaler: TextScaler.linear(2), // 文字缩放
);

3.1.2 Text.rich

Row(
  // 一行中居中
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text.rich(
        TextSpan(
          children: [
            TextSpan(text: "《Hello World》", style: TextStyle(fontSize: 30)),
            TextSpan(text: "mhua", style: TextStyle(fontSize: 20, color: Colors.red)),
            TextSpan(text:"\n测试数据11111111, 测试数据22222222, \n测试数据33333333, 测试数据4444444")
          ],
        ),
      textAlign: TextAlign.center,
    ),
  ],
);

效果如下:
在这里插入图片描述


3.2 按钮

3.2.1 示例

import 'package:flutter/material.dart';

void main () {
  runApp(MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Demo'),
          centerTitle: true,
        ),
        body: ContentWidget(),
      ),
    );
  }
}

// 自定义按钮
class TestButton extends StatelessWidget {
  const TestButton({super.key});

  
  Widget build(BuildContext context) {
    return  ElevatedButton(
      onPressed: () {
        print('Button clicked');
      },
      style: ButtonStyle(
        // 背景颜色
        backgroundColor: WidgetStateProperty.all(Colors.blue),
        // 文字颜色
        foregroundColor: WidgetStateProperty.all(Colors.white)
      ),
      child: Row(
        // 宽度尽可能小的
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.add),
          // 添加一个空隙
          SizedBox(width: 10),
          Text('Click me'),
        ],
      ),
    );
  }
}

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

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 自带 Material Design 风格背景色和阴影效果
        ElevatedButton(
            child: Text("ElevatedButton"),
            // 设置圆角
            style: ButtonStyle(
              shape: WidgetStateProperty.all(
                  BeveledRectangleBorder(borderRadius: BorderRadius.circular(6))
              ),
            ),
            onPressed: () {
              print("ElevatedButton");
            }
        ),
        // 圆形悬浮按钮,通常用于主操作(如“新建”),支持扩展样式
        FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: () => print("FloatingActionButton")
        ),
        // 纯文本按钮
        TextButton(
            child: Text("TextButton"),
            onPressed: () => print("TextButton")
        ),
        // 带边框的按钮,默认透明背景,按下时边框高亮并显示阴影
        OutlinedButton(
            child: Text("OutlinedButton"),
            onPressed: () => print("OutlinedButton")
        ),
        IconButton(
          icon: Icon(Icons.thumb_up),
          onPressed: () {},
        ),
        // 自定义按钮
        TestButton()
      ]
    );
  }
}

效果如下:
在这里插入图片描述

3.3 图片

3.3.1 加载网络图片

Image.network("https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k")

3.3.2 加载本地图片

  1. assets目录 在根目录下
Image.asset("assets/images/1.jpg")

注意:需要在pubspec.yaml配置图片路径才可以正常使用
在这里插入图片描述


3.3.3 图片缩放模式

默认显示格式如下图:
在这里插入图片描述

BoxFit.fill

拉伸填充满空间,图片会出现变形。

Image.network(
  "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k",
   fit: BoxFit.fill,
)

效果图:
在这里插入图片描述

BoxFit.cover

图片等比例拉伸,不会变形,多出的部分会被裁剪。

Image.network(
  "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k",
   fit: BoxFit.cover,
)

效果图:
在这里插入图片描述

BoxFit.contain

默认值,图片不会变形,自适应父容器并且会完整显示出来。

Image.network(
  "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k",
   fit: BoxFit.contain,
)

效果图:
在这里插入图片描述

BoxFit.fitWidth

图片宽度会填充满父容器的宽度,高度等比例缩放,图片不会变形,超过空间的部分会被裁剪。

Image.network(
  "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k",
   fit: BoxFit.fitWidth,
)

效果图:
在这里插入图片描述

BoxFit.fitHeight

图片高度会填充满父容器的高度,宽度等比例缩放,图片不会变形,超过空间的部分会被裁剪。

Image.network(
  "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k",
   fit: BoxFit.fitHeight,
)

效果图:
在这里插入图片描述

3.3.4 重复模式

Image.network(
    "https://fastly.picsum.photos/id/866/4704/3136.jpg?hmac=I55vcxY9Vt3jgVTWqY8GjooRixzyYFPojxuMdtpIy9k",
    repeat: ImageRepeat.repeatY,
)
  • repeat 图片沿着 YX 轴 重复
  • repeatY 图片沿着 Y 轴 重复
  • repeatX 图片沿着 X 轴 重复
  • noRepeat 不重复,只显示一张图片

3.3.5 圆角图片

默认效果:
在这里插入图片描述

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

  
  Widget build(BuildContext context) {
    return Center(
      child: ClipOval(
        child: Image.asset(
            "assets/images/2.png",
            width: 150,
            height: 150,
        )
      ),
    );
  }
}

效果图:
在这里插入图片描述

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

  
  Widget build(BuildContext context) {
    return Center(
      child: ClipRRect(
        // 设置圆角
        borderRadius: BorderRadius.circular(20),
        child: Image.asset(
          "assets/images/2.png",
          width: 150,
          height: 150,
        ),
      )
    );
  }
}

在这里插入图片描述

3.4 表单

3.4.1 TextField

class RegisterWidgetState extends State<RegisterWidget> {

  final textEditingController = TextEditingController();

  
  void initState() {
    super.initState();
    textEditingController.text = "设置默认值";
    textEditingController.addListener(() {
      print("监听值的改变 ${textEditingController.text}");
    });
  }

  
  Widget build(BuildContext context) {
   return Center(
     child: Padding(
       padding: const EdgeInsets.all(20),
       child: Column(
         children: <Widget>[
           TextField(
             decoration: InputDecoration(
               icon: Icon(Icons.person),
               hintText: '请输入用户名',
               labelText: '用户名',
               // 设置边框颜色
               border: OutlineInputBorder(
                 borderSide: BorderSide(
                   color: Colors.blue,
                   width: 1
                 )
               ),
               // 填充输入框背景颜色
               filled: true,
               fillColor: Colors.blue,
             ),
             onChanged: (value) {
               print(value);
             },
             controller: textEditingController,
           ),
         ],
       ),
     )
   );
  }
}

效果图:
在这里插入图片描述

3.4.2 Form

  • 实例代码
class LoginWidgetState extends State<LoginWidget> {

  String username = '';
  String password = '';

  GlobalKey<FormState> formGlobalKey = GlobalKey();

  
  Widget build(BuildContext context) {
   return Form(
      key: formGlobalKey,
       child: Column(
         children: <Widget>[
           TextFormField(
             decoration: InputDecoration(
               labelText: '用户名',
               hintText: '请输入用户名',
               icon: Icon(Icons.person),
             ),
             onSaved: (value) {
               username = value!;
             },
             autovalidateMode: AutovalidateMode.always,
             validator: (value) {
               if (value == null || value.isEmpty) {
                 return '请输入账号';
               }
               return null;
             },
           ),
           TextFormField(
             obscureText: true,
             autovalidateMode: AutovalidateMode.always,
             decoration: InputDecoration(
               labelText: '密码',
               hintText: '请输入密码',
               icon: Icon(Icons.lock),
             ),
             onSaved: (value) {
               password = value!;
             },
             validator: (value) {
               if (value == null || value.isEmpty) {
                 return '请输入密码';
               }
               return null;
             },
           ),
           Container(
             // 尽可能 width 覆盖父容器
             width: double.infinity,
             padding: EdgeInsets.all(16.0),
             child: ElevatedButton(
               style: ButtonStyle(
                // 背景颜色
                backgroundColor: WidgetStateProperty.all(Colors.blue),
                // 文字颜色
                foregroundColor: WidgetStateProperty.all(Colors.white)
               ),
               child: Text('登录', style: TextStyle(fontSize: 16.0),),
               onPressed: () {
                 if (formGlobalKey.currentState != null) {
                   formGlobalKey.currentState!.save();
                   formGlobalKey.currentState!.validate();
                   print('用户名:$username, 密码:$password');
                 }
                 print('登录');
               },
             ),
           )
         ],
       )
   );
  }
}
  • 定义 Form 的key 属性
    在这里插入图片描述

  • 点击登录按钮触发 form 的 formGlobalKey.currentState!.save() 事件

  • formGlobalKey.currentState!.save() 事件会触发 TextFormField 下的 onSaved 事件,onSaved 事件,给变量赋值。
    在这里插入图片描述

  • formGlobalKey.currentState!.save() 调用之后,就能获取变量值
    在这里插入图片描述

  • 表单校验,formGlobalKey.currentState!.validate() 会触发 validator 校验
    在这里插入图片描述

  • 表单自动校验,输入文字的时候就会触发校验。
    在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到