【Flutter】之自带组件(覆盖 80%场景使用的基础组件,带完整示例)
前言
在之前的文章中讲到关于
Dart语言和Flutter周边的安装,那么现在我们全部就已经就绪,现在就可以开始开发了。本篇文章是分享一下关于Flutter自带的组件,因为Flutter官方文档使用的是英文,市面上一些关于Flutter的介绍文章也都较为碎片化,只能一边查一边写,很浪费时间,所以我就将我用到的都总结在这里,随着我用的越多,文章也会持续更新,欢迎各位监督。更新日期:2022-12-02
UI 样式用 Material,还是 Cupertino ?
Flutter中包含两套风格的组件,分别是Material和Cupertino,Cupertino是iOS风格的组件,命名都带Cupertino前缀,比如CupertinoSlider、CupertinoDatePicker等,Material Design是由
本篇着重分享就 Material 类型的样式!!!
Material 风格使用
- 导入
import 'package:flutter/material.dart';
- 添加
void main() => runApp(new App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp();
}
}
MaterialApp
一个
MaterialApp一般包含如下两部分:
MaterialApp(
title: 'Flutter',
home: new Scaffold(
),
)
其中home是我们App中可以看见的元素部分。
Scaffold 框架
Scaffold是Material library中提供的一个widget,它提供了最基本的页面布局结构,有导航栏、标题、滑出的抽屉、底部导航、背景颜色以及最重要的主屏幕body等。widget树可以很复杂。简单的例子如下:
Scaffold(
appBar: AppBar(title: const Text('标题')),
body: const Center(
child: Text('内容'),
))...
效果如下:

注意: 当一个页面只可以用一个Scaffold,避免嵌套组件多处使用。
第一个hello word
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: const Text('hellow,world'),
),
body: const Center(child: Text('hellow world imook')),
),
);
}
}

AppBar 顶部导航栏
title: 顶部的名称elevation: 阴影centerTitle:是否居中leading: 左侧的操作按钮,平常用作返回按钮actions: 右侧的操作按钮,可以是多个backgroundColor:更改appbar的主题颜色
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('标题'),
elevation: 10.0,
centerTitle: true,
leading: const BackButton(),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.menu),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.add),
onPressed: () {},
)
],
),
body: const Center(
child: Text('内容'),
));
}
}

appbar的主题颜色默认是蓝色,当然也是可以更改的:

Text 文本显示组件
最常用的组件,没有之一,一般作为子组件用在需要文字显示的地方。
最基础的使用:
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('内容'),
));
}
}

style 文字样式
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text(
'内容',
style: TextStyle(
color: Colors.red
),
),
));
}
}

添加方式如上,以下示例将用伪代码代替,为了看起来方便,下面字体都加大了:
fontSize 字体大小
style: TextStyle(
fontSize: 30.0,
),

fontStyle 字体样式
FontStyle.italic斜体
style: TextStyle(
fontSize: 30.0,
fontStyle: FontStyle.italic,
),

FontStyle.normal普通,无样式
style: TextStyle(
fontSize: 30.0,
fontStyle: FontStyle.normal,
),

fontWeight 字体粗细
FontWeight.bold加粗,等同于FontWeight.w700
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
),

FontWeight.normal普通样式,无加粗
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.normal,
),

除了上面的两种模式,FontWeight 还有从w100 -- w900的枚举,供我们使用:
FontWeight.w100最细
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w100,
),

FontWeight.w900最粗,要比FontWeight.bold还要粗
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900,
),

decoration 装饰器
顾名思义就是给字体加一些额外的样式,下划线,删除线等。
TextDecoration.lineThrough删除线
style: TextStyle(
fontSize: 30.0,
decoration: TextDecoration.lineThrough,
),

TextDecoration.overline文字上划线
style: TextStyle(
fontSize: 30.0,
decoration: TextDecoration.overline,
),

TextDecoration.underline文字下划线
style: TextStyle(
fontSize: 30.0,
decoration: TextDecoration.underline,
),

