分頁功能是閱讀器類軟件的基本功能之一, 也是本身以前寫閱讀器時遇到的第一個問題. 嘗試了很多辦法才解決, 如今把其中最容易實現的一個方法記錄下來, 也方便你們參考.canvas
基本思路以下:ide
總體思路很簡單, 其中惟一的難點就是第 4 步, 如何獲取 TextView 中的可見字數.函數
我遇到這類問題通常就是兩步走, 先文檔, 後源碼.佈局
因此先去查 Android 文檔, 看看 TextView 有沒有什麼能夠利用的函數. 在其中找到一個函數:指針
getLineBounds(int line, Rect bounds) // 獲得指定行的邊界
code
彷佛有點用. 只要從第一行開始一行一行往下看, 直到找到超出邊界的那一行, 就能知道這個 TextView 能顯示多少行了. 或者用 getHeight() / getLineHeight()
也能獲取 TextView 的最大顯示行數. 但因爲並不知道每行的字數, 因此仍是算不出來一頁到底有多少字.文檔
後來又嘗試了許多其餘方法, 也在提問區問過. 結果只獲得了一個建議, 就是本身寫個 View. 整個 View 都由本身實現的話, 的確能很方便地控制全部細節, 但隨之而來的麻煩就是, 全部的細節都得本身實現. 好比個人斷行, 和佈局自適應這兩點處理得就沒原生的 TextView 那麼好, 只能說勉強能用. 更別提超連接這類的東西了, 要想所有實現還真不是一時半會能搞定的.字符串
既然查文檔無果, 那就只能去看源碼了. 不看不知道, 這不起眼的 Textview 源碼竟然有近 9000 行, 頓時有點犯暈. 不過個人目標只有一個, 搞清楚 TextView 是怎麼排版的. 因此直接看 onDraw(Canvas canvas) 函數, 在其中找到這麼一行:get
layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
源碼
由此能夠推斷 TextView 排版及繪製文字靠的就是這個 layout, 因此馬上到文檔中找 Layout, 此次終於在其中找到了幾個有用的函數(就是那些 getLine*** 函數), 最有用的是這兩個:
getLineForVertical(int vertical) // 根據縱座標獲得對應的行號
和
getLineEnd(int line) // 返回指定行中最後一個字在整個字符串中的位置
因此咱們只要先計算出最下面一行是第幾行, 而後再算出這行最後一個字是第幾個字就好了.
先算行號:
public int getLineNum() { Layout layout = getLayout(); int topOfLastLine = getHeight() - getPaddingTop() - getPaddingBottom() - getLineHeight(); return layout.getLineForVertical(topOfLastLine); }
再算字數:
public int getCharNum() { return getLayout().getLineEnd(getLineNum()); }
這樣咱們就能獲得 TextView 在本頁所顯示的字數了.
public class ReadView extends TextView { // 構造函數略... @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); resize(); } /** * 去除當前頁沒法顯示的字 * @return 去掉的字數 */ public int resize() { CharSequence oldContent = getText(); CharSequence newContent = oldContent.subSequence(0, getCharNum()); setText(newContent); return oldContent.length() - newContent.length(); } /** * 獲取當前頁總字數 */ public int getCharNum() { return getLayout().getLineEnd(getLineNum()); } /** * 獲取當前頁總行數 */ public int getLineNum() { Layout layout = getLayout(); int topOfLastLine = getHeight() - getPaddingTop() - getPaddingBottom() - getLineHeight(); return layout.getLineForVertical(topOfLastLine); } }
示例工程下載: http://pan.baidu.com/share/link?shareid=3043803389&uk=1563550261