實現縮略圖卷軸后荆烈,一下子就爆發(fā)出很多的可能性拯勉。這些方向主要有:縮略圖網格、頁面跳轉的歷史記錄憔购、全文搜索宫峦、以及書簽。
一倦始、縮略圖網格
mViewPager.setLayoutManager(new GridLayoutManager(a, 6));
這樣就完成6列網格的顯示了斗遏。GridLayoutManager 擴展自 LinearLayoutManager,所以不會出問題鞋邑,但具體還需調整。
二、實現PDF全文搜索
2.1 搜索界面
通過改寫recyclerview的適配器铸本,顯示全部頁面的子集肮雨,作為搜索結果的基本展示。
底部數據就一個 Arraylist箱玷,存放具體頁面的索引怨规。所以也可以使用SparseIntArray。
實現 ResultsProvider 接口將底部數據隱藏起來锡足。
運用廣度優(yōu)先的搜索策略波丰,即優(yōu)先搜索哪些頁面有匹配,而不是全部匹配的具體位置舶得。
2.2 PDF 全文搜索
API : FPDFText_FindStart掰烟、FPDFText_FindNext。暫時這兩個就夠沐批,一頁頁地調用兩個API各一次進行搜索纫骑。
需要用 FPDF_LoadPage、FPDFText_LoadPage分別加載每一頁及其文本對象九孩。測試發(fā)現先馆,七百多頁的內存中的Gpu pro 1,加載全部頁面耗時2.7秒躺彬,加載全部頁面的文本對象耗時4.4-2.7秒煤墙。對每一頁面發(fā)起并關閉一次搜索的時間可忽略不計缤底。
也就是說什么搜沒開始搜索,就有一個4.4秒左右的基本耗時番捂。
JNI_FUNC(void, PdfiumCore, nativeFindAll)(JNI_ARGS, jlong docPtr, jint pages) {
DocumentFile* docFile = (DocumentFile*)docPtr;
// 測試搜索功能个唧。
const unsigned short nope[] = { 'n', 'o', 'p', 'e', '\0' }; // 模仿測試文件 fpdftext_embeddertest.cpp
FPDF_DOCUMENT pdfDoc = docFile->pdfDocument;
if(pdfDoc){
for(int i=0;i<pages;i++) { // 對每一頁面
FPDF_PAGE page = FPDF_LoadPage(pdfDoc, i); //加載頁面
if(page) {
FPDF_TEXTPAGE text = FPDFText_LoadPage(page); //加載文本
if(text) {
// 發(fā)起搜索
FPDF_SCHHANDLE findHandle = FPDFText_FindStart(text, nope, 0, 0);
// 關閉搜索
FPDFText_FindClose(findHandle);
FPDFText_ClosePage(text); //卸載文本
}
FPDF_ClosePage(page); //卸載頁面
}
}
}
}
進一步測試,在發(fā)起搜索和關閉搜索之間正式搜索一次设预。耗時4.5秒徙歼,還是很快的。
FPDFText_FindNext(findHandle); // 正式搜索
這樣一來就可以放心使用API了鳖枕。接下來將有匹配的頁面置入ArrayList里面魄梯,最后傳給上面說的縮略圖頁面子集適配器就可以了!
附從jstring獲取可以傳給FPDFText_FindStart的keyStr:
const unsigned short * keyStr = env->GetStringChars(key, 0);
如果選擇緩存全部頁面對象而不關閉宾符,那么第二次搜索將快很多(200到300毫秒)酿秸;但是會占用內存空間,七百多頁共占0.2GB左右魏烫。
事實也證明頁面及其文本對象的加載是主要耗時過程辣苏。相比之下,jni調用哄褒、jstring轉換等的消耗不值一提稀蟋。
2.3 繪制高亮
又是與繪制選區(qū)差不多唄。拿到基本的搜索結果后呐赡,渲染時進一步循環(huán)調用 FPDFText_FindNext 搜索直到這一頁返回false退客。循環(huán)之內,用FPDFText_GetSchResultIndex链嘀、FPDFText_GetSchCount獲取一頁內所有匹配的字符索引萌狂。然后和之前一樣用FPDFText_CountRects 和 FPDFText_GetRect獲得一些需要繪制的矩形。
這個功能是 JNI 調用最為密集的怀泊,因此簡單測試了一下 JNI 調用的效率茫藏,發(fā)現在native層調用java方法要比正向調用慢一些,不知是否是測試方法的問題包个。
然后是繪制方面刷允,之前說若將選區(qū)方框繪制在后面需要分好幾層,很麻煩碧囊。實際則簡單得多树灶,只需用paint.setXfermode(PorterDuff.Mode.DARKEN)
就可以達成類似的效果,神奇糯而。
結果如圖所示天通,使用YPWaveView(動態(tài)波浪視圖)指示搜索進度,效果相當不錯熄驼。
……