Flutter 之 表單Widget(TextField & Form)(七)

1. TextField Widget

TextField用于接收用戶的文本輸入

20190605135257203.png

1.1 基本屬性

TextField

  const TextField({
    Key key,
    this.controller,//控制器
    this.focusNode,//焦點(diǎn)
    this.decoration = const InputDecoration(),//裝飾
    TextInputType keyboardType,//鍵盤類型易阳,即輸入類型
    this.textInputAction,//鍵盤按鈕
    this.textCapitalization = TextCapitalization.none,//大小寫
    this.style,//樣式
    this.strutStyle,
    this.textAlign = TextAlign.start,//對(duì)齊方式
    this.textDirection,
    this.autofocus = false,//自動(dòng)聚焦
    this.obscureText = false,//是否隱藏文本蛮拔,即顯示密碼類型
    this.autocorrect = true,//自動(dòng)更正
    this.maxLines = 1,//最多行數(shù),高度與行數(shù)同步
    this.minLines,//最小行數(shù)
    this.expands = false,
    this.maxLength,//最多輸入數(shù)隅俘,有值后右下角就會(huì)有一個(gè)計(jì)數(shù)器
    this.maxLengthEnforced = true,
    this.onChanged,//輸入改變回調(diào)
    this.onEditingComplete,//輸入完成時(shí)沈自,配合TextInputAction.done使用
    this.onSubmitted,//提交時(shí),配合TextInputAction
    this.inputFormatters,//輸入校驗(yàn)
    this.enabled,//是否可用
    this.cursorWidth = 2.0,//光標(biāo)寬度
    this.cursorRadius,//光標(biāo)圓角
    this.cursorColor,//光標(biāo)顏色
    this.keyboardAppearance,
    this.scrollPadding = const EdgeInsets.all(20.0),
    this.dragStartBehavior = DragStartBehavior.start,
    this.enableInteractiveSelection,
    this.onTap,//點(diǎn)擊事件
    this.buildCounter,
    this.scrollPhysics,
  }) 


InputDecoration

  const InputDecoration({
    this.icon,//左側(cè)外的圖標(biāo)
    this.labelText,//懸浮提示徐勃,可代替hintText
    this.labelStyle,//懸浮提示文字的樣式
    this.helperText,//幫助文字
    this.helperStyle,
    this.hintText,//輸入提示
    this.hintStyle,
    this.hintMaxLines,
    this.errorText,//錯(cuò)誤提示
    this.errorStyle,
    this.errorMaxLines,
    this.hasFloatingPlaceholder = true,//是否顯示懸浮提示文字
    this.isDense,
    this.contentPadding,//內(nèi)填充
    this.prefixIcon,//左側(cè)內(nèi)的圖標(biāo)
    this.prefix,
    this.prefixText,//左側(cè)內(nèi)的文字
    this.prefixStyle,
    this.suffixIcon,//右側(cè)內(nèi)圖標(biāo)
    this.suffix,
    this.suffixText,
    this.suffixStyle,
    this.counter,//自定義計(jì)數(shù)器
    this.counterText,//計(jì)數(shù)文字
    this.counterStyle,//計(jì)數(shù)樣式
    this.filled,//是否填充
    this.fillColor,//填充顏色
    this.errorBorder,
    this.focusedBorder,
    this.focusedErrorBorder,
    this.disabledBorder,
    this.enabledBorder,
    this.border,//邊框
    this.enabled = true,
    this.semanticCounterText,
    this.alignLabelWithHint,
  })


1.2 樣式

1.2.1 基礎(chǔ)樣式
TextField(),

style:TextStyle 可以修改文本樣式


20190605155222258.png
1.2.2 隱藏文本

修改obscureText的屬性值
obscureText 設(shè)置為true時(shí),輸入的文本不可見一罩,常用的密碼類型

TextField(
  obscureText: true,
),
image.png
1.2.3 鍵盤類型

keyboardType 即可輸入類型莉测,傳入TextInputType類型,比如傳入number即數(shù)字鍵盤

TextField(
  keyboardType: TextInputType.number,
),
image.png

TextInputType 可選類型

TextInputType.text
TextInputType.multiline
TextInputType.phone
TextInputType.datetime
TextInputType.emailAddress
TextInputType.url
TextInputType.visiblePassword
TextInputType.name
TextInputType.streetAddress
1.2.4 鍵盤按鈕

即鍵盤右下角按鈕樣式柔袁,比如完成或者Done

TextField(
  textInputAction: TextInputAction.done,
),
截屏2022-04-13 上午9.34.25.png

