老孟導讀:大家好,這是【Flutter實戰】系列文章的第二篇,這一篇講解文字元件,文字元件包括文字展示元件(Text和RichText)和文字輸入元件(TextField),基礎用法和五個案例助你快速掌握。 第一篇連結:【Flutter實戰】移動技術發展史
Text
Text是顯示文字的元件,最常用的元件,沒有之一。基本用法如下:
Text('老孟')複製程式碼
注意:Text元件一定要包裹在Scaffold元件下,否則效果如下:
文字的樣式在style
中設定,型別為TextStyle
,TextStyle
中包含很多文字樣式屬性,下面介紹一些常用的。
設定文字大小和顏色:
Text('老孟',style: TextStyle(color: Colors.red,fontSize: 20),),複製程式碼
上面黑色的字型為沒有設定的效果,作為對比。
設定字型粗細:
Text('老孟',style: TextStyle(fontWeight: FontWeight.bold))複製程式碼
字型粗細共有9個級別,為w100
至w900
,FontWeight.bold是w700
。
設定斜體:
Text('老孟',style: TextStyle(fontStyle: FontStyle.italic,))複製程式碼
設定自定義的字型:
- 首先下載字型庫(比如中華字型庫)
- 將字型檔案拷貝的專案中,一般目錄是:assets/fonts/,assets和fonts都需要手動建立,此目錄不是必須的,而是約定俗成,資源一般都放在assets目錄下。
- 配置
pubspec.yaml
:
fonts:
- family: maobi
fonts:
- asset: assets/fonts/maobi.ttf複製程式碼
maobi:是自己對當前字型的命名,有意義即可。
asset:字型檔案的目錄。
使用:
Text('老孟', style: TextStyle(fontFamily: 'maobi',)),複製程式碼
設定對齊方式:
Container(
height: 100,
width: 200,
color: Colors.blue.withOpacity(.4),
child: Text('老孟', textAlign: TextAlign.center),
),複製程式碼
textAlign
只是控制水平方向的對齊方式,值說明如下:
- left:左對齊
- right:右對齊
- center:居中
- justify:兩端對齊,此屬性中文存在bug(Flutter版本:1.17.3)也可以在官方issue中關注此問題
- start:前端對齊,和
TextDirection
屬性有關,如果設定TextDirection.ltr
,則左對齊,設定TextDirection.rtl
則右對齊。 - end:末端對齊,和
TextDirection
屬性有關,如果設定TextDirection.ltr
,則右對齊,設定TextDirection.rtl
則左對齊。
設定文字自動換行:
Container(
height: 100,
width: 200,
color: Colors.blue.withOpacity(.4),
child: Text('老孟,專注分享Flutter技術和應用實戰',softWrap: true,),
)複製程式碼
文字超出範圍時的處理:
Container(
height: 100,
width: 200,
color: Colors.blue.withOpacity(.4),
child: Text('老孟,專注分享Flutter技術和應用實戰',overflow: TextOverflow.ellipsis,),
)複製程式碼
溢位的處理方式:
- clip:直接裁剪。
- fade:越來越透明。
- ellipsis:省略號結尾。
- visible:依然顯示,此時將會溢位父元件。
設定全域性字型樣式:
在MaterialApp
的theme
中設定如下
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
...
textTheme: TextTheme(
bodyText2: TextStyle(color: Colors.red,fontSize: 24),
)
),
home: Scaffold(
body: TextDemo(),
),
)複製程式碼
Text元件預設為紅色,
Text('老孟'),
Text('老孟',style: TextStyle(color: Colors.blue,fontSize: 20),),複製程式碼
RichText
RichText的屬性和Text基本一樣,使用如下:
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <InlineSpan>[
TextSpan(text: '老孟', style: TextStyle(color: Colors.red)),
TextSpan(text: ','),
TextSpan(text: '專注分享Flutter技術和應用實戰'),
]),
)複製程式碼
TextField
TextField是文字輸入元件,即輸入框,常用元件之一。基本用法:
TextField()複製程式碼
不需要任何引數,一個最簡單的文字輸入元件就出來了,效果如下:
decoration
是TextField元件的裝飾(外觀)引數,型別是InputDecoration。
icon
顯示在輸入框的前面,用法如下:
TextField(
decoration: InputDecoration(
icon: Icon(Icons.person),
),
)複製程式碼
當輸入框是空而且沒有焦點時,labelText顯示在輸入框上邊,當獲取焦點或者不為空時labelText往上移動一點,labelStyle
參數列示文字樣式,具體參考TextStyle
, 用法如下:
TextField(
decoration: InputDecoration(
labelText: '姓名:',
labelStyle: TextStyle(color:Colors.red)
),
)複製程式碼
hasFloatingPlaceholder
引數控制當輸入框獲取焦點或者不為空時是否還顯示labelText
,預設為true,顯示。
helperText
顯示在輸入框的左下部,用於提示使用者,helperStyle
參數列示文字樣式,具體參考TextStyle
用法如下:
TextField(
decoration: InputDecoration(
helperText: '使用者名稱長度為6-10個字母',
helperStyle: TextStyle(color: Colors.blue),
helperMaxLines: 1
),
)複製程式碼
hintText
是當輸入框為空時的提示,不為空時不在顯示,用法如下:
TextField(
decoration: InputDecoration(
hintText: '請輸入使用者名稱',
hintStyle: TextStyle(color: Colors.grey),
hintMaxLines: 1
),
)複製程式碼
errorText
顯示在輸入框的左下部,預設字型為紅色,用法如下:
TextField(
decoration: InputDecoration(
errorText: '使用者名稱輸入錯誤',
errorStyle: TextStyle(fontSize: 12),
errorMaxLines: 1,
errorBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.red)),
),
)複製程式碼
prefix
系列的元件是輸入框前面的部分,用法如下:
TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.person)
),
)複製程式碼
注意prefix和icon的區別,icon是在輸入框邊框的外部,而prefix在裡面。
suffix和prefix相反,suffix在輸入框的尾部,用法如下:
TextField(
decoration: InputDecoration(
suffixIcon: Icon(Icons.person)
),
)複製程式碼
counter
元件統計輸入框文字的個數,counter僅僅是展示效果,不具備自動統計字數的功能, 自動統計字數程式碼如下:
var _textFieldValue = '';
TextField(
onChanged: (value){
setState(() {
_textFieldValue = value;
});
},
decoration: InputDecoration(
counterText: '${_textFieldValue.length}/32'
),
)複製程式碼
filled
為true時,輸入框將會被fillColor
填充,仿QQ登入輸入框程式碼如下:
Container(
height: 60,
width: 250,
child: TextField(
decoration: InputDecoration(
fillColor: Color(0x30cccccc),
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0x00FF0000)),
borderRadius: BorderRadius.all(Radius.circular(100))),
hintText: 'QQ號/手機號/郵箱',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0x00000000)),
borderRadius: BorderRadius.all(Radius.circular(100))),
),
),
)複製程式碼
controller
是輸入框文字編輯的控制器,可以獲取TextField的內容、設定TextField的內容,下面將輸入的英文變為大寫:
TextEditingController _controller;
@override
void initState() {
super.initState();
_controller = TextEditingController()
..addListener(() {
//獲取輸入框的內容,變為大寫
_controller.text = _controller.text.toUpperCase();
});
}
@override
Widget build(BuildContext context) {
return TextField(
controller: _controller,
);
}
@override
dispose() {
super.dispose();
_controller.dispose();
}複製程式碼
有時輸入框後面帶有“清除”功能,需要controller來實現。如果需要2個TextField的內容進行同步,只需要給2個TextField設定同一個controller即可實現。
keyboardType
引數控制軟鍵盤的型別,說明如下:
- text:通用鍵盤。
- multiline:當TextField為多行時(maxLines設定大於1),右下角的為“換行” 按鍵。
- number:數字鍵盤。
- phone:手機鍵盤,比數字鍵盤多"*"和 "#"。
- datetime:在ios上和text一樣,在android上出現數字鍵盤、":"和 "-"。
- emailAddress:郵箱鍵盤,有"@" 和 "."按鍵。
- url:url鍵盤,有"/" 和 "."按鍵。
- visiblePassword:既有字幕又有數字的鍵盤。
textInputAction
引數控制軟鍵盤右下角的按鍵,說明如下:
- none:android上顯示返回鍵,ios不支援。
- unspecified:讓作業系統自己決定哪個合適,一般情況下,android顯示“完成”或者“返回”。
- done:android顯示代表“完成”的按鈕,ios顯示“Done”(中文:完成)。
- go:android顯示錶達使用者去向目的地的圖示,比如向右的箭頭,ios顯示“Go”(中文:前往)。
- search:android顯示錶達搜尋的按鈕,ios顯示"Search"(中文:搜尋)。
- send:android顯示錶達傳送意思的按鈕,比如“紙飛機”按鈕,ios顯示"Send"(中文:傳送)。
- next:android顯示錶達“前進”的按鈕,比如“向右的箭頭”,ios顯示"Next"(中文:下一項)。
- previous:android顯示錶達“後退”的按鈕,比如“向左的箭頭”,ios不支援。
- continueAction:android 不支援,ios僅在ios9.0+顯示"Continue"(中文:繼續)。
- join:Android和ios顯示"Join"(中文:加入)。
- route:android 不支援,ios顯示"Route"(中文:路線)。
- emergencyCall:android 不支援,ios顯示"Emergency Call"(中文:緊急電話)。
- newline:android顯示錶達“換行”的按鈕,ios顯示”換行“。
大家可能發現了,Android上顯示的按鈕大部分是不確定的,比如next
有的顯示向右的箭頭,有的顯示前進,這是因為各大廠商對Android ROM定製引發的。
textCapitalization
引數是配置鍵盤是大寫還是小寫,僅支援鍵盤模式為text
,其他模式下忽略此配置,說明如下:
- words:每一個單詞的首字母大寫。
- sentences:每一句話的首字母大寫。
- characters:每個字母都大寫
- none:都小寫
這裡僅僅是控制軟鍵盤是大寫模式還是小寫模式,你也可以切換大小寫,系統並不會改變輸入框內的內容。
textAlignVertical
表示垂直方向的對齊方式,textDirection
表示文字方向,用法如下:
TextField(
textAlignVertical: TextAlignVertical.center,
textDirection: TextDirection.rtl,
)複製程式碼
toolbarOptions
表示長按時彈出的選單,有copy
、cut
、paste
、selectAll
,用法如下:
TextField(
toolbarOptions: ToolbarOptions(
copy: true,
cut: true,
paste: true,
selectAll: true
),
)複製程式碼
cursor
表示游標,用法如下:
TextField(
showCursor: true,
cursorWidth: 3,
cursorRadius: Radius.circular(10),
cursorColor: Colors.red,
)複製程式碼
效果如下:
將輸入框設定為密碼框,只需obscureText
屬性設定true即可,用法如下:
TextField(
obscureText: true,
)複製程式碼
通過inputFormatters
可以限制使用者輸入的內容,比如只想讓使用者輸入字元,設定如下:
TextField(
inputFormatters: [
WhitelistingTextInputFormatter(RegExp("[a-zA-Z]")),
],
)複製程式碼
這時使用者是無法輸入數字的。
onChanged
是當內容發生變化時回撥,onSubmitted
是點選回車或者點選軟鍵盤上的完成回撥,onTap
點選輸入框時回撥,用法如下:
TextField(
onChanged: (value){
print('onChanged:$value');
},
onEditingComplete: (){
print('onEditingComplete');
},
onTap: (){
print('onTap');
},
)複製程式碼
輸入框右下角經常需要字數統計,除了使用上面介紹的方法外,還可以使用buildCounter
,建議使用此方法,用法如下:
TextField(
maxLength: 100,
buildCounter: (
BuildContext context, {
int currentLength,
int maxLength,
bool isFocused,
}) {
return Text(
'$currentLength/$maxLength',
);
},
)複製程式碼
動態獲取焦點
FocusScope.of(context).requestFocus(_focusNode);複製程式碼
_focusNode
為TextField的focusNode:
_focusNode = FocusNode();
TextField(
focusNode: _focusNode,
...
)複製程式碼
動態失去焦點
_focusNode.unfocus();複製程式碼
過渡顏色的文字
Builder(
builder: (BuildContext context) {
RenderBox box = context.findRenderObject();
final Shader linearGradient = LinearGradient(
colors: <Color>[Colors.purple, Colors.blue],
).createShader(
Rect.fromLTWH(0.0, 0.0, box?.size?.width, box?.size?.height));
return Text(
'老孟,專注分享Flutter技術和應用實戰',
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
foreground: Paint()..shader = linearGradient),
);
},
)複製程式碼
Builder
元件是為了計算當前Text元件大小,生成LinearGradient。
帶前後置標籤的文字
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <InlineSpan>[
WidgetSpan(
child: Container(
margin: EdgeInsets.only(right: 10),
padding: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.blue),
child: Text(
'判斷題',
style: TextStyle(color: Colors.white),
),
)),
TextSpan(text: '泡沫滅火器可用於帶電滅火'),
]),
)複製程式碼
“服務協議”
通常在登入頁面的底部會出現登入即代表同意並閱讀 《服務協議》,其中《服務協議》為藍色且可點選:
Text.rich(
TextSpan(
text: '登入即代表同意並閱讀',
style: TextStyle(fontSize: 11, color: Color(0xFF999999)),
children: [
TextSpan(
text: '《服務協議》',
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
recognizer: TapGestureRecognizer()
..onTap = () {
print('onTap');
},
),
]),
)複製程式碼
登入密碼輸入框
TextField(
decoration: InputDecoration(
fillColor: Color(0x30cccccc),
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0x00FF0000)),
borderRadius: BorderRadius.all(Radius.circular(100))),
hintText: '輸入密碼',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0x00000000)),
borderRadius: BorderRadius.all(Radius.circular(100))),
),
textAlign: TextAlign.center,
obscureText: true,
onChanged: (value) {
},
)複製程式碼
評論回覆
Text.rich(
TextSpan(
text: '回覆',
style: TextStyle(fontSize: 11, color: Color(0xFF999999)),
children: [
TextSpan(
text: '@老孟:',
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
recognizer: TapGestureRecognizer()
..onTap = () {
print('onTap');
},
),
TextSpan(
text: '你好,想知道Flutter發展前景如何?',
),
]),
)複製程式碼
交流
老孟Flutter部落格地址(330個控制元件用法):laomengit.com
歡迎加入Flutter交流群(微信:laomengit)、關注公眾號【老孟Flutter】: