老孟導讀:你們好,這是【Flutter實戰】系列文章的第二篇,這一篇講解文本組件,文本組件包括文本展現組件(Text和RichText)和文本輸入組件(TextField),基礎用法和五個案例助你快速掌握。
第一篇連接: 【Flutter實戰】移動技術發展史
Text是顯示文本的組件,最經常使用的組件,沒有之一。基本用法以下:前端
Text('老孟')
注意:Text組件必定要包裹在Scaffold組件下,不然效果以下:android
文本的樣式在style
中設置,類型爲TextStyle
,TextStyle
中包含不少文本樣式屬性,下面介紹一些經常使用的。ios
設置文本大小和顏色:git
Text('老孟',style: TextStyle(color: Colors.red,fontSize: 20),),
上面黑色的字體爲沒有設置的效果,做爲對比。github
設置字體粗細:api
Text('老孟',style: TextStyle(fontWeight: FontWeight.bold))
字體粗細共有9個級別,爲w100
至w900
,FontWeight.bold是w700
。微信
設置斜體:ide
Text('老孟',style: TextStyle(fontStyle: FontStyle.italic,))
設置自定義的字體:post
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
只是控制水平方向的對齊方式,值說明以下:
TextDirection
屬性有關,若是設置TextDirection.ltr
,則左對齊,設置TextDirection.rtl
則右對齊。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,), )
溢出的處理方式:
設置全局字體樣式:
在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的屬性和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()
不須要任何參數,一個最簡單的文本輸入組件就出來了,效果以下:
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
參數控制軟鍵盤的類型,說明以下:
textInputAction
參數控制軟鍵盤右下角的按鍵,說明以下:
你們可能發現了,Android上顯示的按鈕大部分是不肯定的,好比next
有的顯示向右的箭頭,有的顯示前進,這是由於各大廠商對Android ROM定製引起的。
textCapitalization
參數是配置鍵盤是大寫仍是小寫,僅支持鍵盤模式爲text
,其餘模式下忽略此配置,說明以下:
這裏僅僅是控制軟鍵盤是大寫模式仍是小寫模式,你也能夠切換大小寫,系統並不會改變輸入框內的內容。
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個控件用法):http://laomengit.com
歡迎加入Flutter交流羣(微信:laomengit)、關注公衆號【老孟Flutter】: