如何在 Android 的 textview 里獲取行數?
TextView可以通過getLineCount獲取行數,但是這裡要在控制項繪畫後才能獲取,否則調用這個函數返回值為0。但是我想在addText時就獲得text的行數,這樣我可以控制TextView的高度,請問有沒有一些開源的代碼或者想法可以實現在addText獲取行數呢?
手機答題,等回去了補充鏈接等。
Android 本身提供了 BoringLayout, StaticLayout 或 DynamicLayout 用於處理文本的換行和樣式繪製,TextView 類內部也是用這三個 Layout 處理文本的。
BoringLayout 是單行,根據題主的需要選擇支持多行的 StaticLayout.
官方文檔如下:
StaticLayoutDynamicLayout構造函數里提供所需寬度(比如屏幕寬度減去 marginLeft 和 marginRight),文本 (CharSequence, 支持 Span),對應的 TextPaint, 兩個行間距 (multiplier 和 add, 如果為一倍行距就分別為 1.0f 和 0f ),隨後即可通過 Layout 提供的 getLineCount() 方法獲得行數,getHeight() 獲得文本總高度。Layout 這幾個類還提供比如某一行的 start, end, top, width, offset 等等。
這種方法的不需要 View measure, 只需要計算出寬度即可 (一般 View 寬度可根據屏幕寬度等等計算出來),避免了實例化 TextView 可能遇到的需要多次 measure, layout 問題,但相關參數 (字體,字型大小,行間距) 一定要與你用於顯示的 TextView 一致以保證結果正確。以後這種問題,就不要知乎里問了吧
你可以首先用 textView.measure()的方法去動態獲取全部文字畫出後的高度,然後再計算出只畫一行的高度,這樣就可以得到一共可以占幾行
附加方法給你吧:
private int measureTextViewHeight(String text, int textSize, int deviceWidth) {
TextView textView = new TextView(getContext());
textView.setText(text);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(deviceWidth, MeasureSpec.AT_MOST);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
textView.measure(widthMeasureSpec, heightMeasureSpec);
return textView.getMeasuredHeight();
}
正好項目里遇到了,給你解答一下:這個監聽器看名字也知道了,就是在繪畫完成之前調用的,在這裡面可以獲取到行數,當然也可以獲取到寬高等信息。
final TextView totalTitleNo = (TextView) findViewById(R.id.tv_ac_sub_account);
ViewTreeObserver vto = totalTitleNo.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int lineCount = totalTitleNo.getLineCount();
System.out.println(lineCount);
}
});
當TextView 在listview 中復用的時候 這個情況有人考慮過沒有
這個問題大家已經回答得很好了,在這裡我「狗尾續貂」補充一下:
這種類型的問題其實說白了要怎麼拿到已經繪製好的View的相關數據,比如寬高,間距,還有題目中的行數等
如果在onCreate()中如果直接去取,取得的數據往往為0,因為View還沒有繪製完成。
那我在onResume()中去取呢?抱歉,還是取不到。
在任玉剛老師的《Android開發藝術探索》中給了幾個方案,其中一個是利用Activity中的onWindowFocusChanged,當hasFocus為true的時候頁面就繪製完成了,所以這個時候你可以取得相關數據。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
}
這個方法的缺陷在於如果我的View層是Fragment的話,需要做一個回調,而在自定義View或者封裝管理類中調用更是較為繁瑣,所以有了另一個方案:
view.post(new Runnable() {
@Override
public void run() {
}
});
這裡我的理解是,post發送的消息會在主線程的消息隊列的最後,所以Runnable的操作會在View繪製之後才執行。
為了防止重複創建線程,你可以在初始化的時候就把線程創建好,如果是在ListView或者RecyclerView的適配器中使用的話:)
play.post(new Runnable() {
@Override
public void run() {
Log.d("after", play.getHeight() + "");
}
});
最近發現這個問題,挖個墳~
在onCreate()中估計不好獲取,不過等頁面宣染好了可以通過getLineCount()獲取
推薦閱讀:
※如何進一步提高Android技術能力?
※當 Activity 以全屏模式運行時,如何允許 Android 系統狀態欄在頂層出現,而不迫使 Activity 重新布局讓出空間?
※Android開發中在哪些場合下會需要使用AIDL?
※怎樣才能獲得編程開發的樂趣?
※怎樣著手研究 Android 源代碼?
TAG:Android開發 |