一、情景再現
當TextView的高度寬度爲固定大小時,隨着其Text的動態增加,導致TextView的顯示範圍以無法滿足完全顯示所有Text時,這個時候TextView會直接不顯示後面動態增加的文字,這個時候我們很可能其實是想顯示後面動態增加的文字,那麼這個時候我們就需要就算該TextView可以顯示的文字範圍,然後動態的顯示我們需要顯示的某一範圍的文字。
例如,有一個動態文字:端午節可以去你家喫糉子嗎?我可以幫你跑8公里
我們沒有處理前,可能是這樣動態顯示:
可以看到當我們增加了第二句話之後,TextView已經無法顯示完整了,導致看不到第二句話。
處理後我們可以選擇某個範圍,例如可能之前我們已經看到了前面的文字,只想顯示後面的:
二、實現原理
那麼上面的 功能是如何實現的呢?接下來我們來分析下:
假如這是一個TextView,當然實際中,還沒顯示文字的時候我們是不知道它有能力顯示多少行的
如果我們要想知道這個TextView可以顯示多少個文字,只需要計算TextView顯示的總寬度,文字的寬度,當文字的寬度大於TextView顯示的總寬度時,通過取文本區間,得以按照你想要的文本顯示在TextView上
那麼,我們怎麼接着看看怎麼計算TextView可以顯示的總寬度和文本的寬度:
1.首先我們得計算TextView 單行的寬度,viewWidth
private int lineHeight=0;
private int viewHeight=0;
private int viewWidth=0;
private int maxLine=0;
private int totalWidth=0;
viewWidth = textView.getMeasuredWidth();
2.計算TextView可以顯示多少行 maxLine,通過 總高度/行高,
viewHeight = textView..getMeasuredHeight();
lineHeight = textView..getLineHeight();
maxLine = viewHeight/lineHeight;
textView.setMaxLines(maxLine);
3.接着得到總寬度
totalWidth = viewWidth * maxLine ;
4.計算文本的寬度
TextPaint textPaint = textView.getPaint();
float textPaintWidth = textPaint.measureText(text);
5.接着就是按照你自己想要顯示的方式遞歸計算最終需要顯示的結果即可,例如我這裏同構先進先出計算顯示的文字,得到如下遞歸函數,其他的顯示需求讀者自己舉一反三,自由發揮。
public String calculateTextPreScreen(String tempStr, TextPaint textPaint, int width) {
if (tempStr == null) {
return "";
}
float textPaintWidth = textPaint.measureText(tempStr);
if (textPaintWidth > width) {
for (int i = 1; i < tempStr.length(); i++) {
String tempSubStr = tempStr.substring(i, tempStr.length());
return calculateTextPreScreen(tempSubStr, textPaint, width);
}
}
return tempStr;
}
最後需要注意的是,TextView的高度和寬度需要在View繪製完成之後才能獲取,通過如下方式:
textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (viewHeight!=0){
viewWidth = textView.getMeasuredWidth();
viewHeight = textView..getMeasuredHeight();
lineHeight = textView..getLineHeight();
maxLine = viewHeight/lineHeight;
totalWidth = viewWidth * maxLine ;
textView.setMaxLines(maxLine);
textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
};