天天看點

【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#

      小菜剛學習了 TextField 的基本用法,今天特意學習一下 TextField InputDecoration 文本框裝飾器的相關内容;

InputDecoration 源碼分析

const InputDecoration({
    this.icon,                  // 裝飾器外小圖示
    this.labelText,             // 文本框描述标簽
    this.labelStyle,            // 文本框描述标簽樣式
    this.helperText,            // 文本框輔助标簽
    this.helperStyle,           // 文本框輔助标簽樣式
    this.hintText,              // 文本框預設提示資訊
    this.hintStyle,             // 文本框預設提示資訊樣式
    this.hintMaxLines,          // 文本框預設提示資訊最大行數
    this.errorText,             // 文本框錯誤提示資訊
    this.errorStyle,            // 文本框錯誤提示資訊樣式
    this.errorMaxLines,         // 文本框錯誤提示資訊最大行數
    this.hasFloatingPlaceholder = true,     // 文本框擷取焦點後 labelText 是否向上浮動
    this.isDense,               // 是否問緊湊型文本框
    this.contentPadding,        // 文本内邊距
    this.prefixIcon,            // 前置圖示
    this.prefix,                // 前置預填充 Widget
    this.prefixText,            // 前置預填充文本
    this.prefixStyle,           // 前置預填充樣式
    this.suffixIcon,            // 後置圖示
    this.suffix,                // 後置預填充 Widget
    this.suffixText,            // 後置預填充文本
    this.suffixStyle,           // 後置預填充樣式
    this.counter,               // 輸入框右下角 Widget
    this.counterText,           // 輸入框右下角文本
    this.counterStyle,          // 輸入框右下角樣式
    this.filled,                // 是否顔色填充文本框
    this.fillColor,             // 填充顔色
    this.errorBorder,           // errorText 存在時未擷取焦點邊框
    this.focusedBorder,         // 擷取焦點時邊框
    this.focusedErrorBorder,    // errorText 存在時擷取焦點邊框
    this.disabledBorder,        // 不可用時邊框
    this.enabledBorder,         // 可用時邊框
    this.border,                // 邊框
    this.enabled = true,        // 輸入框是否可用
    this.semanticCounterText,
    this.alignLabelWithHint,    // 覆寫将标簽與 TextField 的中心對齊
})

const InputDecoration.collapsed({
    @required this.hintText,
    this.hasFloatingPlaceholder = true,
    this.hintStyle,
    this.filled = false,
    this.fillColor,
    this.border = InputBorder.none,
    this.enabled = true,
})
           

      分析源碼可知,Flutter 不僅提供了全面的建構裝飾器的方式,還提供了簡單便利的建構方式 collapsed 預設是無邊框的,且無法設定标簽等其他屬性;

案例嘗試

  1. icon 為裝飾器外小圖示,可靈活設定圖示或其他 Widget,預設距輸入框 16dp,主題可通過 IconTheme 設定;
return TextField(decoration: InputDecoration(icon: Image.asset('images/ic_launcher.png')));
return TextField(decoration: InputDecoration(icon: Icon(Icons.android)));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. labelText 為文本框描述标簽,為 String 類型,直接編輯内容即可;labelStyle 為标簽樣式屬性;TextField 擷取焦點之後描述标簽上移;
return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple)));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. helperText 為文本框輔助标簽,一般在文本框底部,提示性内容;helperStyle 為文本框輔助标簽樣式屬性;與 TextField 是否擷取焦點無變化;
return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    helperText: '請輸入手機号或郵箱!', helperStyle: TextStyle(color: Colors.teal)));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. hintText 為文本框預設提示資訊,若設定 labelText,則 TextField 在未擷取焦點時優先展示 labelText;hintStyle 為文本框提示資訊樣式屬性;hintMaxLines 為提示資訊過長時允許展示的最大行數;
return TextField(decoration: InputDecoration(
    hintStyle: TextStyle(color: Colors.brown), hintMaxLines: 1, hintText: '請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!'));

return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    helperText: '請輸入手機号或郵箱!', helperStyle: TextStyle(color: Colors.teal),
    hintText: '請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!',
    hintStyle: TextStyle(color: Colors.brown), hintMaxLines: 2));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. errorText 為文本框錯誤提示資訊,一般在文本框底部,當設定 errorText 時不展示 helperText,整體預設為紅色;errorStyle 為錯誤提示資訊樣式屬性;errorMaxLines 為錯誤資訊過長時允許展示的最大行數;與 hintText 類似;
