输入和选择

在前面的文章中我们学习了Flutter中事件的处理,包括组件的单击、双击、长按、滑动等。想必大家多其已经有了一定的认识。

那么,这节我们主要介绍下Flutter中输入和选择组件的用法。

TextField

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

TextField的构造方法:

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

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、标签文字等。

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是用户提交而触发的回调。

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

onChanged: (String str){

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

每当用户改变输入框内的文字,都会在控制台输出现在的字符串 当用户点击提交按钮(输入法回车键)

再来看下效果:

控制台输出:

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,大家在这里不需要了解太多,以后会具体介绍的。

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

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,没错就是我们常用的复选框,具体的用法也很简单的

构造方法:

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

直接看代码看用法:

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中,只能有一个选中的。

构造方法:

const Radio({
Key key,
@required this.value,
@required this.groupValue,
@required this.onChanged,
this.activeColor
})

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

还是来看代码:

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翻译过来就是开关的意思,就是控制开关。和Ios和Android中的Switch组件类似

构造方法如下

const Switch({
Key key,
@required this.value,
@required this.onChanged,
this.activeColor,
this.activeTrackColor,
this.inactiveThumbColor,
this.inactiveTrackColor,
this.activeThumbImage,
this.inactiveThumbImage
})

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

还是来看下基本的用法:

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滑块组件,也类似于进度条组件,用法依旧很简单。

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,
})

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

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

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是对相应组件的封装

试一试

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

最近大家都在说公众号上阅读不方便,会把文章同步到网站上(http://flutter.link),点击阅读原文即可查看。

当然,有什么问题也欢迎大家在后台留言,我会在看到的第一时间回复大家的

我怀疑这个是个坏掉的二维码,分享到朋友圈试试?

原文发布于微信公众号 - flutter开发者(Flutter_Developers)

原文发表时间:2018-03-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券