表单组件

2019-12-20  本文已影响0人  放肆滴微笑

Flutter 中常见的表单有 TextField 单行文本框,TextField 多行文本框、CheckBox、Radio、Switch、CheckboxListTile、RadioListTile、SwitchListTile、Slide

TextField

属性 描述
maxLines 设置此参数可以把文本框改为多行文本框
onChanged 文本框改变的时候触发的事件
obscureText 把文本框框改为密码框
controller controller 结合 TextEditingController()可以配置表单默认显示的内容,也可以进行赋值
decoration hintText类似 html 中的 placeholder
border 配置文本框边框 OutlineInputBorder 配合使用
labelText lable 的名称
labelStyle 配置 lable 的样式
const TextField({
    Key key,
    this.controller,    //编辑框的控制器,跟文本框的交互一般都通过该属性完成,如果不创建的话默认会自动创建
    this.focusNode,  //用于管理焦点
    this.decoration = const InputDecoration(),   //输入框的装饰器,用来修改外观
    TextInputType keyboardType,   //设置输入类型,不同的输入类型键盘不一样
    this.textInputAction,   //用于控制键盘动作(一般位于右下角,默认是完成)
    this.textCapitalization = TextCapitalization.none,
    this.style,    //输入的文本样式
    this.textAlign = TextAlign.start,   //输入的文本位置
    this.textDirection,    //输入的文字排列方向,一般不会修改这个属性
    this.autofocus = false,   //是否自动获取焦点
    this.obscureText = false,   //是否隐藏输入的文字,一般用在密码输入框中
    this.autocorrect = true,   //是否自动校验
    this.maxLines = 1,   //最大行
    this.maxLength,   //能输入的最大字符个数
    this.maxLengthEnforced = true,  //配合maxLength一起使用,在达到最大长度时是否阻止输入
    this.onChanged,  //输入文本发生变化时的回调
    this.onEditingComplete,   //点击键盘完成按钮时触发的回调,该回调没有参数,(){}
    this.onSubmitted,  //同样是点击键盘完成按钮时触发的回调,该回调有参数,参数即为当前输入框中的值。(String){}
    this.inputFormatters,   //对输入文本的校验
    this.enabled,    //输入框是否可用
    this.cursorWidth = 2.0,  //光标的宽度
    this.cursorRadius,  //光标的圆角
    this.cursorColor,  //光标的颜色
    this.keyboardAppearance,
    this.scrollPadding = const EdgeInsets.all(20.0),
    this.dragStartBehavior = DragStartBehavior.down,
    this.enableInteractiveSelection,
    this.onTap,    //点击输入框时的回调(){}
    this.buildCounter,
  })
InputDecoration({
    this.icon,    //位于装饰器外部和输入框前面的图片
    this.labelText,  //用于描述输入框,例如这个输入框是用来输入用户名还是密码的,当输入框获取焦点时默认会浮动到上方,
    this.labelStyle,  // 控制labelText的样式,接收一个TextStyle类型的值
    this.helperText, //辅助文本,位于输入框下方,如果errorText不为空的话,则helperText不会显示
    this.helperStyle, //helperText的样式
    this.hintText,  //提示文本,位于输入框内部
    this.hintStyle, //hintText的样式
    this.hintMaxLines, //提示信息最大行数
    this.errorText,  //错误信息提示
    this.errorStyle, //errorText的样式
    this.errorMaxLines,   //errorText最大行数
    this.hasFloatingPlaceholder = true,  //labelText是否浮动,默认为true,修改为false则labelText在输入框获取焦点时不会浮动且不显示
    this.isDense,   //改变输入框是否为密集型,默认为false,修改为true时,图标及间距会变小
    this.contentPadding, //内间距
    this.prefixIcon,  //位于输入框内部起始位置的图标。
    this.prefix,   //预先填充的Widget,跟prefixText同时只能出现一个
    this.prefixText,  //预填充的文本,例如手机号前面预先加上区号等
    this.prefixStyle,  //prefixText的样式
    this.suffixIcon, //位于输入框后面的图片,例如一般输入框后面会有个眼睛,控制输入内容是否明文
    this.suffix,  //位于输入框尾部的控件,同样的不能和suffixText同时使用
    this.suffixText,//位于尾部的填充文字
    this.suffixStyle,  //suffixText的样式
    this.counter,//位于输入框右下方的小控件,不能和counterText同时使用
    this.counterText,//位于右下方显示的文本,常用于显示输入的字符数量
    this.counterStyle, //counterText的样式
    this.filled,  //如果为true,则输入使用fillColor指定的颜色填充
    this.fillColor,  //相当于输入框的背景颜色
    this.errorBorder,   //errorText不为空,输入框没有焦点时要显示的边框
    this.focusedBorder,  //输入框有焦点时的边框,如果errorText不为空的话,该属性无效
    this.focusedErrorBorder,  //errorText不为空时,输入框有焦点时的边框
    this.disabledBorder,  //输入框禁用时显示的边框,如果errorText不为空的话,该属性无效
    this.enabledBorder,  //输入框可用时显示的边框,如果errorText不为空的话,该属性无效
    this.border, //正常情况下的border
    this.enabled = true,  //输入框是否可用
    this.semanticCounterText,  
    this.alignLabelWithHint,
  })