textInputAction 可選類型

         TextInputAction.none //為不彈出鍵盤
         TextInputAction.unspecified //換行
         TextInputAction.done //完成或者done
         TextInputAction.go  //前往或者go
         TextInputAction.search //搜索或者search
         TextInputAction.send  //發(fā)送或者send
         TextInputAction.next //下一項(xiàng)或者next
         TextInputAction.previous // 上一項(xiàng) IOS 不支持
         TextInputAction.continueAction //繼續(xù)或者 continue
         TextInputAction.join //加入或者join
         TextInputAction.route //路線或者route
         TextInputAction.emergencyCall //緊急電話
         TextInputAction.newline //換行或者newline
1.2.5 大小寫

即控制輸入英文字母大小寫呆躲,比如單詞首字母大寫

TextField(
  textCapitalization: TextCapitalization.words,
),
image.png

textCapitalization 其他可選類型

TextCapitalization.words // 單詞首字母大寫
TextCapitalization.sentences // 句子首字母大寫
TextCapitalization.characters // 所有字母大寫
textCapitalization: TextCapitalization.none // 默認(rèn)無
1.2.6 光標(biāo)

默認(rèn)是一個(gè)藍(lán)色豎線

TextField(
  cursorColor: Colors.orange,
  cursorWidth: 15,
  cursorRadius: Radius.circular(15),
),
截屏2022-04-13 上午9.45.31.png
1.2.7 最多行數(shù)
TextField(
  maxLines: 3,
),
image.png

從效果上看,TextField默認(rèn)行數(shù)變成3行捶索,如果我們想默認(rèn)顯示1行插掂,最多輸入3行,可以再加個(gè)參數(shù) minLines

TextField(
  maxLines: 3,
  minLines: 1,
),

TextField的高度會(huì)自適應(yīng)

1.2.8 計(jì)數(shù)器

TextField 右下角有個(gè)計(jì)數(shù),超出數(shù)量限制無法輸入

TextField(
  maxLength: 8,
),
image.png

默認(rèn)效果:當(dāng)前輸入長(zhǎng)度/最大長(zhǎng)度腥例,我們可以自定義一個(gè)計(jì)數(shù)器

TextField(
  maxLength: 8,
  decoration: InputDecoration(
    counter: Text("自定義計(jì)數(shù) 0/100"),
  ),
),
image.png
1.2.9 圖標(biāo)

圖標(biāo)有3種

  • 左外側(cè)圖標(biāo)
TextField(
  decoration: InputDecoration(
    icon: Icon(Icons.person),
  ),
),
image.png
  • 左內(nèi)側(cè)圖標(biāo)
TextField(
  decoration: InputDecoration(
    prefixIcon: Icon(Icons.phone_android),
  ),
),
image.png
  • 右內(nèi)側(cè)圖標(biāo)
TextField(
  decoration: InputDecoration(
    suffixIcon: IconButton(
      icon: Icon(Icons.close),
      onPressed: () {
        controller.clear();
      },
    ),
  ),
),

在右側(cè)圖標(biāo)加了IconButton辅甥,可以點(diǎn)擊

image.png
1.2.10 提示文字

提示文字有4種

  • 輸入提示文字
TextField(
  controller: controller,
  decoration: InputDecoration(
    hintText: '請(qǐng)輸入賬號(hào)aaa',
  ),
),
image.png
  • 懸浮提示文本
TextField(
  controller: controller,
  decoration: InputDecoration(
    hintText: '請(qǐng)輸入賬號(hào)aaa',
    labelText: '請(qǐng)輸入賬號(hào)',
  ),
),
image.png

可以看到默認(rèn)顯示labelText的,聚焦后顯示hintText

  • 幫助提示文本
TextField(
  controller: controller,
  decoration: InputDecoration(
    helperText: "幫助文字",
    helperStyle: TextStyle(color: Colors.blue)
  ),
),
image.png
  • 錯(cuò)誤提示文本
TextField(
  controller: controller,
  decoration: InputDecoration(
    errorText: "你沒有輸入任何內(nèi)容",
  ),
),

image.png
1.2.11 去掉下劃線
TextField(
  decoration: InputDecoration.collapsed(hintText: "無下劃線的輸入框"),
),
image.png

也可以decoration:null,這樣的話就沒有提示文本

1.2.12 邊框
TextField(
  decoration: InputDecoration(
    border: OutlineInputBorder(),
  ),
),
image.png

可以通過borderRadius 修改圓角

