<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Flutter 中 TextField 組件必然會遇到的問題

          共 5788字,需瀏覽 12分鐘

           ·

          2021-11-28 09:49

          TextField 組件幾乎是開發(fā)中必然會用到的一個組件,在使用的過程中會遇到兩個非常棘手的問題:

          • 字數(shù)統(tǒng)計異常。
          • 設置高度,文字無法居中。

          字數(shù)統(tǒng)計異常

          一般情況下,實現(xiàn)字數(shù)統(tǒng)計方法如下:

          TextField(
          ??onChanged:?(value){
          ????setState(()?{
          ??????_textFieldValue?=?value;
          ????});
          ??},
          ??decoration:?InputDecoration(
          ??????counterText:?'${_textFieldValue.length}/32'
          ??),
          ),

          大部分情況下是沒有問題的,但是在 IOS 簡體拼音輸入法下有問題(可能其他輸入法也有類似的問題),效果如下:

          中文輸入法統(tǒng)計正在編輯中文的過程中會統(tǒng)計英文,假如限制5個中文,當輸入4個中文后,最后一個中文輸入2個及以上英文時,會觸發(fā)最大字數(shù)限制,這當然不是我們想要的效果。

          ?

          在去年的時候,這個Bug解決了很久都沒有解決,最終產品妥協(xié)去掉了這個功能,直到最近查看源碼的時候,無意中發(fā)現(xiàn)了這個Bug的解決方案。

          ?

          下面說下如何修復這個問題,關鍵是 TextField 中 「controller.value.composing」 這個屬性,官方文檔說明:

          ?

          The range of text that is still being composed.

          仍在編寫的文本范圍。

          ?

          就是上面GIF中出現(xiàn)下劃線的部分,字數(shù)統(tǒng)計計算:

          ??TextEditingController?_controller?=?TextEditingController();
          ??int?_wordLength?=?0;
          ??///?計算字數(shù),不算正在編輯的文字
          ??void?_computeWordCount()?{
          ????var?valueLength?=?_controller.value.text.length;
          ????var?composingLength?=
          ????????_controller.value.composing.end?-?_controller.value.composing.start;
          ????setState(()?{
          ??????_wordLength?=?valueLength?-?composingLength;
          ????});
          ??}

          TextField(
          ??controller:?_controller,
          ??onChanged:?(value){
          ????_computeWordCount();
          ??},
          ??decoration:?InputDecoration(
          ??????counterText:?'$_wordLength/32'
          ??),
          ),

          文字無法居中

          首先我們寫一個 「TextField」 的基本用法,為了方便定位文字是否居中,給 「TextField」 加上邊框:

          TextField(
          ??decoration:?InputDecoration(
          ????enabledBorder:?OutlineInputBorder(
          ??????borderSide:?BorderSide(color:?Color(0xFFDCDFE6)),
          ??????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ????),
          ????focusedBorder:?OutlineInputBorder(
          ??????borderSide:?BorderSide(color:?Color(0xFF409EFF)),
          ??????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ????),
          ??),
          ),

          此時文字是正好居中的,下面改變 TextField 的高度:

          Container(
          ??height:?30,
          ??child:?TextField(
          ????decoration:?InputDecoration(
          ??????enabledBorder:?OutlineInputBorder(
          ????????borderSide:?BorderSide(color:?Color(0xFFDCDFE6)),
          ????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????),
          ??????focusedBorder:?OutlineInputBorder(
          ????????borderSide:?BorderSide(color:?Color(0xFF409EFF)),
          ????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????),
          ????),
          ??),
          ),

          發(fā)現(xiàn)此時文字已經不居中了,當然網上有很多解決辦法,比如設置 contentPadding: EdgeInsets.symmetric(vertical: 0,horizontal: 12)

          Container(
          ??height:?30,
          ??child:?TextField(
          ????decoration:?InputDecoration(
          ??????fillColor:?Colors.white,
          ??????filled:?true,
          ??????enabledBorder:?OutlineInputBorder(
          ????????borderSide:?BorderSide(color:?Color(0xFFDCDFE6)),
          ????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????),
          ??????focusedBorder:?OutlineInputBorder(
          ????????borderSide:?BorderSide(color:?Color(0xFF409EFF)),
          ????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????),
          ??????contentPadding:?EdgeInsets.symmetric(vertical:?0,horizontal:?12),
          ????),
          ??),
          ),

          其實這種方式并沒有嚴格居中對齊,只不過偏差較小,勉強可以接受。

          看下面的例子,設置高度為150:

          Container(
          ??height:?150,
          ??color:?Colors.green.withOpacity(.5),
          ??child:?TextField(
          ????decoration:?InputDecoration(
          ??????fillColor:?Colors.white,
          ??????filled:?true,
          ??????enabledBorder:?OutlineInputBorder(
          ????????borderSide:?BorderSide(color:?Color(0xFFDCDFE6)),
          ????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????),
          ??????focusedBorder:?OutlineInputBorder(
          ????????borderSide:?BorderSide(color:?Color(0xFF409EFF)),
          ????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????),
          ????),
          ??),
          )

          發(fā)現(xiàn) TextField 的高度不是150,在 「maxLines = 1」 的情況下,通過設置 「contentPadding」 改變其高度,為了方便驗證是否居中,在中間繪制一條對齊線:

          Container(
          ??height:?150,
          ??color:?Colors.green.withOpacity(.5),
          ??child:?Stack(
          ????children:?[
          ??????TextField(
          ????????decoration:?InputDecoration(
          ??????????fillColor:?Colors.white,
          ??????????filled:?true,
          ??????????enabledBorder:?OutlineInputBorder(
          ????????????borderSide:?BorderSide(color:?Color(0xFFDCDFE6)),
          ????????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????????),
          ??????????focusedBorder:?OutlineInputBorder(
          ????????????borderSide:?BorderSide(color:?Color(0xFF409EFF)),
          ????????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????????),
          ??????????contentPadding:
          ??????????????EdgeInsets.symmetric(horizontal:?12,?vertical:?75),
          ????????),
          ??????),
          ??????Positioned.fill(
          ??????????child:?Divider(
          ????????height:?1,
          ????????color:?Colors.red,
          ??????)),
          ????],
          ??),
          ),

          發(fā)現(xiàn)其未居中,調整 「contentPadding」

          contentPadding:
          ????EdgeInsets.symmetric(horizontal:?12,?vertical:?67.5)

          我們改變文字的大小:

          Container(
          ??height:?150,
          ??color:?Colors.green.withOpacity(.5),
          ??child:?Stack(
          ????children:?[
          ??????TextField(
          ????????decoration:?InputDecoration(
          ??????????fillColor:?Colors.white,
          ??????????filled:?true,
          ??????????enabledBorder:?OutlineInputBorder(
          ????????????borderSide:?BorderSide(color:?Color(0xFFDCDFE6)),
          ????????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????????),
          ??????????focusedBorder:?OutlineInputBorder(
          ????????????borderSide:?BorderSide(color:?Color(0xFF409EFF)),
          ????????????borderRadius:?BorderRadius.all(Radius.circular(4.0)),
          ??????????),
          ??????????contentPadding:?EdgeInsets.symmetric(
          ??????????????horizontal:?12,?vertical:?67.5),
          ????????),
          ????????style:?TextStyle(fontSize:?30),
          ??????),
          ??????Positioned.fill(
          ??????????child:?Divider(
          ????????height:?1,
          ????????color:?Colors.red,
          ??????)),
          ????],
          ??),
          ),

          此時又不居中了,contentPadding** 需要設置的值是根據 TextField的高度 和 文字高度共同決定的,公式是:

          ?

          「( TextField的高度 - 文字高度)/2」

          ?

          我們需要計算出文字的高度:

          ????TextStyle?_style?=?const?TextStyle(fontSize:?30);
          ????var?textPainter?=?TextPainter(
          ??????text:?TextSpan(
          ????????text:?'',
          ????????style:?_style,
          ??????),
          ??????textDirection:?TextDirection.ltr,
          ??????textWidthBasis:?TextWidthBasis.longestLine,
          ????)..layout();

          「textPainter.height」 表示文字的高度。

          設置 contentPadding:

          contentPadding:?EdgeInsets.symmetric(
          ????horizontal:?12,
          ????vertical:?(150?-?textPainter.height)?/?2),

          以后再也不需要根據不同的高度和字體進行微調了。

          你可能還喜歡

          關注「老孟Flutter」
          讓你每天進步一點點
          瀏覽 186
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲一级黄片免费观看视频洲免费观看 | 操逼链接| 五月丁香婷婷在线 | 男人天堂日韩无码 | 夜色av无码 |