enum TextInputAction {
//没有任何动作
  none,
  
//让操作系统决定哪个动作更合适
  unspecified,
  
//完成动作,一般会显示“完成”二字
  done,
  
  /// 跳转动作,一般用于输入了一个超链接后执行该动作。键盘上会显示“前往”二字
  go,
//搜索动作
  search,

//发送
  send,

  ///下个
  next,

  /// 返回前一个
  previous,

//继续动作,在Android上好像没反应,不显示键盘
  continueAction,

//在Android上好像没反应,不显示键盘
  route,

//拨打紧急电话,在Android上好像没反应,不显示键盘
  emergencyCall,

//换行
  newline,
}

TextField onChanged

onChanged: (val) {
        print(val);
},

TextField onEditingComplete

onEditingComplete: (){
        print("点击了键盘上的动作按钮");
},
image.png image.png
@override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: Padding(
            padding: EdgeInsets.all(20),
            child: ListView(
              children: <Widget>[
                TextField(
                  decoration: InputDecoration(
                    hintText: "请输入用户名",
                  ),
                  controller: _username,
                  onChanged: (value) {
                    setState(() {
                      _username.text = value;
                    });
                  },
                ),
                Divider(),
                TextField(
                  decoration: InputDecoration(icon: Icon(Icons.phone)),
                ),
                Divider(),
                TextField(
                  decoration: InputDecoration(
                      labelText: "用户名",
                      labelStyle: TextStyle(color: Colors.red, fontSize: 20)),
                ),
                Divider(),
                TextField(
                  decoration: InputDecoration(
                      labelText:
                          "labelText是否浮动,默认为true,修改为false则labelText在输入框获取焦点时不会浮动且不显示",
                      hasFloatingPlaceholder: false),
                ),
                Divider(),
                TextField(
                  decoration: InputDecoration(
                    hintText: "hint 文字",
                    helperText: "请输入邮箱",
                    errorText: "sss", //如果有errorText ,则helperText不显示
                  ),
                ),
                Divider(),
                TextField(
                  decoration: InputDecoration(
//                  icon: Icon(Icons.phone),
                      prefixIcon: Icon(Icons.radio_button_checked),
                      prefixText: "预填充文字"),
                ),
                Divider(),
                TextField(
                  decoration: InputDecoration(
                      suffixIcon: Icon(Icons.remove_red_eye),
                      suffixText: "suffixIcon suffixText"),
                ),
                Divider(),
                TextField(
                  decoration: InputDecoration(counterText: "counterText"),
                ),
                TextField(
                  decoration: InputDecoration(
                      filled: true,
                      fillColor: Colors.cyanAccent,
                      hintText: "颜色填充"),
                ),
                TextField(
                  decoration: InputDecoration(
                      border: InputBorder.none, hintText: "没有边框"),
                ),
                TextField(
                  decoration: InputDecoration(
                      hintText: "边框样式",
                      //未点击后
                      enabledBorder: OutlineInputBorder(
                          // 边角
                          borderRadius: BorderRadius.all(Radius.circular(20)),
                          borderSide: BorderSide(color: Colors.blue, width: 2)),
                      // 点击后
                      focusedBorder: OutlineInputBorder(
                          borderSide:
                              BorderSide(color: Colors.yellow, width: 2))),
                ),
                TextField(
                  decoration: InputDecoration(
                    hintText: "底边线,默认",
                    errorBorder: UnderlineInputBorder(
                      borderRadius: BorderRadius.all(Radius.circular(20)),
                      borderSide: BorderSide(color: Colors.blue),
                    ),
                    focusedErrorBorder: UnderlineInputBorder(
                        borderSide: BorderSide(
                      color: Colors.green,
                      //边框颜色为绿色
                      width: 5, //宽度为5
                    )),
                  ),
                )
              ],
            )));
  }

CheckBox

Checkbox({
    this.tristate = false, //如果为 true,那么复选框的值可以是 true,false 或 null。
    this.onChanged, //ValueChanged - 改变时触发。
    this.activeColor,  //激活时的颜色。
    this.checkColor,  //对勾的颜色
    this.materialTapTargetSize,
  }

CheckboxListTile

属性 描述
value true 或者 false
onChanged 改变的时候触发的事件
activeColor 选中的颜色、背景颜色
title 标题
subtitle 二级标题
secondary 配置图标或者图片
selected 选中的时候文字颜色是否跟着改变
image.png
body: Container(
          child: Column(
            children: <Widget>[
              Checkbox(
                  value: select,
                  onChanged: (v) {
                    setState(() {
                      this.select = v;
                    });
                  }),
              Row(
                children: <Widget>[
                  Checkbox(
                      checkColor: Colors.cyanAccent,
                      value: select,
                      onChanged: (v) {
                        setState(() {
                          this.select = v;
                        });
                      }),
                  Text(this.select ? "选中" : "未选中"),
                ],
              ),
              Divider(),
              CheckboxListTile(
                value: this.select,
                onChanged: (v) {
                  setState(() {
                    this.select = v;
                  });
                },
                title: Text("这是CheckboxListTile"),
                subtitle: Text("这是副标题"),
                activeColor: Colors.yellow,
                secondary: Icon(Icons.help),
              )
            ],
          ),
        ),

Radio

是单选值,所以在一组中只有1个能被选中,groupValue就是这个组,必须每个Radio都要写,而且要一样
Radio

属性 描述
value 单选的值
onChanged 改变时触发,获得是选中的值
activeColor 选中的颜色、背景颜色
groupValue 选择组的值

RadioListTile

属性 描述
value true 或者 false
onChanged 改变的时候触发的事件
activeColor 选中的颜色、背景颜色
title 标题
subtitle 二级标题
secondary 配置图标或者图片
groupValue 选择组的值
selected true false true 则当前高亮显示
image.png
class _RadioDemoState extends State<RadioDemo> {
  int groupValue = 1;
  int sex = 1;

  bool switchFlag = true;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Column(
          children: <Widget>[
            Row(
              children: <Widget>[
                Text("男:"),
                Radio(
                    value: 1,
                    groupValue: groupValue,
                    onChanged: (v) {
                      setState(() {
                        this.groupValue = v;
                      });
                    }),
                SizedBox(
                  width: 10,
                ),
                Text("女:"),
                Radio(
                  value: 2,
                  groupValue: groupValue,
                  onChanged: (v) {
                    setState(() {
                      this.groupValue = v;
                    });
                  },
                )
              ],
            ),
            Row(
              children: <Widget>[
                Text("${this.groupValue}"),
                Text("${this.groupValue == 1 ? "男" : "女"}")
              ],
            ),
            SizedBox(
              height: 50,
            ),
            RadioListTile(
              selected: this.groupValue == 1, //true  则当前高亮显示
              title: Text("tilte"),
              subtitle: Text("subtitle"),
              secondary: Icon(Icons.phone),
              value: 1,
              groupValue: this.groupValue,
              onChanged: (v) {
                setState(() {
                  this.groupValue = v;
                });
              },
            ),
            RadioListTile(
              selected: this.groupValue == 2, //true  则当前高亮显示
              title: Text("tilte"),
              subtitle: Text("subtitle"),
              secondary: Icon(Icons.phone),
              value: 2,
              groupValue: this.groupValue, // 和上面是一个组的
              onChanged: (v) {
                setState(() {
                  this.groupValue = v;
                });
              },
            ),
            Switch(value: switchFlag, onChanged: (v){
              setState(() {
                this.switchFlag = v;
              });
            })
          ],
        ),
      ),
    );
  }
}

表单提交


image.png
class _FromDemoState extends State<FromDemo> {
  String username;
  int sex = 1;
  String result="";

  List hobby = [
    {"checked": true, "title": "吃饭"},
    {"checked": true, "title": "跑步"},
    {"checked": true, "title": "打麻将"}
  ];

  List<Widget> getHobby() {
    List<Widget> tmp = [];
    for (var i = 0; i < hobby.length; i++) {
      tmp.add(Row(
        children: <Widget>[
          Text(hobby[i]["title"]),
          Checkbox(
              value: hobby[i]["checked"],
              onChanged: (v) {
                setState(() {
                  hobby[i]["checked"] = v;
                });
              })
        ],
      ));
    }
    return tmp;
  }

  void _sexChange(value) {
    setState(() {
      this.sex = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("表单"),
        ),
        body: Padding(
          padding: EdgeInsets.all(20),
          child: Column(
            children: <Widget>[
              TextField(
                decoration: InputDecoration(
                  hintText: "输入用户信息",
                ),
                onChanged: (v) {
                  setState(() {
                    this.username = v;
                  });
                },
              ),
              Row(
                children: <Widget>[
                  Text("男"),
                  Radio(value: 1, groupValue: this.sex, onChanged: _sexChange),
                  Text("女"),
                  Radio(value: 2, groupValue: this.sex, onChanged: _sexChange),
                ],
              ),
              Column(children: getHobby()),
              Container(
                width: double.infinity,
                height: 40,
                child: RaisedButton(
                  onPressed: () {
                    setState(() {
                      this.result = "姓名:${this.username} 性别:${this.sex} 爱好:${this.hobby}";
                    });
                  },
                  child: Text("提交信息"),
                ),
              ),
              SizedBox(
                height: 10,
              ),
              TextField(
                maxLines: 5,
                //  通过 controller来进行TextField 赋值
                controller: TextEditingController.fromValue(
                        TextEditingValue(
                            text: result,
                    // 保持光标在最后
                  selection: TextSelection.fromPosition(TextPosition(
                      affinity: TextAffinity.downstream,
                      offset: result.length
                  )
                ),
                decoration: InputDecoration(border: OutlineInputBorder()),
              )
            ],
          ),
        ),
      ),
    );
  }
}

参考

上一篇 下一篇

猜你喜欢

热点阅读