最近閑來(lái)無(wú)事一直在學(xué)習(xí)WebView的知識(shí)丁鹉,最近幾篇博客也都和這個(gè)有關(guān)喂江≌傩猓看了好久WebView的Api,終于找到了一個(gè)拿的出手給大家分享(水)的功能了获询≌撬辏看標(biāo)題,就知道是搜索匹配當(dāng)前網(wǎng)頁(yè)內(nèi)的關(guān)鍵詞的功能啦吉嚣,慣例先放下成品圖(UI參照了桌面版的Chrome):
效果和桌面版Chrome的頁(yè)內(nèi)搜索也是差不多的梢薪。下面就介紹下相關(guān)相關(guān)Api和具體實(shí)現(xiàn)流程吧。
Api
void findAllAsync(String find)
找到網(wǎng)頁(yè)內(nèi)所有關(guān)鍵詞尝哆,看方法名字知道是異步查找的秉撇。所有找到的匹配項(xiàng)都會(huì)用顏色標(biāo)記(上圖是黃色)。
void findNext(boolean forward)
切換所找到關(guān)鍵詞列表的匹配項(xiàng)秋泄。forward是切換方向琐馆,true切換到下一個(gè),false切換到前一個(gè)恒序。當(dāng)前選中的匹配項(xiàng)會(huì)用另外一個(gè)顏色標(biāo)記(橙色)瘦麸。注意切換的操作是循環(huán)的,比如已經(jīng)在最后一項(xiàng)了奸焙,再往前切換就會(huì)回到第一個(gè)匹配項(xiàng)瞎暑。
void setFindListener(FindListener listener)
設(shè)置接口監(jiān)聽器,回調(diào)查找的結(jié)果与帆,其中FindListener
就一個(gè)方法:
public void onFindResultReceived(int activeMatchOrdinal//當(dāng)前匹配列表項(xiàng)的序號(hào)(從0開始)
,int numberOfMatches//所有匹配關(guān)鍵詞的個(gè)數(shù)
,boolean isDoneCounting);//有沒有查找完成
void clearMatches()
清除所有找到的關(guān)鍵詞的顏色標(biāo)記了赌。用來(lái)做復(fù)原操作。
以下是一些過時(shí)(廢棄)的方法:
boolean showFindDialog(String text, boolean showIme)
找到關(guān)鍵詞玄糟,并顯示彈框勿她。原來(lái)WebView有內(nèi)置的查找文字的彈框,可惜在所有android版本的系統(tǒng)上這個(gè)方法都不一定有用阵翎。
int findAll(String find)
findAllAsync的同步版本逢并,返回的是查找的結(jié)果的個(gè)數(shù)。猜測(cè)如果網(wǎng)頁(yè)內(nèi)文字太多郭卫,同步查找可能引起UI線程阻塞砍聊,所以系統(tǒng)建議我們采用異步的查找方式。
好了主要方法就是以上這些贰军,下面講下具體的實(shí)現(xiàn)流程玻蝌。
實(shí)現(xiàn)流程
整個(gè)查找的流程(包括顯示細(xì)節(jié))都仿照了了Chrome的查找方式。
彈框最初我選擇了DialogFrgment,但是dialog會(huì)阻塞Webview獲取焦點(diǎn)俯树。因?yàn)槲覀冾A(yù)期的結(jié)果是查找到所有匹配項(xiàng)后仍能夠自己滑動(dòng)WebView
查看帘腹。所有只能直接寫在WebView的布局里面。為了優(yōu)化布局加載速度许饿,可以采用如下引用方式:
<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"
/>
這樣就能實(shí)現(xiàn)布局的延遲加載阳欲。當(dāng)然最好的方法還是選擇dialog或者poupwindow÷剩可惜沒有解決焦點(diǎn)的問題球化。
注冊(cè)查找回調(diào)的接口,注意下標(biāo)索引是從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");
}
}
}
});
通過監(jiān)聽輸入框的內(nèi)容變化進(jìn)行動(dòng)態(tài)的文字查找赊窥。
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);
}
}
});
在彈框查找框同時(shí)要彈出輸入框。并且需要判斷有沒有存在內(nèi)容狸页,有的話直接查找,但是這只是為了顯示找到匹配項(xiàng)的個(gè)數(shù)扯再,所以清除顏色標(biāo)記芍耘。
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);
在隱藏查找框的時(shí)候隱藏輸入框和清楚匹配項(xiàng)的顏色標(biāo)記:
searchLayout.setVisibility(View.GONE);
KeyboardUtils.hideSoftInput(getActivity(), mEditText);
mWebView.clearMatches();
查找框的進(jìn)入消失動(dòng)畫可以用Transition
實(shí)現(xiàn)
TransitionManager.beginDelayedTransition(mViewGroup, new Slide(Gravity.TOP));
以上差不多就是所有的實(shí)現(xiàn)要點(diǎn)了。
小結(jié)
貼下本文代碼的地址
關(guān)于WebView之前已經(jīng)寫過幾篇博客了熄阻。對(duì)這方面感興趣的同學(xué)可以看下我的其他相關(guān)博客(Github地址同上):