包括以下 widget:
TextField
- 輸入框Switch
- 選擇切換Radio
- 單選按鈕組Checkbox
- 多選按鈕組- ``
- ``
- ``
- ``
- ``
TextField
網上的資料包括官方文件都是一上來一大堆屬性列出來,輸入框可設定的屬性太多了,這樣的話很難看的,很勸退的,所以我努力把這些屬性分門別類按照幾個大的範圍整理下,以往能看的順眼
屬性大全
// 雖然不想寫,但是還是寫上吧
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,
})
複製程式碼
鍵盤控制
1. 鍵盤樣式
Flutter 內建了不少種鍵盤樣式的,有的我也沒搞明白,就這麼看吧
TextInputType.text
- 普通完整鍵盤TextInputType.number
- 數字鍵盤TextInputType.emailAddress
- 帶有“@”的普通鍵盤TextInputType.datetime
- 帶有“/”和“:”的數字鍵盤)TextInputType.multiline
- 帶有選項以啟用有符號和十進位制模式的數字鍵盤url
- 會顯示“/ .”phone
- 會彈出數字鍵盤並顯示"* #"
TextField(
keyboardType: TextInputType.datetime,
)
複製程式碼
2. 大小寫控制
TextCapitalization.none
- 全部小寫TextCapitalization.words
- 每個單詞的首字母大寫TextCapitalization.sentences
- 每個句子的首字母大寫TextCapitalization.characters
- 每個字每大寫
我試了試,有的鍵盤貌似不管用,大家還是自己靠正則或是校驗來控制輸入吧,感覺這個設定不靠譜
3. 修改鍵盤動作按鈕樣式
關鍵詞是 textInputAction
,改變的是鍵盤右下角那個按鈕的樣式,根據安裝的輸入法的不同,有的顯示的是文字,有的顯示的是圖示。Flutter 內建了不少樣式,可惜沒有預覽,只能看英文自己猜了
TextField(
textInputAction: TextInputAction.search,
),
複製程式碼
4. 鍵盤動作按鈕點選響應 - 無參的
回撥是 onEditingComplete
,注意是沒有返回值的
TextField(
onEditingComplete: (){
print("AA");
},
),
複製程式碼
5. 鍵盤動作按鈕點選響應 - 有參的
回撥是 onSubmitted
,這次是有返回值的,也就是你輸入的資料
TextField(
onSubmitted: (inputValue){
print("輸入資料位: ${inputValue}");
},
),
複製程式碼
監聽事件
onChanged
- 當使用者輸入就會觸發回撥,我們從中可以拿到使用者輸入值,經過測試,每次拿到的都是使用者所有的輸入值
TextField(
keyboardType: TextInputType.datetime,
onChanged: (inputValue) {
print("input:${inputValue}");
},
)
複製程式碼
TextEditingController
- 官文件描述為:文字控制器
,目前發現也就是 TextEditingController.text 拿到輸入的內容,Flutter widget 一般都不要用 物件.屬性的去寫,所以提供了這麼一個東西。我們要 new 一個 TextEditingController 出來,傳給 TextField
class TestWidgetState extends State<TestWidget> {
var editContore = TextEditingController();
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
width: 200,
child: TextField(
keyboardType: TextInputType.datetime,
onChanged: (inputValue) {
print("input:${inputValue}");
},
controller: editContore,
),
),
RaisedButton(
child: Text("請點選"),
onPressed: () {
print("輸入內容:${editContore.text}");
},
),
],
);
}
}
複製程式碼
onTap
- 在按下開始輸入的那一瞬間觸發,每次輸入只觸發一次
TextField(
keyboardType: TextInputType.datetime,
onTap: (){
print("tap...");
},
)
複製程式碼
onEditingComplete
- 鍵盤完成按鈕響應 - 無引數的onSubmitted
- 鍵盤完成按鈕響應 - 有引數的實現右邊圖示點選
- 預設沒有回撥,需要我們自己寫
class TestWidgetState extends State<TestWidget> {
var isCan = true;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
width: 200,
child: TextField(
decoration: InputDecoration(
suffixIcon: isCan
? GestureDetector(
child: Icon(Icons.clear),
onTap: () {
print("AAAAAA");
},
)
: null,
suffixText: isCan ? ":請確認" : null,
suffixStyle: TextStyle(fontSize: 16),
),
),
),
],
);
}
}
複製程式碼
輸入框樣式
Flutter 裡修改樣式啥的基本都是 decoration
,contain 裡是 BoxDecoration
,TextField 的則是 InputDecoration
,這部分內容也是相當多的,我拆開來說,我喜歡分門別類
1. 提示文字:
labelText/labelStyle
- 輸入框標題吧,在輸入內容的上面,在我們輸入之後,labelText 會有一個縮放的動畫的,style 是文字樣式,注意這個文字樣式只能在輸入之前管事helperText/helperStyle
- 輸入內容下部的提示文字errorText/errorStyle
- 錯誤提示文字,也是在輸入內容下部hintText/hintStyle
- 預設提示文字
TextField(
labelText: "姓名:",
labelStyle: TextStyle(
fontSize: 22,
),
helperText: '請輸入你的真實姓名',
helperStyle: TextStyle(
fontSize: 8,
),
errorText: "請重新輸入",
errorStyle: TextStyle(
fontSize: 12,
),
hintText: "請輸入文字",
hintStyle: TextStyle(
fontSize: 12,
),
)
複製程式碼
2. 左右提示和圖片
prefixIcon/prefixText/prefixStyle
- 左邊的圖示和文字,樣式看下面圖樣,提示文字不會進入到輸入內容的,這個測試過了suffixIcon/suffixText/suffixStyle
- 右邊的圖示和文字prefix/suffix
- 或者直接自己給一個 widget 也可以icon
- 左邊的圖示,但是圖示在輸入欄的外面,樣子看下面注意點
- 這裡的提示文字是隻有在輸入框拿到焦點時才會顯示,否則只會顯示 hint 文字suffix 點選
- 預設沒提供相關回撥,我們自己套一個GestureDetector
就行啦,測試過沒問題的,並且不會和onTap
衝突的
class TestWidgetState extends State<TestWidget> {
var editContore = TextEditingController();
var isCan = true;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
width: 200,
child: TextField(
decoration: InputDecoration(
icon: Icon(Icons.search),
prefixIcon: isCan ? Icon(Icons.access_alarm) : null,
prefixText: isCan ? "輸入:" : null,
prefixStyle: TextStyle(fontSize: 12),
suffixIcon: isCan
? GestureDetector(
child: Icon(Icons.clear),
onTap: () {
print("AAAAAA");
},
)
: null,
suffixText: isCan ? ":請確認" : null,
suffixStyle: TextStyle(fontSize: 16),
),
),
),
],
);
}
}
複製程式碼
3. 右小角統計數字
這個具體的文字樣式是自己做的,假如想要 6/10
這種樣式的,需要自己 setState 去修改文字
counterText
- 文字counterStyle
- 文字樣式counter
- 自定義 widget- 要是想達到圖中的效果:
var count = 0;
TextField(
decoration: InputDecoration(
counterText: "${count}/10",
),
onChanged: (inputValue) {
setState(() {
count = inputValue.length;
});
},
)
複製程式碼
4. 改顏色
filled/fillColor
- 修改輸入框背景色,filled 是個 boolean 值,用來控制顏色顯示的
TextField(
decoration: InputDecoration(
filled: true,
fillColor: Colors.grey,
),
)
複製程式碼
5. 修改邊框
邊框有3種:
InputBorder.none
- 沒有邊框,此模式下連下面的線都沒有了OutlineInputBorder
- 4面邊框,可以設定圓角
TextField(
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30), //邊角為30
),
borderSide: BorderSide(
color: Colors.amber, //邊線顏色為黃色
width: 2, //邊線寬度為2
),
),
)
複製程式碼
UnderlineInputBorder
- 底邊線,一樣可以設定圓角,不過不好看
TextField(
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30), //邊角為30
),
borderSide: BorderSide(
color: Colors.amber, //邊線顏色為黃色
width: 2, //邊線寬度為2
),
),
)
複製程式碼
輸入驗證
就是 TextInputFormatter
這個東西啦,他是一個抽象介面,具體實現有以下幾種:
WhitelistingTextInputFormatter
- 白名單校驗,也就是隻允許輸入符合規則的字元BlacklistingTextInputFormatter
- 黑名單校驗,除了規定的字元其他的都可以輸入LengthLimitingTextInputFormatter
- 長度限制,跟maxLength作用類似
效果呢就是輸入無效,你輸入的非法字元既無法顯示,也不被算作輸入之內
inputFormatters: [WhitelistingTextInputFormatter(RegExp("[a-z]"))],
複製程式碼
inputFormatters
的特點呢,就是可以接受多個格式驗證啦
- 首先
inputFormatters
接受的是[]
集合引數 - 再者其實現類,像
WhitelistingTextInputFormatter
他們接受的是Pattern
型別的資料,而正則RegExp
恰恰就實現了Pattern
,所以本質上接受的就是正規表示式
當然了,使用 inputFormatters
的話是沒辦法和 errorText
聯動的啦,如果要有這樣的效果,那麼就得自己在 onChange
中自己做正則判斷啦
Switch
Switch
不多做介紹,大家都知道的,flutter 的這個 Switch 可以設定選中時按鈕的顏色,圖示,橫條的顏色:
activeColor
- 選中時按鈕的顏色activeThumbImage
- 選中時按鈕的圖示activeTrackColor
- 選中時和橫條的顏色inactiveThumbColor
- 不選時按鈕的顏色inactiveTrackColor
- 不選時橫條的顏色inactiveThumbImage
- 不選時按鈕的圖示onChanged
- 點選影響value
- 當前值,這個必須一開始就寫上哈
Switch
在這裡的最大問題就是此存有點小,大家看下圖,這是相對整個螢幕的大小,而且 Switch 本身還不支援大小調整
class TestWidgetState extends State<TestWidget> {
bool _value = false;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
width: 200,
decoration: BoxDecoration(
color: Colors.tealAccent,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('關'),
Switch(
value: _value,
activeColor: Colors.blue,
activeTrackColor: Colors.green,
activeThumbImage: AssetImage(('assets/icons/icon_1.gif')),
inactiveThumbColor: Colors.red,
inactiveThumbImage: AssetImage(('assets/icons/icon_2.jpg')),
inactiveTrackColor: Colors.grey,
onChanged: (newValue) {
setState(() {
_value = newValue;
});
},
),
Text('開'),
],
),
);
}
}
複製程式碼
Radio
Radio
是單選按鈕,我總是和多選混。Flutter 的單選按鈕設計挺簡單的,使用 groupValue
參數列示一組單選按鈕的統一 ID,用相同 groupValue
的單選按鈕就算一組的,比在外面再加一層容器的思路靈活多了,這樣頁面好寫多了
value
- 單選按鈕值,這裡值是無實際意義,此值就是表示使用者點個哪個按鈕,配合列舉會好用很多groupValue
- 單選按鈕組統一 IDonChanged
- 回撥activeColor
- 選中時候的顏色
class TestWidgetState extends State<TestWidget> {
String _value = '1';
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Radio(
value: 'a',
activeColor: Colors.blue,
groupValue: _value,
onChanged: (newValue) {
setState(() {
print("a:${newValue}");
_value = newValue;
});
}
),
Text('開')
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Radio(
value: 'b',
activeColor: Colors.blue,
groupValue: _value,
onChanged: (newValue) {
setState(() {
print("b:${newValue}");
_value = newValue;
});
}
),
Text('關')
],
)
],
);
}
}
複製程式碼
Checkbox
Checkbox
Flutter 的一貫設計:書寫簡潔
、設計簡單
,多選按鈕組也是沒有外層容器那一說了,而是採用有多少個按鈕選項就配合多少個 boolean
引數的思路,配合上表驅動法的思路,很 Nice
value
- true 選中,fasle 不選中activeColor
- 選中時填充顏色checkColor
- 選中時 Icon 顏色
class TestWidgetState extends State<TestWidget> {
var _isBook = false;
var _isPrice = false;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Checkbox(
value: _isBook,
onChanged: (newValue) {
print('book:$newValue');
setState(() {
_isBook = newValue;
});
},
activeColor: Colors.red,
checkColor: Colors.blue,
),
Text("書"),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Checkbox(
value: _isPrice,
onChanged: (newValue) {
print('price:$newValue');
setState(() {
_isPrice = newValue;
});
},
activeColor: Colors.red,
checkColor: Colors.blue,
),
Text("價格"),
],
)
],
);
}
}
複製程式碼