最近閒來無事一直在學習WebView的知識,最近幾篇部落格也都和這個有關。看了好久WebView的Api,終於找到了一個拿的出手給大家分享(水)的功能了。看標題,就知道是搜尋匹配當前網頁內的關鍵詞的功能啦,慣例先放下成品圖(UI參照了桌面版的Chrome):
效果和桌面版Chrome的頁內搜尋也是差不多的。下面就介紹下相關相關Api和具體實現流程吧。
Api
void findAllAsync(String find)
找到網頁內所有關鍵詞,看方法名字知道是非同步查詢的。所有找到的匹配項都會用顏色標記(上圖是黃色)。
void findNext(boolean forward)
切換所找到關鍵詞列表的匹配項。forward是切換方向,true切換到下一個,false切換到前一個。當前選中的匹配項會用另外一個顏色標記(橙色)。注意切換的操作是迴圈的,比如已經在最後一項了,再往前切換就會回到第一個匹配項。
void setFindListener(FindListener listener)
設定介面監聽器,回撥查詢的結果,其中FindListener
就一個方法:
public void onFindResultReceived(int activeMatchOrdinal//當前匹配列表項的序號(從0開始)
,int numberOfMatches//所有匹配關鍵詞的個數
,boolean isDoneCounting);//有沒有查詢完成
複製程式碼
void clearMatches()
清除所有找到的關鍵詞的顏色標記。用來做復原操作。
以下是一些過時(廢棄)的方法:
boolean showFindDialog(String text, boolean showIme)
找到關鍵詞,並顯示彈框。原來WebView有內建的查詢文字的彈框,可惜在所有android版本的系統上這個方法都不一定有用。
int findAll(String find)
findAllAsync的同步版本,返回的是查詢的結果的個數。猜測如果網頁內文字太多,同步查詢可能引起UI執行緒阻塞,所以系統建議我們採用非同步的查詢方式。
好了主要方法就是以上這些,下面講下具體的實現流程。
實現流程
整個查詢的流程(包括顯示細節)都仿照了了Chrome的查詢方式。
彈框最初我選擇了DialogFrgment,但是dialog會阻塞Webview獲取焦點。因為我們預期的結果是查詢到所有匹配項後仍能夠自己滑動WebView
檢視。所有隻能直接寫在WebView的佈局裡面。為了優化佈局載入速度,可以採用如下引用方式:
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/search_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
複製程式碼
這樣就能實現佈局的延遲載入。當然最好的方法還是選擇dialog或者poupwindow。可惜沒有解決焦點的問題。 註冊查詢回撥的介面,注意下標索引是從0開始的,所以要加1:
mWebView.setFindListener(new IX5WebViewBase.FindListener() {
@Override
public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
boolean isDoneCounting) {
if (isDoneCounting) {
if (numberOfMatches != 0) {
searchInfo.setText(String.format("%d/%d", (activeMatchOrdinal + 1), numberOfMatches));
} else {
searchInfo.setText("0/0");
}
}
}
});
複製程式碼
通過監聽輸入框的內容變化進行動態的文字查詢。
mEditText.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (TextUtils.isEmpty(mEditText.getText().toString())) {
searchInfo.setVisibility(View.INVISIBLE);
} else {
searchInfo.setVisibility(View.VISIBLE);
}
String content = s.toString();
if (!TextUtils.isEmpty(content)) {
mWebView.findAllAsync(content);
}
}
});
複製程式碼
在彈框查詢框同時要彈出輸入框。並且需要判斷有沒有存在內容,有的話直接查詢,但是這只是為了顯示找到匹配項的個數,所以清除顏色標記。
String content=mEditText.getText().toString();
if (TextUtils.isEmpty(content)) {
searchInfo.setVisibility(View.INVISIBLE);
} else {
mWebView.findAllAsync(content);
mWebView.clearMatches();
searchInfo.setVisibility(View.VISIBLE);
}
KeyboardUtils.showSoftInput(getContext(), mEditText);
複製程式碼
在隱藏查詢框的時候隱藏輸入框和清楚匹配項的顏色標記:
searchLayout.setVisibility(View.GONE);
KeyboardUtils.hideSoftInput(getActivity(), mEditText);
mWebView.clearMatches();
複製程式碼
查詢框的進入消失動畫可以用Transition
實現
TransitionManager.beginDelayedTransition(mViewGroup, new Slide(Gravity.TOP));
以上差不多就是所有的實現要點了。
小結
貼下本文程式碼的地址
關於WebView之前已經寫過幾篇部落格了。對這方面感興趣的同學可以看下我的其他相關部落格(Github地址同上):