TextDecoration.none无任何装饰
style: TextStyle(
fontSize: 30.0,
decoration: TextDecoration.none,
),

以下介绍的几个属性并不在style里面,而是写在外面的属性
textAlign 文字对齐方式
TextAlign.right右对齐
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.pink,
margin: const EdgeInsets.only(top: 100),
child: const Text(
'内容',
style: TextStyle(
fontSize: 30.0,
),
textAlign: TextAlign.right,
),
));
}
}

TextAlign.left左对齐
textAlign: TextAlign.left

TextAlign.center左对齐
textAlign: TextAlign.center

start 和 end 取决于TextDirection,如果是TextDirection.ltr,开始是左边,如果TextDirection.rtl,开始是右边
TextAlign.start以开始位置为对齐方式
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 50.0,
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world China,hellow world China hellow world China hellow world China hellow world China hellow world Chinahellow world Chinahellow world Chinahellow world iChina',
textDirection: TextDirection.rtl,
textAlign: TextAlign.start,
style: TextStyle(
fontSize: 20.0,
color: Colors.pink,
),
)),
);
}
}

TextAlign.end以结束位置为对齐方式
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 50.0,
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world China,hellow world China hellow world China hellow world China hellow world China hellow world Chinahellow world Chinahellow world Chinahellow world iChina',
textDirection: TextDirection.rtl,
textAlign: TextAlign.end,
style: TextStyle(
fontSize: 20.0,
color: Colors.pink,
),
)),
);
}
}

TextAlign.justify两端对齐方式
不要给父级定义宽高,不然不生效,而且两端对齐只对首行生效
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world China,hellow world China hellow world Chinahellow world Chinahellow world Chinahellow world iChina',
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 20.0,
color: Colors.pink,
),
)),
);
}
}

maxLines 最大行数
设置当前显示最多的行数
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world China,hellow world China hellow world China hellow world China hellow world China hellow world Chinahellow world Chinahellow world Chinahellow world iChina',
maxLines: 2,
style: TextStyle(
fontSize: 20.0,
color: Colors.pink,
),
)),
);
}
}

overflow 文本溢出
TextOverflow.ellipsis超出内容省略显示
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world China,hellow world China hellow world China hellow world China hellow world China hellow world Chinahellow world Chinahellow world Chinahellow world iChina',
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 20.0,
color: Colors.pink,
),
)),
);
}
}

TextOverflow.fade超出内容淡入透明
overflow: TextOverflow.fade

TextOverflow.visible默认显示
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 50.0,
color: Colors.amber,
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world China,hellow world China hellow world China hellow world China hellow world China hellow world Chinahellow world Chinahellow world Chinahellow world iChina',
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 20.0,
color: Colors.pink,
),
)),
);
}
}

TextOverflow.clip对超出部分进行裁切
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 50.0,
color: Colors.amber,
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world China,hellow world China hellow world China hellow world China hellow world China hellow world Chinahellow world Chinahellow world Chinahellow world iChina',
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 20.0,
color: Colors.pink,
),
)),
);
}
}

img 图片
加入的几种形式:
asset 加载资源图片,会使打包时包体过大
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
alignment: Alignment.topCenter,
margin: const EdgeInsets.only(top: 100),
child: Image.asset(
'assets/images/rongxin_icon.png',
height: 200.0,
width: 300.0,
fit: BoxFit.fill,
)),
);
}
}

network 网络资源图片,经常换的或者动态的图片
import 'package:flutter/material.dart';
// 扁平化风格
void main() => runApp(const APage());
class APage extends StatelessWidget {
const APage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'cont',
home: Scaffold(
appBar: AppBar(
title: const Text('img'),
),
body: Center(
child: Container(
child: Image.network(
'https://fanyi-cdn.cdn.bcebos.com/static/translation/img/header/logo_e835568.png',
scale: 1.5,
// fit: BoxFit.fitWidth, // 图片充满样式
// color: Colors.green,
// colorBlendMode: BlendMode.srcATop, // 图片混合叠加模式
repeat: ImageRepeat.repeatX, // 图片重复样式
),
width: 300.0,
height: 200.0,
color: Colors.lightGreen,
)),
),
);
}
}