TextField(
  decoration: InputDecoration(
    border: OutlineInputBorder(
      borderRadius: BorderRadius.all(Radius.circular(30)),
    ),
  ),
),
image.png
1.2.13 獲取輸入內(nèi)容

有兩種方式

  • onChanged
    onChanged 是輸入文本發(fā)生變化時(shí)回調(diào)燎竖,返回是一個(gè)String璃弄,可以用變量記錄下
TextField(
  onChanged: (text) {
    print("輸入改變時(shí)" + text);
  },
),
  • controller
    即控制器

初始化

  var controller;

  @override
  void initState() {
    super.initState();
    controller = TextEditingController();
    controller.addListener(() {});
  }

配置給TextField

TextField(
  controller: controller,
),

獲取內(nèi)容

controller.text

在事件中調(diào)用controller.text,即輸入的文本

1.2.14 關(guān)閉軟鍵盤

初始化

FocusNode userFocusNode = FocusNode();

配置

TextField(
  focusNode: userFocusNode,
),

然后在需要的地方調(diào)用

userFocusNode.unfocus();
1.2.15 校驗(yàn)

RegExp 可以使用正則表達(dá)式來校驗(yàn)

  String? validateMobile(String value) {
    String patttern = r'(^[0-9]*$)';
    RegExp regExp = new RegExp(patttern);
    if (value.length == 0) {
      return "手機(jī)號(hào)為空";
    } else if (!regExp.hasMatch(value)) {
      return "手機(jī)號(hào)格式不正確";
    }
    return null;
  }

2构回、表單From

flutter提供一套表單校驗(yàn)框架Form夏块,可以通過Form框架一步校驗(yàn)所有表單,非常方便纤掸,比較常用的用法是Form+TextFormField

2.1 Form & TextFormField 介紹

Form

class Form extends StatefulWidget {
  final Widget child;
  ...
    const Form({
    Key? key,
    required this.child,
    this.onWillPop,
    this.onChanged,
    AutovalidateMode? autovalidateMode,
  })
  ...

Form繼承StatefulWidget脐供,有一個(gè)widget 類型的child參數(shù),證明Form是一個(gè)容器
FormState 里還有一個(gè)validate方法

  bool validate() {
    _hasInteractedByUser = true;
    _forceRebuild();
    return _validate();
  }

一般通過GlobalKey來訪問Form中validate方法借跪,F(xiàn)orm的validate方法用來校驗(yàn)所有Form里的FormField表單政己,validate方法返回值是bool類型,返回true表示所有表單校驗(yàn)成功掏愁;返回false表示有校驗(yàn)失敗的表單歇由;

TextFormField

class TextFormField extends FormField<String> {
...
 TextFormField({
   ...
    FormFieldValidator<String> validator,
   ...
  })

TextFormField繼承FormField卵牍,F(xiàn)ormField后面源碼分析會(huì)講,所有Form可統(tǒng)一校驗(yàn)的表單都必須繼承FormField沦泌,可以通過FormField自定義各種各樣可校驗(yàn)表單辽慕,TextFormField只是FormField自定義表單中的一種。
表單校驗(yàn)必須實(shí)現(xiàn)的方法為validator赦肃,定義如下:

typedef FormFieldValidator<T> = String? Function(T? value);

每個(gè)表單的校驗(yàn)規(guī)則都在validator里實(shí)現(xiàn)溅蛉,通過返回值來判斷是否校驗(yàn)成功。

返回null他宛,表示表單校驗(yàn)成功
返回非null船侧,表示表單校驗(yàn)失敗,其實(shí)返回的非null還可以用來表示校驗(yàn)失敗的錯(cuò)誤提示信息厅各,TextFormField內(nèi)部實(shí)現(xiàn)就將返回的非null當(dāng)成錯(cuò)誤信息提示出來

2.2 使用步驟

1镜撩、用Form包在所有需要校驗(yàn)的表單最外層,如下:

