<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    Flutter 中 TextField 組件必然會(huì)遇到的問題

    共 5788字,需瀏覽 12分鐘

     ·

    2021-11-28 09:49

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

    • 字?jǐn)?shù)統(tǒng)計(jì)異常。
    • 設(shè)置高度,文字無法居中。

    字?jǐn)?shù)統(tǒng)計(jì)異常

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

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

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

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

    ?

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

    ?

    下面說下如何修復(fù)這個(gè)問題,關(guān)鍵是 TextField 中 「controller.value.composing」 這個(gè)屬性,官方文檔說明:

    ?

    The range of text that is still being composed.

    仍在編寫的文本范圍。

    ?

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

    ??TextEditingController?_controller?=?TextEditingController();
    ??int?_wordLength?=?0;
    ??///?計(jì)算字?jǐn)?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'
    ??),
    ),

    文字無法居中

    首先我們寫一個(gè) 「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)),
    ????),
    ??),
    ),

    此時(shí)文字是正好居中的,下面改變 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)此時(shí)文字已經(jīng)不居中了,當(dāng)然網(wǎng)上有很多解決辦法,比如設(shè)置 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),
    ????),
    ??),
    ),

    其實(shí)這種方式并沒有嚴(yán)格居中對齊,只不過偏差較小,勉強(qiáng)可以接受。

    看下面的例子,設(shè)置高度為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」 的情況下,通過設(shè)置 「contentPadding」 改變其高度,為了方便驗(yàn)證是否居中,在中間繪制一條對齊線:

    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)其未居中,調(diào)整 「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,
    ??????)),
    ????],
    ??),
    ),

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

    ?

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

    ?

    我們需要計(jì)算出文字的高度:

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

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

    設(shè)置 contentPadding:

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

    以后再也不需要根據(jù)不同的高度和字體進(jìn)行微調(diào)了。

    你可能還喜歡

    關(guān)注「老孟Flutter」
    讓你每天進(jìn)步一點(diǎn)點(diǎn)
    瀏覽 186
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評論
    圖片
    表情
    推薦
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    日韩视频在线观看二区 | 中文字幕亚洲高清 | 日视频啪啪啪在线观看 | 国产理伦| 日本黄色美女网站 |