file本地图片,比如相机照相后的图片预览memory加载到内存中的图片,Uint8List
Icon 图标
更多图标地址:跳转链接

示例:
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Icon(
Icons.fingerprint,
size: 40,
color: Colors.red,
semanticLabel: 'fingerprint',
),
));
}
}

Button
根据用途和使用场景不同,分为多个不同的button 类型,整理中也发现有些button 已经不维护了,当然也有代替它的使用
废弃的Button 代替的Button
RaisedButton => ElevatedButton
FlatButton => TextButton
OutlineButton => OutlinedButton
ElevatedButton 按钮
ElevatedButton是一个凸起的Material矩形按钮,可以使用提升的按钮为原本基本平坦的布局添加维度,例如在长列表中,或在广阔的空间中。避免在已经提升的内容(如对话框或卡片)上使用提升按钮
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.all(40.0),
child: ElevatedButton(
child: const Text('按钮'),
onPressed: () {
print('点击事件');
},
)),
);
}
}

IconButton 图标按钮
为配合展示,给容器加了宽高和背景,这些不是按钮的,按钮只有图标
import 'package:flutter/material.dart';
import 'package:ytxim_flutter_sdk_example/resource/icons/iconfont_line.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.blue,
margin: const EdgeInsets.all(40.0),
child: IconButton(
icon: const Icon(
IconFontLine.icon_plus,
color: Colors.white,
size: 30.0,
),
onPressed: () => {print('22')},
),
),
);
}
}

TextButton 文字按钮
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.all(40.0),
child: TextButton(
onPressed: () {
print('点击事件');
},
child: const Text('确定'),
style: ButtonStyle(
textStyle: MaterialStateProperty.all(
const TextStyle(color: Colors.blue, fontSize: 20.0)))),
),
);
}
}

OutlinedButton 带边框的按钮
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.only(top: 100.0),
child: OutlinedButton(
child: const Text('Button'),
onPressed: () {
print('点击事件');
},
)));
}
}

TextField 输入框
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
TextEditingController contr = TextEditingController();
final focusNode = FocusNode();
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(),
)));
}
}

autofocus 获取焦点
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
TextEditingController contr = TextEditingController();
final focusNode = FocusNode();
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(
autofocus: true,
),
)));
}
}

maxLength 内容最长字数,字数统计
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
TextEditingController contr = TextEditingController();
final focusNode = FocusNode();
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(
autofocus: true,
maxLength: 20,
),
)));
}
}

minLines最小行数maxLines最大行数
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 250.0,
child: TextField(
minLines: 1,
maxLines: 3,
),
),
));
}
}

decoration 装饰器
hintText当输入框为空时的提示,不为空时不显示,hintStyle是hintText的文字样式
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(
decoration: InputDecoration(
hintText: '请输入',
hintStyle: TextStyle(fontSize: 20.0, color: Colors.blue),
),
),
)));
}
}

error错误样式
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(
decoration: InputDecoration(
errorText: '邮箱输入错误',
errorStyle: TextStyle(fontSize: 20),
errorMaxLines: 1,
errorBorder:
OutlineInputBorder(borderSide: BorderSide(color: Colors.red)),
),
),
)));
}
}

labelText标签
当输入框是空而且没有焦点时,labelText显示在输入框上边,当获取焦点或者不为空时labelText往上移动一点,
labelStyle参数表示文本样式,具体参考TextStyle
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
TextEditingController contr = TextEditingController();
final focusNode = FocusNode();
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(
decoration: InputDecoration(
labelText: '邮箱:',
labelStyle: TextStyle(fontSize: 20.0, color: Colors.blue),
),
),
)));
}
}
获取焦点前

获取焦点后:

prefix前缀
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(
decoration: InputDecoration(prefixIcon: Icon(Icons.person)),
),
)));
}
}

suffix后缀,接收一个widget,suffixIcon接收一个Icon的widget
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
child: TextField(
decoration: InputDecoration(
suffixIcon: Icon(Icons.fingerprint),
suffix: Text('.com'),
),
),
)));
}
}

filled重写输入框
filled为true时,输入框将会被fillColor填充
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 250.0,
child: TextField(
decoration: InputDecoration(
fillColor: Color(0x30cccccc),
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0x00FF0000)),
borderRadius: BorderRadius.all(Radius.circular(100))),
hintText: '身份证号/手机号/邮箱',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0x00000000)),
borderRadius: BorderRadius.all(Radius.circular(100))),
)),
),
));
}
}

- border 边框,默认是带下边框,可以设置不带边框
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: SizedBox(
width: 250.0,
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
),
// autofocus: true,
),
),
));
}
}

controller 控制器
控制器可以同步拿到输入时回调,用在输入时校验
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
Index({Key? key}) : super(key: key);
TextEditingController resCtrl = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: 250.0,
child: TextField(
controller: resCtrl,
autofocus: true,
onChanged: (value) {
resCtrl.text = value;
print(value);
},
),
),
));
}
}

Container 容器组件
在容器组件里最常用的则是Container,类似
div
width宽height高color容器填充颜色child容器的内容区域
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.lightBlue,
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

alignment 内容对齐方式,以容器为框,进行对齐
Alignment.topCenter顶部居中对齐
当前效果基本等同于 textAlign: TextAlign.center
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.lightBlue,
alignment: Alignment.topCenter,
margin: const EdgeInsets.only(top: 100),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

Alignment.topLeft顶部左对齐
alignment: Alignment.topLeft,

Alignment.topRight顶部右对齐
alignment: Alignment.topRight,

Alignment.center上下左右居中
alignment: Alignment.center,

Alignment.centerLeft上下居中左对齐
alignment: Alignment.centerLeft,

Alignment.centerRight上下居中右对齐
alignment: Alignment.centerRight,

Alignment.bottomCenter左右居中+底对齐
alignment: Alignment.bottomCenter,

Alignment.bottomLeft左对齐+底对齐
alignment: Alignment.bottomLeft,

Alignment.bottomRight右对齐+底对齐
alignment: Alignment.bottomRight,

margin && padding 外边距、内边距
在边距赋值处需要用的 EdgeInsets,那就先来看一下 EdgeInsets
EdgeInsets.all()各个方向使用同一组值
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.lightBlue,
margin: const EdgeInsets.all(100.0),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

EdgeInsets.only()可指定方向和值
有
left、right、top、bottom四个方向的值
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.lightBlue,
margin: const EdgeInsets.only(left: 100.0),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

margin外边距
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.lightBlue,
margin: const EdgeInsets.only(top: 100.0),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

padding内边距
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
color: Colors.lightBlue,
padding: const EdgeInsets.all(70.0),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}
从结果可以看出来,里面的内容已经被挤的有些部分看不到了

decoration 装饰器
color这个颜色和外层的颜色是二选一的,如果装饰器里面设置了颜色,外面就不能设置
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
alignment: Alignment.topCenter,
margin: const EdgeInsets.only(top: 40.0),
decoration: const BoxDecoration(color: Colors.red),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

border边框
可以给某个方向添加边框,添加边框的颜色,粗细
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
alignment: Alignment.topCenter,
margin: const EdgeInsets.all(100.0),
decoration: const BoxDecoration(
border: Border(
top: BorderSide.none,
bottom: BorderSide(color: Colors.pink, width: 10.0),
left: BorderSide(color: Colors.green),
right: BorderSide(color: Colors.yellow))),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

gradient填充框时使用的渐变
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
margin: const EdgeInsets.all(40.0),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Colors.lightBlue, Colors.pink, Colors.yellow]),
),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

borderRadius边缘圆角
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
margin: const EdgeInsets.all(40.0),
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8),
topRight: Radius.circular(8),
)),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

image添加背景图片
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
margin: const EdgeInsets.all(40.0),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/icon.png',
),
fit: BoxFit.contain,
),
),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