return TextField(onChanged: (text) { setState(() { _textLength = text.length; }); },
    decoration: InputDecoration(
        labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
        helperText: '請輸入手機号或郵箱!', helperStyle: TextStyle(color: Colors.teal),
        hintText: '請輸入使用者名資訊!', hintStyle: TextStyle(color: Colors.brown),
        errorText: _textLength > 11 ? '請勿超過 11 位使用者名!' : null, errorStyle: TextStyle(color: Colors.pink)));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. hasFloatingPlaceholder 設定 TextField 擷取焦點時 labelText 是否向上浮動;設定為 false 時,擷取焦點後 labelText 隐藏,不會向上浮動;
return TextField(decoration: InputDecoration(labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    hasFloatingPlaceholder: false));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. isDense 是否為緊湊型文本框,true 為緊湊型文本框,圖示等與輸入框邊距較小;
return TextField(decoration: InputDecoration(icon: Icon(Icons.android), isDense: false));
return TextField(decoration: InputDecoration(icon: Icon(Icons.android), isDense: true));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. contentPadding 為編輯内容與文本框内邊距;
returnTextField(decoration: InputDecoration(contentPadding: EdgeInsets.all(20.0)));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. prefix... 是文本框前置元件,prefixIcon 為前置圖示,固定在文本輸入框前邊,與 icon 位置不同,其樣式通過 IconTheme 調整;prefixText 為前置預填充文本,例如手機号前(+86) 之類;prefix 為前置預填充元件,可自由設定,更為靈活,但不能與 prefixText 同時使用;prefixStyle 為預填充元件樣式;
return TextField(decoration: InputDecoration(
    prefixIcon: Icon(Icons.supervised_user_circle), prefixText: '(+86)', prefixStyle: TextStyle(color: Colors.purple.withOpacity(0.4))));
    
return TextField(decoration: InputDecoration(
    prefixIcon: Icon(Icons.supervised_user_circle), prefixStyle: TextStyle(color: Colors.purple.withOpacity(0.4)),
    prefix: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[Icon(Icons.phone), Text('(+86)')])));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. suffix... 為文本框後置元件系列;與 prefix... 用法一緻;
return TextField(decoration: InputDecoration(
    suffixIcon: Icon(Icons.close), suffixText: '關閉', suffixStyle: TextStyle(color: Colors.purple.withOpacity(0.4))));
            
return TextField(decoration: InputDecoration(
    suffixIcon: Icon(Icons.close), suffixStyle: TextStyle(color: Colors.purple.withOpacity(0.4)),
    suffix: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[Text('關閉'), Icon(Icons.remove_red_eye)])));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. counter 系列為文本框右下角計數器,當設定 maxLengths 時通常會在右下角展示編輯字元數與整體數量比,可通過 counter 系列元件調整;counterText 為計數器展示内容;counterStyle 為計數器樣式屬性;
return TextField(maxLength: 20,
    decoration: InputDecoration(counterText: '最大長度不超過20', counterStyle: TextStyle(color: Colors.blueAccent)));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. filled 為文本框是否顔色填充,隻有 true 時,filledColor 才生效;
return TextField(decoration: InputDecoration(fillColor: Colors.green.withOpacity(0.4), filled: true));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. enabled 為文本框是否可用,false 為不可用,無法擷取焦點;
return TextField(decoration: InputDecoration(enabled: false));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. alignLabelWithHint 用于 TextField 設定多行時,true 時覆寫将标簽與 TextField 的中心對齊的預設行為,小菜嘗試了多種情況下 true 和 false 狀态,發現效果并不明顯,有待繼續研究;
return TextField(maxLines: null, decoration: InputDecoration(
  alignLabelWithHint: true, labelText: '使用者名:',
  hintMaxLines: null, helperText: '請輸入手機号或郵箱!',
  hintText: '請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!請輸入使用者名資訊!',
));
           
  1. border 為一個系列,包括各種環境下邊框;預設 border 為正常狀态下邊框;邊框基本包括三類:

a. InputBorder 一般設定為無邊框樣式;

return TextField(decoration: InputDecoration(border: InputBorder.none));
           

b. UnderlineInputBorder 一般設定為底部一條直線邊框樣式;小菜測試時設定邊框圓角為 10dp 加上背景色效果更明顯;

return TextField(decoration: InputDecoration(
    filled: true, fillColor: Colors.green.withOpacity(0.4),
    border: UnderlineInputBorder(
        borderRadius: BorderRadius.all(Radius.circular(10.0)),
        borderSide: BorderSide(color: Colors.purple, width: 4.0, style: BorderStyle.solid))));
           

c. OutlineInputBorder 一般設定為包圍的圓角邊框;相較于 UnderlineInputBorder 多了 gapPadding 屬性,用于浮動的 labelText 與邊框的間距;

return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    border: OutlineInputBorder(
        gapPadding: 10.0, borderRadius: BorderRadius.all(Radius.circular(10.0)), 
        borderSide: BorderSide(color: Colors.purple, width: 4.0, style: BorderStyle.solid))));
           

      小菜測試發現 UnderlineInputBorder 和 OutlineInputBorder 對于設定 border 邊框顔色無效,需要通過 ThemeData 來更改屬性;

