詳解Flutter如何獲取Text截斷后的字符串
問題
當(dāng)Text
文本設(shè)置maxLins
屬性將文本強(qiáng)制截斷之后,Text
的承載字符串是截斷前?還是截斷后的呢?我們該如何獲取截斷后的字符串呢?
答案是:截斷前,截斷字符串的操作并不會改變Text
的真實文本內(nèi)容屬性,無論原生還是Flutter
截斷字符串的操作只是對TextUI
組件的繪制區(qū)域施加一個限制。
那么我們需要從源碼里看下當(dāng)我們設(shè)置了maxLine
這個屬性以后,文本Text
究竟是如何截斷顯示的, 跟隨著源碼一探究竟。
首先看到Text只是一個簡單的靜態(tài)組件StatelessWidget
從build方法中可以看到返回的是一個RichText,并將maxLines參數(shù)進(jìn)行傳遞。
接著往下看RichText,可以看到RichText繼承了MultiChildRenderObjectWidget
多子渲染W(wǎng)idget,一定有創(chuàng)建渲染對象的地方。
通過createRenderObject對象返回 RenderParagraph
對象,并將maxLine參數(shù)繼續(xù)傳遞
點(diǎn)進(jìn)去看一看,記住這個渲染對象
通過構(gòu)造方法將參數(shù)傳遞給自身維護(hù)的私有成員變量 TextPainter
,這個對象是Flutter的文本繪制器,通過它來處理文本的布局與繪制,那繼續(xù)點(diǎn)進(jìn)去看一看。
最終在布局和繪制方法時會觸發(fā)_createParagraphStyle
方法,返回ParagraphStyle
對象,這里的觸發(fā)時機(jī)就是上面渲染對象布局繪制時調(diào)用的,所以也可以理解TextPainter
就是Flutter框架渲染文本處理的封裝對象。
這個對象主要用來確定文本的段落樣式,而maxLines截取操作只會影響段落的顯示,并不會影響文本本身的樣式,這里判斷了是否設(shè)置了文本TextStyle樣式。如果沒有設(shè)置使用默認(rèn)的樣式。 點(diǎn)進(jìn)去看一看
最終通過構(gòu)造方法觸發(fā)_encodeParagraphStyle
方法,文本屬性會直接通過和c++層交互進(jìn)行保存,TextStyle和StrutStyle樣式的設(shè)置原理也一樣。最后通過渲染對象觸發(fā)layout方法確定文本繪制區(qū)域,也就是說設(shè)置maxLines之后文本內(nèi)容不會改變,但文本的繪制區(qū)域會發(fā)生改變。
解決方案
我們現(xiàn)在知道maxLine
本身是針對UI來進(jìn)行截斷的,并不會改變設(shè)置的內(nèi)容屬性,如果想要獲取截斷后的文本數(shù)據(jù)我們該如何操作呢, 其實TextPainter
給我們提供了一些Api方法,我們可以直接使用。
通過didExceedMaxLines
方法我們可以判斷出,該文本是否超過最大行設(shè)置。
通過getPositionForOffset
可以返回一個TextPosition
對象,里面的offset
屬性就是我們需要的截斷后字符串在原始文本當(dāng)中的index索引。
代碼:
class TextUtil { /// 獲取最大行文字字?jǐn)?shù) static int calculateTextMaxTextPos(String value, double fontSize, {required double fontHeight, required double maxWidth, required EdgeInsetsGeometry padding, int maxLines = 3}) { final TextPainter painter = TextPainter( locale: WidgetsBinding.instance.window.locale, textDirection: TextDirection.ltr, maxLines: maxLines, strutStyle: StrutStyle(forceStrutHeight: true, fontSize: fontSize, height: fontHeight), text: TextSpan( text: value, style: TextStyle( height: fontHeight, fontSize: fontSize, ), ), textAlign: TextAlign.center); painter.layout(maxWidth: maxWidth - padding.horizontal); final didExceedMaxLines = painter.didExceedMaxLines; // print('是否超出最大行$didExceedMaxLines'); if (didExceedMaxLines) { final position = painter.getPositionForOffset(Offset( painter.width, painter.height, )); return position.offset; } return 0; } }
使用場景
有了這個方法,我們在一些產(chǎn)品需求為文字末尾添加展開收起的騷操作就非常的方便了,具體的封裝就留給你們啦,而且通過這種方式還可以計算電子書每頁數(shù)據(jù),也是非常的快速,同時也優(yōu)化了下之前模擬手勢翻頁電子書的計算。相較于之前計算文字高度計算量少了很多。
鏈接:booxfx 電子書模擬手勢翻頁。
到此這篇關(guān)于詳解Flutter如何獲取Text截斷后的字符串的文章就介紹到這了,更多相關(guān)Flutter獲取字符串內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android利用ShaderMask實現(xiàn)花里胡哨的文字特效
我們的?App?大部分時候的文字都是一種顏色,實際上,文字的顏色也可以多姿多彩。我們今天就來介紹一個能夠輕松實現(xiàn)文字漸變色的組件?——?ShaderMask,感興趣的可以了解一下2022-12-12Android編程ProgressBar自定義樣式之動畫模式實現(xiàn)方法
這篇文章主要介紹了Android編程ProgressBar自定義樣式之動畫模式實現(xiàn)方法,涉及Android動畫模式的布局技巧,非常具有實用價值,需要的朋友可以參考下2015-10-10Android開發(fā)中怎樣調(diào)用系統(tǒng)Email發(fā)送郵件(多種調(diào)用方式)
在Android中調(diào)用其他程序進(jìn)行相關(guān)處理,幾乎都是使用的Intent,所以,Email也不例外,所謂的調(diào)用Email,只是說Email可以接收Intent并做這些事情2013-06-06Android隱私協(xié)議提示彈窗的實現(xiàn)流程詳解
這篇文章主要介紹了Android隱私協(xié)議提示彈窗的實現(xiàn)流程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01Android App開發(fā)中HTTP擴(kuò)展包OkHttp的入門使用指南
OkHttp包為安卓開發(fā)中基于HTTP協(xié)議的網(wǎng)絡(luò)編程提供了很大便利,這里我們就來看一下Android App開發(fā)中HTTP擴(kuò)展包OkHttp的入門使用指南:2016-07-07優(yōu)化SimpleAdapter適配器加載效率的方法
下面小編就為大家?guī)硪黄獌?yōu)化SimpleAdapter適配器加載效率的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04