boxShadow阴影
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 200.0,
height: 200.0,
margin: const EdgeInsets.all(40.0),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: const Color.fromARGB(255, 203, 52, 52).withOpacity(0.15),
offset: const Offset(0, 1),
spreadRadius: 0,
blurRadius: 4,
)
],
),
child: const Text(
'hellow world',
style: TextStyle(
fontSize: 20.0,
),
)),
);
}
}

SizedBox 有固定宽高的盒子容器
是上面Container 的简单版本
width宽height高
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.only(top: 100.0),
child: const SizedBox(
width: 100.0,
height: 100.0,
child: Text('我是内容,我是内容,我是内容,我是内容,我是内容,我是内容'),
),
));
}
}

GestureDetector 手势识别
可以识别点击、双击、长按事件、拖动、缩放等手势。
onTap 点击事件
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTapDown: (TapDownDetails tapDownDetails) {
print('按下时');
},
onTapUp: (TapUpDetails tapUpDetails) {
print('抬起时');
},
onTap: () {
print('点击时');
},
onTapCancel: () {
print('点击取消');
},
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
),
));
}
}
点击时的事件触发的先后顺序为:按下时 -> 抬起时 -> 点击时

点击拖动时的事件触发的先后顺序为:按下时 -> 点击取消

onDoubleTap 双击事件
onDoubleTap: () {
print('双击');
},

onLongPress 长按事件
onLongPressStart: (v) {
print('开始长按');
},
onLongPressMoveUpdate: (v) {
print('长按移动');
},
onLongPressUp: () {
print('长按抬起');
},
onLongPressEnd: (v) {
print('长按结束');
},
onLongPress: () {
print('长按');
},
长按时的事件触发的先后顺序为:按下时 ->点击取消 -> 开始长按 -> 长按 -> 长按结束 -> 长按抬起

长按后移动的事件触发的先后顺序为:按下时 -> 点击取消 -> 开始长按 -> 长按 -> 长按移动 -> 长按结束 -> 长按抬起

onScale 缩放事件
onScaleStart: (v) {
print('开始缩放');
},
onScaleUpdate: (v) {
print('缩放更新');
},
onScaleEnd: (v) {
print('开始缩放');
},
缩放的事件触发的先后顺序为:**按下时 -> 点击取消 -> 开始缩放 -> 缩放更新 -> 结束缩放 **

Column 列表
children接收的是一个数组
import 'package:flutter/material.dart';
class APage extends StatelessWidget {
const APage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('A页面')),
body: Center(
child: Column(children: [
ElevatedButton(
onPressed: () {
print('1');
},
child: const Text('按钮1')),
ElevatedButton(
onPressed: () {
print('2');
},
child: const Text('按钮2')),
])),
);
}
}

Center 居中布局
常用于我们需要居中的样式
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(child: Text('我是内容')),
);
}
}

Row 水平布局
接收一个数组,可平铺多个
widget
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: <Widget>[
Container(
height: 50,
width: 100,
color: Colors.red,
),
Container(
height: 50,
width: 100,
color: Colors.green,
),
Container(
height: 50,
width: 100,
color: Colors.blue,
),
],
)));
}
}

mainAxisAlignment 对齐方式
- start
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
height: 50,
width: 100,
color: Colors.red,
),
Container(
height: 50,
width: 100,
color: Colors.green,
),
Container(
height: 50,
width: 100,
color: Colors.blue,
),
],
)));
}
}

- center 居中
mainAxisAlignment: MainAxisAlignment.center,

- end 以结束位置对齐
mainAxisAlignment: MainAxisAlignment.end,

- spaceAround 分散对齐
mainAxisAlignment: MainAxisAlignment.spaceAround,

- spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceBetween,

-spaceEvenly
mainAxisAlignment: MainAxisAlignment.spaceEvenly,

spaceAround和spaceEvenly区别是:
-
spaceAround:第一个子控件距开始位置和最后一个子控件距结尾位置是其他子控件间距的一半。 -
spaceEvenly:所有间距一样。
crossAxisAlignment
- start
crossAxisAlignment: CrossAxisAlignment.start,

