Android高仿qq閱讀/微信讀書/掌閱高亮選擇文字效果

布丁西西發表於2018-06-06

前言

   最近做epub閱讀器,有劃線的需求,即類似於qq閱讀/微信讀書/掌閱那樣的移動選擇文字並高亮劃線等,在這裡記錄下實現的思路供大家參考,功能都還沒有上線,等優化徹底了,我可以考慮抽出這個模組開源下,嘿嘿!

 

實現的效果圖

 

 

可以看到,這個效果還是可以的,目前來說,我是將這個移動選擇繪製在文字的上層,即蓋一個顏色的透明層,最好的移動繪製是在文字的下方繪製,這樣文字的顏色不會因為繪製而模糊改變,微信讀書/掌閱是繪製在下方的,qq閱讀應該和我的實現方法類似,在文字的上層繪製,繪製的顏色帶點透明度,不過我文字的底部劃線必須和文字在一個canvas畫布上,否則你移動的時候,會發現劃線和文字不是同時移動,就是因為不在同一個canvas上的問題.

 

主要實現步驟

 

 

 閱讀器實現原理

 

  閱讀器每個頁面其實是由底層C++(編寫對應so庫)繪製文字並生成一個圖片供java上層呼叫,所以說,這些頁面本身是一張圖片bitmap,其實我們就是在這個bitmap上做文章,比如繪製文章章節的頭部資訊,底部頁碼資訊,長按移動選擇文字等.目前市面上的閱讀器應該都是這個實現的思路,即底層繪製,分頁提供so庫供上層呼叫顯示.

 

 頁面資訊

 

   雖然底層返回的是一張圖片給上層,但是每個頁面所包含的文字資訊(包括文字的座標,文字內容,段落ID等)都會返回給上層,我門根據座標繪製即可.

 ios文字座標計算:直接使用改座標x,y即可;安卓我的演算法目前是這樣的:x * density,y * density 即乘以螢幕的密度,按道理說最好直接使用底層提供的x,y,後續這塊還可以優化,這塊主要是底層的座標計算問題,目前乘以螢幕的密度,可以準確定位到當前文字的位置,無論文字怎麼放大縮小,劃線均可以準確的顯示到該文字的下方,畢竟是根據座標來劃線的.

 有了文字的x,y位置座標,其實繪製就簡單多了,當前選中的區域是一段段Rect區域,使用path 動態的將他們聯絡在一起即可.

比如文字F的rect區域 RectF rect = new RectF(F.x,F.y,F.x + F.Width,F.y + F.Height);//注意x,y乘以螢幕的密度

 文字rectF核心程式碼,movey + 1是為了減少高度誤差,即增加了rectF區域的高度.

 private RectF createRectF(int startX, int startY, int moveX, int moveY) {
        return new RectF(startX * mDensity, startY * mDensity, moveX * mDensity, (moveY + 1) * mDensity);
    }

 手指移動繪製就是根據選中的首尾兩個字元,進行迴圈遍歷繪製.(當前頁面的所有文字資訊遍歷)

 繪製相對來說,不是特別難的,難度最大的屬於劃線,還有合併劃線的功能,下面也給大家提供點實現思路.

 

難點

 

合併劃線功能,即判斷兩條線是否有交集等.這裡給大家個思路.

分三種情況:

1.劃線區域包括了選擇區域(這個場景可以直接不做任何操作,或者進行取消劃線的操作)

2.選擇區域包括劃線.

3.選擇區域和劃線有交集(前後交集)

 這個功能寫了一週,確實很麻煩,只能根據頁面提供的文字座標等資訊進行遍歷計算判斷.

 

 

總結

 

上面說了下這個閱讀器文字選擇和劃線的實現的思路,功能還需完善,還未上線,暫時也無法開源,大家有問題可以留言給我,我有看到,會及時回覆!

 其實這個功能不是特別的難,相信大家花點時間也都會做出來的!

 

 

 

 

 

 

相關文章