Flutter开发者

输入和选择

2018-03-26

上期回顾

在前面的文章中我们学习了Flutter中事件的处理,包括组件的单击、双击、长按、滑动等。想必大家多其已经有了一定的认识。那么,这节我们主要介绍下Flutter中输入和选择组件的用法。

TextField

顾名思义文本输入框,类似于Ios中的UITextField和Android中的EditText。主要是为用户提供输入文本提供方便。相信大家在原生客户端上都用过这个功能,就不在做具体介绍了,接下来还是具体介绍下Flutter中TextField的用法。

TextField的构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const TextField({
Key key,
this.controller,//控制器,控制TextField文字
this.focusNode,
this.decoration: const InputDecoration(),//输入器装饰
TextInputType keyboardType: TextInputType.text,//输入的类型
this.style,
this.textAlign: TextAlign.start,//对齐方式
this.autofocus: false,
this.obscureText: false,//是否隐藏输入
this.autocorrect: true,
this.maxLines: 1,
this.maxLength,
this.maxLengthEnforced: true,
this.onChanged,//文字改变触发
this.onSubmitted,//文字提交触发(键盘按键)
this.inputFormatters,
})

先来试试最基本的TextField

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

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyAppState();
}
}

class MyAppState extends State<MyApp> {

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("TextField"),
),
body: new TextField());
}
}


我们增加一个keyboardType属性,把keyboardType设置为TextInputType.number


可以看到每次我们让TextField获得焦点的时候弹出的键盘就变成了数字优先了。

当然,我们也可以为输入框做一些其他的效果,如提示文字,icon、标签文字等。

1
2
3
4
5
6
7
8
new TextField(keyboardType: TextInputType.number,
decoration: new InputDecoration(
contentPadding: const EdgeInsets.only(top: 10.0),
icon: new Icon(Icons.phone),
labelText: "请输入你的手机号",
helperText: "注册时填写的手机号码"),
autofocus: false,
))

我们给上面的代码新增decoration属性,设置相关属性,可以发现当我们的TextField获得焦点时,图标会自动变色,提示文字会自动上移。

接下来,我们来看下onChanged和onSubmitted。onChanged是每次输入框内每次文字变更触发的回调,onSubmitted是用户提交而触发的回调。

在前面代码的基础上新增如下代码:

1
2
3
4
5
6
7
8

onChanged: (String str){

print("用户输入变更:$str");
},
onSubmitted: (String str){
print("用户提交:$str");
},

每当用户改变输入框内的文字,都会在控制台输出现在的字符串

当用户点击提交按钮(输入法回车键)

控制台输出:

1
2
3
4
5
6
7
I/flutter (31747): 用户输入变更:1
I/flutter (31747): 用户输入变更:12
I/flutter (31747): 用户输入变更:123
I/flutter (31747): 用户输入变更:1234
I/flutter (31747): 用户输入变更:12345
I/flutter (31747): 用户输入变更:123456
I/flutter (31747): 用户提交:123456

看了这么多的基础用法,我们还是来看个例子把。

当用户输入 用户名flyou,密码是admin时,提示登录成功,当用户名密码不是此值时提示登录失败。

在这里,我们需要简单介绍下SnackBar

使用 Scaffold.of(context).showSnackBar()即可显示SnackBar,大家在这里不需要了解太多,以后会具体介绍的。

我们还是来看下具体的代码吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyAppState();
}
}

class MyAppState extends State<MyApp> {
//用户名输入框的控制器
TextEditingController _userNameController = new TextEditingController();
//密码输入框的控制器
TextEditingController _userPasswordController = new TextEditingController();

void onTextClear() {
setState(() {
_userNameController.text = "";
_userPasswordController.text = "";
});
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("TextField"),
),
body: new Column(
children: <Widget>[
new TextField(
controller: _userNameController,
decoration: new InputDecoration(
contentPadding: const EdgeInsets.only(top: 10.0),
icon: new Icon(Icons.perm_identity),
labelText: "请输入用户名",
helperText: "注册时填写的名字"),
),
new TextField(
controller: _userPasswordController,
decoration: new InputDecoration(
contentPadding: const EdgeInsets.only(top: 10.0),
icon: new Icon(Icons.lock),
labelText: "请输入密码",
helperText: "登录密码"),
obscureText: true,
),
new Builder(builder: (BuildContext context) {
//监听RaisedButton的点击事件,并做相应的处理
return new RaisedButton(
onPressed: () {
if (_userNameController.text.toString() == 'flyou' &&
_userPasswordController.text.toString() == 'admin') {
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text("登录成功")));
} else {
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text("登录失败,用户名密码有误")));
}
onTextClear();
},
color: Colors.blue,
highlightColor: Colors.lightBlueAccent,
disabledColor: Colors.lightBlueAccent,
child: new Text(
"登录",
style: new TextStyle(color: Colors.white),
));
})
],
));
}
}

在布局上,我们使用一个Column包含了两个TextField和一个RaisedButton。

在逻辑上,每当我们点击下面的按钮都会判断用户名密码是否是flyou和admin,并且使用控制器清空已经输入的用户名和密码。

如果用户输入的用户名等于flyou,密码等于admin则提示“登录成功”,否则提示“登录失败,用户名密码有误”。

代码的逻辑很简单,结合前面的StatefulWidget的用法,看起来也是非常简单的。关于TextField的其他用法就不在一一介绍了,有兴趣的小伙伴可以自己尝试下。

下面我们来你看下Checkbox

Checkbox

Checkbox,没错就是我们常用的复选框,具体的用法也很简单的

构造方法:

1
2
3
4
5
6
const Checkbox({
Key key,
@required this.value,//当前值,是否选中
@required this.onChanged,//选中变更监听
this.activeColor,//选中时的颜色
})