- center
crossAxisAlignment: CrossAxisAlignment.center,

- end
crossAxisAlignment: CrossAxisAlignment.end,

- stretch
crossAxisAlignment: CrossAxisAlignment.stretch,

textDirection 排列方向
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
textDirection: TextDirection.rtl,
children: <Widget>[
Container(
height: 50,
width: 100,
color: Colors.red,
),
Container(
height: 100,
width: 100,
color: Colors.green,
),
Container(
height: 150,
width: 100,
color: Colors.blue,
),
],
));
}
}

mainAxisSize
主轴尺寸由
mainAxisSize属性控制,仅有min和max两种方式,默认是max方法。min表示尽可能小,而max表示尽可能大
import 'package:flutter/material.dart';
class Index extends StatelessWidget {
const Index({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: const EdgeInsets.only(top: 100),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: 50,
width: 100,
color: Colors.red,
),
Container(
height: 50,
width: 100,
color: Colors.green,
),
Container(
height: 50,
width: 100,
color: Colors.blue,
),
],
),
));
}
}

路由配置
新建
3个同级页面,来回跳转
Navigator.push 即可跳转到指定页面
Navigator.pop 则会回退一页
APage:
import 'package:flutter/material.dart';
import './B_page.dart';
class APage extends StatelessWidget {
const APage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('A页面')),
body: Center(
child: Column(children: [
ElevatedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const BPage();
}));
},
child: const Text('go Bpage')),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('go back')),
])),
);
}
}
A 页面展示:

BPage:
import 'package:flutter/material.dart';
import './C_page.dart';
class BPage extends StatelessWidget {
const BPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('B页面')),
body: Center(
child: ElevatedButton(
child: const Text(
'go Cpage',
),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const CPage();
}));
},
)),
);
}
}
B 页面展示:

CPage:
import 'package:flutter/material.dart';
class CPage extends StatelessWidget {
const CPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('C页面')),
body: Center(
child: ElevatedButton(
child: const Text(
'go back',
),
onPressed: () {
Navigator.pop(context);
},
)),
);
}
}
C 页面展示:

路由传参数
首先组件需要是
StatefulWidget有状态组件
现在我们模拟从A页面跳转到B页面,在跳转过程中传参数,在B页面收到A的参数
import 'package:flutter/material.dart';
import 'B_page.dart';
class APage extends StatefulWidget {
const APage({Key? key}) : super(key: key);
@override
State<APage> createState() => APageContent();
}
class APageContent extends State<APage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('A页面')),
body: Center(
child: Column(children: [
ElevatedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return BPage(
name: '哈哈哈哈',
);
}));
},
child: const Text('跳转到B页面,并携带参数name')),
);
}
}

B页面
import 'package:flutter/material.dart';
import './C_page.dart';
class BPage extends StatefulWidget {
String name;
BPage({Key? key, required this.name}) : super(key: key);
@override
State<BPage> createState() => BPageContent();
}
class BPageContent extends State<BPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('B页面')),
body: Center(
child: ElevatedButton(
child: Text(
'参数值 ${widget.name}',
),
onPressed: () {
print('参数值${widget.name}');
},
)),
);
}
}

那我们
B跳转回A页面时如何给A页面回参呢?
A 页面:
import 'package:flutter/material.dart';
import 'B_page.dart';
class APage extends StatefulWidget {
const APage({Key? key}) : super(key: key);
@override
State<APage> createState() => APageContent();
}
class APageContent extends State<APage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('A页面')),
body: Center(
child: Column(children: [
ElevatedButton(
onPressed: () {
// 在这里定义返回结果
var result =
Navigator.push(context, MaterialPageRoute(builder: (context) {
return BPage(
name: '哈哈哈哈',
);
}));
result.then((value) => print(('$value')));
},
child: const Text('跳转到B页面,并携带参数name')),
])),
);
}
}
B页面:
import 'package:flutter/material.dart';
class BPage extends StatefulWidget {
String name;
BPage({Key? key, required this.name}) : super(key: key);
@override
State<BPage> createState() => BPageContent();
}
class BPageContent extends State<BPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('B页面')),
body: Center(
child: ElevatedButton(
child: Text(
'参数值 ${widget.name}',
),
onPressed: () {
Navigator.pop(context, '清凉');
},
)),
);
}
}