【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. enabledBorder 為可用時邊框樣式,enabled 為 true;

Tips:

  1. errorText 存在時 enabledBorder 不生效;
  2. 若不設定其他 border 屬性,擷取焦點預設是 ThemeData 中焦點邊框,設定 border 或 focusedBorder 等生效;
// UnderlineInputBorder 類型且隻設定 enabledBorder
return TextField(decoration: InputDecoration(filled: true,fillColor: Colors.green.withOpacity(0.4),
    enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0))));
// UnderlineInputBorder 類型且設定 enabledBorder 和 border
return TextField(decoration: InputDecoration(filled: true, fillColor: Colors.green.withOpacity(0.4),
    enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0)),
    border: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)))));
// UnderlineInputBorder 類型且 errorText 不為空
return TextField(decoration: InputDecoration(filled: true, fillColor: Colors.green.withOpacity(0.4),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0)),
    border: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)))));
// OutlineInputBorder 類型且隻設定 enabledBorder
return TextField(decoration: InputDecoration(labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0)),
    border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)))));
// OutlineInputBorder 類型設定 enabledBorder,且 errorText 不為空
return TextField(decoration: InputDecoration(labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0))));
// OutlineInputBorder 類,設定 enabledBorder 和 border 且 errorText 不為空  
return TextField(decoration: InputDecoration(labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0)),
    border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)))));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. disabledBorder 為不可用時邊框,enabled 為 false;且 errorText 存在時 disabledBorder 不生效;
// UnderlineInputBorder 類型
return TextField( decoration: InputDecoration(enabled: false,
    filled: true, fillColor: Colors.green.withOpacity(0.4),
    disabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0))));
// UnderlineInputBorder 類型且設定 errorText
return TextField(decoration: InputDecoration(enabled: false,
    filled: true, fillColor: Colors.green.withOpacity(0.4),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    disabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)));
// OutlineInputBorder 類型
return TextField(decoration: InputDecoration(enabled: false,
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    disabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.green, width: 4.0))));
// OutlineInputBorder 類型且設定 errorText
return TextField(decoration: InputDecoration(enabled: false,
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    disabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0))));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. focusedBorder 為擷取焦點時邊框,errorText 存在時 focusedBorder 不生效;
// UnderlineInputBorder 類型
return TextField(decoration: InputDecoration(
    filled: true, fillColor: Colors.green.withOpacity(0.4),
    focusedBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)),
    enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0))));
// UnderlineInputBorder 類型且設定 errorText
return TextField(decoration: InputDecoration(
    filled: true, fillColor: Colors.green.withOpacity(0.4),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    focusedBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)),
    enabledBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple, width: 4.0))));
// OutlineInputBorder 類型
return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0)),
    focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.green, width: 4.0))));
// OutlineInputBorder 類型且設定 errorText
return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)),
    enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0))));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. errorBorder 為 errorText 不為空且未擷取焦點時邊框;
// UnderlineInputBorder 類型
return TextField(decoration: InputDecoration(
    filled: true, fillColor: Colors.green.withOpacity(0.4),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    errorBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.black.withOpacity(0.4), width: 4.0))));
// OutlineInputBorder 類型
return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    errorBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.black.withOpacity(0.4), width: 3.0))));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#
  1. focusedErrorBorder 為 errorText 不為空且擷取焦點時邊框;
// UnderlineInputBorder 類型
return TextField(decoration: InputDecoration(
    filled: true, fillColor: Colors.green.withOpacity(0.4),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    focusedErrorBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.teal, width: 4.0)),
    errorBorder: UnderlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.black, width: 4.0))));
// OutlineInputBorder 類型
return TextField(decoration: InputDecoration(
    labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
    errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink),
    focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.pink, width: 4.0)),
    errorBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.purple.withOpacity(0.4), width: 3.0))));
           
【Flutter 專題】65 圖解基本 TextField 文本輸入框 (二) #yyds幹貨盤點#

小擴充

      在實際開發中,可能回随時需要關閉鍵盤,此時我們僅需監聽一下即可;小菜監聽一個文本輸入框,當輸入字元長度大于 11 位時即收起鍵盤;

return TextField(controller: controller,
    decoration: InputDecoration(
        labelText: '使用者名:', labelStyle: TextStyle(color: Colors.purple),
        errorText: '請勿超過 11 位!', errorStyle: TextStyle(color: Colors.pink)));

void initState() {
  super.initState();
  controller.addListener(() {
    setState(() {
      if (controller.text.length >= 11) {
        // 收起鍵盤
        FocusScope.of(context).requestFocus(FocusNode());
      }
    });
  });
}
           

繼續閱讀