直接看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyAppState();
}
}

class MyAppState extends State<MyApp> {
var _isChecked = true;
onCheckChange(bool isChecked) {
setState(() {
_isChecked = isChecked;
});
}
@override
Widget build(BuildContext context) {

return new Scaffold(
appBar: new AppBar(
title: new Text("CheckBox"),
),
body: new Center(
child: new Checkbox(value: _isChecked, onChanged: onCheckChange),
),
);
}
}

我们在屏幕的正中央放置了一个Checkbox,每当用户点击时就变更选中的状态。

代码很简单,不再做具体介绍了

Radio

没错Radio就是我们常用的单选框的意思,通常Radio都是成组出现的,在一组Radio中,只能有一个选中的。

构造方法:

1
2
3
4
5
6
7
const Radio({
Key key,
@required this.value,
@required this.groupValue,
@required this.onChanged,
this.activeColor
})

构造方法和上面的Checkbox基本类似,只不过比上面的Checkbox多了一个groupValue参数,当然这个参数就是用来控制分组的。

还是来看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyAppState();
}
}

class MyAppState extends State<MyApp> {

int radioValue=0;

void handleRadioValueChanged(int value) {
setState(() {
radioValue = value;
});
}
@override
Widget build(BuildContext context) {

return new Scaffold(
appBar: new AppBar(
title: new Text("CheckBox"),
),
body: new Center(
child: new Column(
children: <Widget>[
new Radio(
value: 0,
groupValue: radioValue,
onChanged: handleRadioValueChanged),
new Radio(
value: 1,
groupValue:radioValue,
onChanged: handleRadioValueChanged),
new Radio(
value: 2,
groupValue: radioValue,
onChanged: handleRadioValueChanged),
new Radio(
value: 3,
groupValue: radioValue,
onChanged: handleRadioValueChanged)
],
)),
);
}
}

我们在Column放了4个Radio,没当点击Radio都会触发handleRadioValueChanged方法来更改当前选中的Radio并且更新选中状态。

看下效果:

接下来我们来看下Switch

Switch

Switch翻译过来就是开关的意思,就是控制开关。和Ios和Android中的Switch组件类似

构造方法如下

1
2
3
4
5
6
7
8
9
10
11
const Switch({
Key key,
@required this.value,
@required this.onChanged,
this.activeColor,
this.activeTrackColor,
this.inactiveThumbColor,
this.inactiveTrackColor,
this.activeThumbImage,
this.inactiveThumbImage
})

已经很简单,只不过多了几个参数用来控制打开和关闭时的颜色或者图片。

还是来看下基本的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyAppState();
}
}

class MyAppState extends State<MyApp> {
var _isChecked = true;

onSwitchChange(bool isChecked) {
setState(() {
print(isChecked);
_isChecked = isChecked;
});
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Switch"),
),
body: new Center(
child: new Switch(value: _isChecked, onChanged: onSwitchChange),
),
);
}
}

看了上面的代码是不是觉得跟CheckBox基本上一模一样呢?

Slider

Slider滑块组件,也类似于进度条组件,用法依旧很简单。

1
2
3
4
5
6
7
8
9
10
11
12
const Slider({
Key key,
@required this.value,
@required this.onChanged,
this.min: 0.0,//最小值
this.max: 1.0,//最小值
this.divisions,
this.label,//标志
this.activeColor,
this.inactiveColor,
this.thumbOpenAtMin: false,
})

由于很简单就直接给大家看代码了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyAppState();
}
}

class MyAppState extends State<MyApp> {
double currentPosition = 66.0;


onSliderChange(double position) {
setState(() {
print(position);
currentPosition = position;

});
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Slider"),
),
body: new Center(
child: new Slider(
label: "进度",
min: 0.0,
max: 100.0,
value: currentPosition,
onChanged: onSliderChange,
),
),
);
}
}

我们设置slider的默认进度为66,每当用户滑动滑块时根据用户的滑动改变滑块的位置。

更多相关Widget

在上面我们分别介绍了,CheckBox、Radio、Switch、的用法,但是这些组件一般不是单独使用的,一般会和Text、Icon或者其他的Widget结合使用。

当然Flutter中为我们内置了多个相关的Widget,例如:

CheckboxListTile、RadioListTile、SwitchListTile,当然这些Widget的用法类似于前面我们说过的ListTitle,只不过在多了一个上面的Widget而已,当然用法也是非常简单的。

我们来看下CheckboxListTile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyAppState();
}
}

class MyAppState extends State<MyApp> {
var _isChecked = true;

onCheckChange(bool isChecked) {
setState(() {
print(isChecked);
_isChecked = isChecked;
});
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("CheckedBoxListTitle"),
),
body: new CheckboxListTile(
value: _isChecked,
onChanged: onCheckChange,
secondary: new Icon(Icons.update,color: Colors.blueAccent,),
title: new Text("新版本自动下载"),
subtitle: new Text("仅在WiFi环境下生效"),

),
);
}
}

同样的每当我们点击CheckBox或者这个CheckboxListTile都会触发CheckBox的相应操作,去改变Checkbox的状态。

RadioListTile和SwitchListTile的用法基本相同,这里就不在具体介绍了,大家可以在下面试一下如何使用。

小结

  • 可以根据TextField的相关属性来完成特定的输入需求
  • CheckBox、Radio、Switch是开发中常用的选择组件
  • Slider滑块组件,可以满足用户对进度的精确控制
  • CheckboxListTile、RadioListTile和SwitchListTile是对相应组件的封装

试一试

根据我们以前学过的东东完成下图效果

实现方法不是唯一的,只要类似就行哦

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

打赏请备注姓名或者昵称,方便我后期统计哦

关注公众号,及时查阅最新文章