命名路由
我们每次使用
Navigator跳转要传一大堆参数,还要修改类的结构,我们有没有方法把路由的内容抽出来?那是当然有
根文件:
import 'package:flutter/material.dart';
import './src/pages/connect/login_view.dart';
import 'package:im_flutter_demo/src/pages/home/home_view.dart';
import 'src/pages/connect/A_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// root
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'App名称',
debugShowCheckedModeBanner: false,
home: const LoginPages(),
routes: {
'/A': (context) => const APage(),
'/home': (context) => const HomePage(),
},
);
}
}
A页面:
import 'package:flutter/material.dart';
import '../home/home_view.dart';
import './A_page.dart';
class LoginPages extends StatefulWidget {
const LoginPages({Key? key}) : super(key: key);
@override
State<LoginPages> createState() => LoginContent();
}
class LoginContent extends State<LoginPages> {
String _result = '';
Future<void> _incrementCounter() {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'loginpage',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Container(
child: Column(children: <Widget>[
ElevatedButton.icon(
onPressed: () {
// 此处直接用 Navigator.pushNamed ,后面第二个参数就是跳转的路由地址,即可完成跳转
Navigator.pushNamed(context, '/home');
},
icon: const Icon(Icons.home),
label: const Text('home')),
ElevatedButton.icon(
onPressed: () {
Navigator.pushNamed(context, '/A');
},
icon: const Icon(Icons.backpack),
label: const Text('A')),
]),
alignment: Alignment.topCenter,
margin: const EdgeInsets.all(100.0),
),
),
),
);
}
}
注:这个routes的位置要位于MaterialApp 这个根文件,我试过放在LoginPage 会报错
// 如果需要传参,可通过第三个参数 :arguments 来传输
Navigator.pushNamed(context, '/home', arguments: 'aaa');
路由钩子,特殊匹配
import 'package:flutter/material.dart';
import './src/pages/connect/login_view.dart';
import 'package:im_flutter_demo/src/pages/home/home_view.dart';
import 'src/pages/connect/A_page.dart';
import 'package:im_flutter_demo/src/pages/connect/C_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// root
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'App名称',
debugShowCheckedModeBanner: false,
// 根页面地址
home: const LoginPages(),
// 路由和对应的页面
routes: {
'/A': (context) => const APage(),
'/home': (context) => const HomePage(),
'/login': (context) => const LoginPages(),
},
// 初始化路由位置
initialRoute: '/',
// 钩子中的拦截判断
onGenerateRoute: (RouteSettings settings) {
if (settings.name == '/z') {
return MaterialPageRoute(builder: (context) => const HomePage());
}
return null;
},
// 找不到路由
onUnknownRoute: (RouteSettings settings) {
return MaterialPageRoute(builder: (context) => const CPage());
},
);
}
}
MaterialApp路由匹配规则:
- 路由为'/'时,
home不为null则使用home - 使用
routes指定的路由 - 使用
onGenerateRoute生成的路由,处理除home和routes以外的路由 - 如果上面都不匹配则调用
onUnknownRoute
文章写到这里还没有结束,我会继续更新,如果正在看文章的你有任何疑惑点🤔,欢迎评论区留言。


如果亲感觉我的文章还不错的话,可以一下添加关注哦!
内容还在持续更新中,怕错过更新的点个关注再走呗!点个关注不迷路哦!😄
求内推
注:如果有小伙伴公司正在招聘,可联系我哦,不胜感激!技术栈:react,ts,flutter,antd,webpack...,可以参考我的文章。地点:北京
转载自:https://juejin.cn/post/7153818484554596366