  Form(
            key:xxx,
            child:xxx

2队塘、將GlobalKey傳給Form袁梗,用于調(diào)用Form里方法,如下:

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  Form(
            key:_formKey,
            child:xxx

3憔古、將TextFormField傳給Form容器遮怜,如下:

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  Form(
            key:_formKey,
            child:
                    ...
                    TextFormField
                    ...

4、實(shí)現(xiàn)對(duì)應(yīng)TextFormField的校驗(yàn)規(guī)則 鸿市,如下:

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  Form(
            key:_formKey,
            child:
                    ...
                    TextFormField( 
                        validator: (value) {
                              ...
                              return xxx; 
                        },
                    )
                    ...

5锯梁、最后調(diào)用Form校驗(yàn)所有表單方法validate,如下:

_formKey.currentState.validate()

2.3 Form 校驗(yàn) 示例

class _MSHomeContentState extends State<MSHomeContent> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      autovalidateMode: AutovalidateMode.onUserInteraction,
      child: Column(
        children: [
          TextFormField(
            decoration: InputDecoration(
              hintText: "請(qǐng)輸入手機(jī)號(hào)",
            ),
            validator: (value) {
              RegExp reg = new RegExp(r'^\d{11}$');
              if (!reg.hasMatch(value!)) {
                return '請(qǐng)輸入11位手機(jī)號(hào)';
              }
              return null;
            },
          ),
          TextFormField(
            decoration: InputDecoration(
              hintText: "請(qǐng)輸入用戶名",
            ),
            validator: (value) {
              if (value!.isEmpty) {
                return "請(qǐng)輸入用戶名";
              }
              return null;
            },
          ),
          SizedBox(
            height: 20,
          ),
          ElevatedButton(
            onPressed: () {
              if (_formKey.currentState!.validate()) {
                ScaffoldMessenger.of(context)
                    .showSnackBar(SnackBar(content: Text("校驗(yàn)成功")));
                // Scaffold.of(context).showSnackBar(snackbar)
              }
            },
            child: Text("校驗(yàn)"),
          ),
        ],
      ),
    );
  }
}

截屏2022-04-13 下午12.00.20的副本.png

2.4 Form 保存和獲取表單數(shù)據(jù) 示例

class _MSHomeContentState extends State<MSHomeContent> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  String? phoneNum;
  String? userName;
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Form(
        key: _formKey,
        child: Column(
          children: [
            TextFormField(
              decoration: InputDecoration(
                hintText: "請(qǐng)輸入手機(jī)號(hào)",
              ),
              onSaved: (value) {
                phoneNum = value;
              },
            ),
            SizedBox(
              height: 20,
            ),
            TextFormField(
              decoration: InputDecoration(
                hintText: "請(qǐng)輸入用戶名",
              ),
              onSaved: (value) {
                userName = value;
              },
            ),
            SizedBox(
              height: 20,
            ),
            Container(
              width: double.infinity,
              height: 50,
              padding: EdgeInsets.symmetric(horizontal: 16),
              child: ElevatedButton(
                onPressed: () {
                  // 保存和獲取表單數(shù)據(jù)
                  _formKey.currentState!.save();
                  print("userName: $userName,phoneNum:$phoneNum");
                },
                child: Text("保存"),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

截屏2022-04-13 下午12.22.37.png

參考:
[Button]https://blog.csdn.net/qq_41619796/article/details/115658314
[Image]http://www.reibang.com/p/27394b02d4d6/
[TextFiled]https://blog.csdn.net/yechaoa/article/details/90906689
[From]http://www.reibang.com/p/b5bc338b260b

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末焰情,一起剝皮案震驚了整個(gè)濱河市陌凳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌内舟,老刑警劉巖合敦,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異验游,居然都是意外死亡充岛,警方通過查閱死者的電腦和手機(jī)批狱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門裸准,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赔硫,“玉大人权悟,你說我怎么就攤上這事±莆簦” “怎么了瘪菌?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵撒会,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我师妙,道長(zhǎng)诵肛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任默穴,我火速辦了婚禮怔檩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蓄诽。我一直安慰自己薛训,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布仑氛。 她就那樣靜靜地躺著许蓖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪调衰。 梳的紋絲不亂的頭發(fā)上膊爪,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音嚎莉,去河邊找鬼米酬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛趋箩,可吹牛的內(nèi)容都是我干的赃额。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼叫确,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼跳芳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起竹勉,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤飞盆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吓歇,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孽水,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了城看。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片女气。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖测柠,靈堂內(nèi)的尸體忽然破棺而出炼鞠,到底是詐尸還是另有隱情,我是刑警寧澤轰胁,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布簇搅,位于F島的核電站,受9級(jí)特大地震影響软吐,放射性物質(zhì)發(fā)生泄漏瘩将。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一凹耙、第九天 我趴在偏房一處隱蔽的房頂上張望姿现。 院中可真熱鬧,春花似錦肖抱、人聲如沸备典。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽提佣。三九已至,卻和暖如春荤崇,著一層夾襖步出監(jiān)牢的瞬間拌屏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工术荤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倚喂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓瓣戚,卻偏偏與公主長(zhǎng)得像端圈,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子子库,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容