Flutter零基础入门

提示语法错误,检查是否有const修饰,他不能修饰可变的东西。

Flutter项目基本介绍

pubspec.yaml:依赖包管理文件,添加依赖后,点击`Pub get可以进行下载添加的依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: draft #包名或项目名
description: write a draft #项目描述
publish_to: 'none' # 发布包配置,不发布
version: 1.0.0+1 #项目版本
environment: #环境变量
sdk: ">=2.17.1 <3.0.0" #Dart语言版本
dependencies: #应用或包依赖的其他包或插件,会编译到app应用里
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
dev_dependencies: #开发环境依赖的工具包,用于辅助开发和测试,不会编译到app应用里
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter: #flutter相关配置
uses-material-design: true

控件(material

  • TextField 输入框

    1
    2
    3
    4
    5
    6
    7
    child: TextField(
    obscureText: true,
    decoration: InputDecoration(
    border: OutlineInputBorder(), //边框样式
    labelText: '用户名', //提示标签
    ),
    ),
  • Text 文本框

    1
    child: Text("欢迎登录"),
  • TextButton 按钮

    1
    2
    3
    4
    5
    6
    child: TextButton(
    onPressed: (){
    print("点击了");
    },
    child: const Text("登录")
    )
  • Autocomplete 自动补齐输入框框(带下拉搜索输入框)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    child: Autocomplete<Soft>(
    displayStringForOption: (Soft option) => option.name, //输入框显示的值
    optionsBuilder: (TextEditingValue textEditingValue) {
    return HttpUtil().getSoftListString(
    context, "20", textEditingValue.text.toLowerCase());
    }, //选项构建,数据来源支持异步
    fieldViewBuilder: (context, textEditingController, focusNode, onFieldSubmitted) {
    return TextField(
    controller: textEditingController, //传递
    focusNode: focusNode, //传递
    decoration: const InputDecoration(
    border: OutlineInputBorder(), labelText: '软件'),
    ); //自定义样式
    }, //输入框自定义
    onSelected: (Soft selection) {
    versionController.text = selection.version;
    }, //选中回掉
    ),
  • Image图片显示

    1
    Image(image: NetworkImage('url'))
  • GestureDetector 给一个控件添加一个事件

    1
    2
    3
    4
    GestureDetector(
    onTap:() //触摸事件
    child: //给该child添加一个触摸事件
    )

布局(layout

  • Column:列布局

  • Row:行布局

    1
    2
    3
    4
    5
    6
    Column( //或者Row布局
    children: [
    const Text('行一'),
    const Text('行二'),
    ]
    )
  • CustomScrollView:滚动布局

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    1. 继承State
    2. 设置中心key
    3. 触发setState((){num++}) 动态更新布局
    4. 基础结构:
    CustomScrollView
    center:
    slivers:[
    SliverList(key: centerKey,delegate:SliverChildBuilderDelegate(childCount:num)),//num是指重复布局几个
    SliverList()),
    ]

启动类

1
2
3
4
5
6
import 'package:flutter/material.dart';
import 'login.dart';

void main() {
runApp(const Login());
}

一个页面(类)基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import 'package:flutter/material.dart';

class Login extends StatelessWidget {
const Login({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: '登录',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
home: Scaffold(
appBar: AppBar(
title: const Text('登录'),
),
body: Colum(),
),
);
}
}

简单页面跳转

1
2
//跳转到Home页面 
Navigator.push(context, MaterialPageRoute(builder:(context)=> const Home()));

多复杂页面跳转-路由(router)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//-----主页面
void main() {
runApp(MaterialApp(
routes: { //配置路由
'/': (context) => const Home(),
'/login': (context) => const Login(),
},
));
}
//----跳转到登录页面----
Navigator.pushNamed(context, '/login');
//----登录页面退回主页----
Navigator.pop(context);
//---移除当前页面,再加载/页面,可以用于页面刷新
Navigator.pushReplacementNamed(context, '/');

获取输入框的值

  • 方法一:定一个变量,然后通过输入框的onChanged设置值到变量,然后获取

  • 方法二:设置controller

    1
    2
    3
    4
    5
    TextEditingController userNameController =TextEditingController(); //定义controller
    TextField(
    controller: userNameController, //设置controller
    )
    print("输入了${userNameController.text}"); //获取controller的值

toast提示框-fluttertoast

  1. 添加依赖fluttertoast: ^8.0.9
  2. 导包import 'package:fluttertoast/fluttertoast.dart';
  3. 使用Fluttertoast.showToast(msg: "请登录");

网络请求-dio框架

  1. pubspec.yamldependencies下添加依赖dio: ^4.0.6,然后点击文件顶部Pub get更新依赖

  2. 导入包import 'package:dio/dio.dart';

  3. 简单使用

    1
    2
    3
    4
    5
    6
    /// 登录请求
    Future<Response> loginPost(String userName, String password) async {
    Response response = await Dio.post('/api/v1/user/login',
    data: {'username': userName, 'password': password});
    return response;
    }

文件选择-File Picker

1
2
3
///选择图片文件
FilePickerResult? result = await FilePicker.platform
.pickFiles(type: FileType.image);

文件压缩-flutter_native_image

1
2
File compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 50);

缓存-文件模式-shared_preferences

工具类用Sputil

问题

  1. 如下错误:

    1
    2
    Error: Not a constant expression.
    onPressed: (){},

    解决:Not a constant expression 关键字const,使用const修饰的变量及方法不能包含可变的,所以onPressed就不可以使用了,const关键字使用要点

    • 不可修改
    • 编译期初始化
    • const 构造函数
  2. 错误:Navigator operation requested with a context that does not include a Navigator.

    解决:启动类添加MaterialApp包括,修改如下

    1
    2
    3
    4
    5
    void main() {
    runApp(const MaterialApp(
    home: Login(),
    ));
    }
  3. flutter 如何动态更新界面或控件?

    解决:使用setState((){})

  4. flutter如何重新加载主页?

    解决:使用Navigator.pushReplacementNamed();Navigator.popAndPushNamed()

  5. flutter的File Picker如何选择相册?

    解决:设置typeFileType.image,完整示例FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.image);

  6. dio如何开启网络请求日志?

    解决:添加过滤器_dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //debug开启权限日志

  7. flutter如何获取输入框的值,或者动态修改输入框的值?

    解决:添加公共变量TextEditingController versionController = TextEditingController(); 然后在TextField设置controller: versionController,最后在其他地方获取或设置输入框的值versionController.text

  8. Row布局如何按比例分配空间大小?

    解决:添加Expanded包装控件,然后设置flex比例,例如1:2

  9. 如何修改输入框提示文字的颜色?

    解决:添加labelStyle: TextStyle(color: Colors.amberAccent)属性