有時(shí)候項(xiàng)目中會(huì)有一些資訊列表圾旨,列表展現(xiàn)的是資訊圖片踱讨、標(biāo)題、簡(jiǎn)介砍的、或者各種其他點(diǎn)擊量這類(lèi)信息什么的啊痹筛,然后點(diǎn)擊列表中的文章或是圖片,然后進(jìn)入一個(gè)網(wǎng)頁(yè)廓鞠,就是展示具體的文章內(nèi)容了帚稠,當(dāng)然,這里網(wǎng)頁(yè)URL在列表數(shù)據(jù)中由服務(wù)器返回的床佳。
哈哈滋早,就想放張雙越的虐dog圖,(__) 嘻嘻……
《Android權(quán)威編程指南》這里用的是一個(gè)PhotoGallery項(xiàng)目來(lái)講解的網(wǎng)頁(yè)瀏覽砌们,我這里學(xué)習(xí)總結(jié)就不用那個(gè)例子了馆衔,麻煩了點(diǎn),就自己隨意弄個(gè)url地址怨绣,來(lái)壓縮例子重點(diǎn)知識(shí)吧角溃,主要分為兩種方式打開(kāi)網(wǎng)頁(yè):
隱式intent (隱式intent可啟動(dòng)瀏覽器,并在其中打開(kāi)圖片URL指向的網(wǎng)頁(yè))
核心代碼:
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(i);
使用WebView(使用隱式intent打開(kāi)網(wǎng)頁(yè)簡(jiǎn)單又高效篮撑,但是减细,不想打開(kāi)獨(dú)立的瀏覽器的時(shí)候,WebView就派上用場(chǎng)了赢笨,而且未蝌,在真正的項(xiàng)目中,要展現(xiàn)一篇文章的詳情茧妒,也不可能真的去打開(kāi)一個(gè)瀏覽器去展示吧萧吠,萬(wàn)一用戶手機(jī)就沒(méi)有瀏覽器這類(lèi)應(yīng)用軟件呢,所以桐筏,開(kāi)始來(lái)學(xué)習(xí)WebView吧纸型,WebView控件等于就是給我們開(kāi)發(fā)應(yīng)用軟件內(nèi)置了一個(gè)瀏覽器的感覺(jué),我這里弄個(gè)簡(jiǎn)單學(xué)習(xí)實(shí)例Demo梅忌,到了真正項(xiàng)目中就靈活運(yùn)用一下吧)
WebView要成功顯示一個(gè)網(wǎng)頁(yè)要做的事情:
- 首先——告訴WebView要打開(kāi)的URL
- 其次——啟用JavaScript狰腌。JavaScript默認(rèn)是禁用的。雖然并不總是需要啟用它牧氮,可是項(xiàng)目中有時(shí)候的HTML頁(yè)面有些互動(dòng)需要琼腔。(啟用JavaScript后,Android Lint會(huì)警告信息(擔(dān)心跨網(wǎng)站的腳本攻擊)踱葛,可以使用@SuppressLint("SetJavaScriptEnabled")注解onCreate(...)方法以禁止Lint的警告丹莲。)
- 最后——覆蓋WebViewClient類(lèi)的shouldOverrideUrlLoading(WebView, String)方法光坝,并返回false值。
Demo中弄了兩個(gè)按鈕甥材,一個(gè)按鈕就是使用隱式intent打開(kāi)網(wǎng)頁(yè)教馆,按鈕點(diǎn)擊時(shí)間中的核心代碼在如上,第二個(gè)按鈕把url傳入了下個(gè)頁(yè)面WebViewActivity.java擂达,使用的WebView打開(kāi)網(wǎng)頁(yè),布局文件中也就放入了一個(gè)WebView控件胶滋。
WebViewActivity .java
public class WebViewActivity extends AppCompatActivity {
private WebView mWebView;
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
mWebView = (WebView) findViewById(R.id.webview);
String uri = getIntent().getStringExtra("uri");
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return false;
}
});
mWebView.loadUrl(uri);
}
}
小結(jié):
- 加載URL必須等WebView配置完成后進(jìn)行
- 啟動(dòng)JavaScript——調(diào)用getSettings()方法獲得WebSettings實(shí)例板鬓,再調(diào)用WebSettings.setJavaScriptEnabled(true)方法
- WebSetting是修改WebView配置的三種途徑之一。另外其他一些可設(shè)置屬性究恤,如用戶代理字符串和顯示文字大小俭令。
- 配置WebViewClient。WebViewClient是一個(gè)事件接口部宿〕唬可自己實(shí)現(xiàn)WebViewClient來(lái)響應(yīng)各種渲染事件。例如理张,可檢測(cè)渲染器何時(shí)開(kāi)始從指定URL加載圖片赫蛇,或決定是否需要向服務(wù)器重新提交POST請(qǐng)求。WebViewClient很多方法可覆蓋雾叭,大多數(shù)用不到悟耘,必須要覆蓋shouldOverrideUrlLoading(WebView, String)默認(rèn)方法。當(dāng)有新的URL加載到WebView時(shí)织狐,譬如說(shuō)點(diǎn)擊某個(gè)鏈接暂幼,該方法會(huì)決定下一步行動(dòng),即對(duì)網(wǎng)頁(yè)中超鏈接按鈕的響應(yīng)移迫,如返回true旺嬉,表示W(wǎng)ebView不要處理URL,如返回false厨埋,表示叫WebView邪媳,去加載這個(gè)URL,默認(rèn)返回false荡陷。
使用WebChromeClient優(yōu)化WebView顯示
這里給布局添加一個(gè)進(jìn)度條控件
代碼中聲明進(jìn)度條悲酷,給進(jìn)度條設(shè)置mProgressBar.setMax(100);然后使用WebChromeClient,核心代碼:
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100){
mProgressBar.setVisibility(View.GONE);
}else {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setProgress(newProgress);
}
}
@Override
public void onReceivedTitle(WebView view, String title) {
Toast.makeText(WebViewActivity.this, title, Toast.LENGTH_LONG).show();
}
});
這樣進(jìn)入網(wǎng)頁(yè)時(shí)亲善,網(wǎng)頁(yè)加載時(shí)设易,會(huì)出現(xiàn)進(jìn)度條,onReceivedTitle本來(lái)是用于模擬顯示子標(biāo)題蛹头,Demo中就先打印出來(lái)看看title是什么顿肺,網(wǎng)頁(yè)加載完畢會(huì)打印title戏溺,同時(shí)進(jìn)度條消失。
小結(jié):
- WebChromeClient相當(dāng)于一個(gè)事件接口屠尊,用來(lái)響應(yīng)那些改變?yōu)g覽器中裝飾元素的事件旷祸,包括JavaScript警告信息、網(wǎng)頁(yè)圖標(biāo)讼昆、狀態(tài)條加載托享,已經(jīng)當(dāng)前網(wǎng)頁(yè)標(biāo)題的刷新。
- onProgressChanged(WebView, int)是進(jìn)度條更新的回調(diào)浸赫,onReceivedTitle(WebView, String)是標(biāo)題欄更新的回調(diào)闰围。
處理WebView的設(shè)備旋轉(zhuǎn)問(wèn)題
當(dāng)旋轉(zhuǎn)設(shè)備的時(shí)候,WebView會(huì)重新加載網(wǎng)頁(yè)既峡,由于WebView包含太多數(shù)據(jù)羡榴,無(wú)法在onSaveInstanceState(...)方法中全部保存,所以設(shè)備旋轉(zhuǎn)运敢,它必定從頭加載網(wǎng)頁(yè)數(shù)據(jù)校仑。WebView是視圖層級(jí)結(jié)構(gòu)的一部分,旋轉(zhuǎn)肯定會(huì)銷(xiāo)毀重建传惠,那用什么方法解決這個(gè)問(wèn)題呢迄沫?答案如下:
對(duì)于一些類(lèi)似的類(lèi)(如VideoView),Android文檔推薦讓activity自己處理設(shè)備配置變更卦方,即無(wú)法重建activity邢滑,就能直接調(diào)整自己的視圖以適應(yīng)新的屏幕尺寸。
在Demo的AndroidManifest.xml中添加如下代碼就解決問(wèn)題了
android:configChanges屬性表明愿汰,若因鍵盤(pán)開(kāi)關(guān)困后、屏幕方向改變、屏幕大小改變而發(fā)生配置改變衬廷,則activity應(yīng)自己處理配置更改摇予。
注意:
- 自己處理配置更改,資源修飾符無(wú)法自動(dòng)工作吗跋,開(kāi)發(fā)人員必須手工重載視圖侧戴。
- activity自己處理配置更改,依然需要覆蓋Activity.onSavedInstanceStare(...)方法存儲(chǔ)UI狀態(tài)跌宛,因?yàn)榧词棺约禾幚碓O(shè)備配置更改酗宋,低內(nèi)存情況下的生死還是需要考慮。
深入學(xué)習(xí):注入 JavaScript 對(duì)象
文檔網(wǎng)頁(yè):https://developer.android.com/reference/android/webkit/WebView.html
使用addJavaScriptInterface(Object, String)方法可注入任意JavaScript對(duì)象到指定文檔中疆拘。
自Jelly Bean 4.2(API 17) 開(kāi)始蜕猫,只有以@JavascriptInterface注解的公共方法才會(huì)暴露給JavaScript。在這之前哎迄,所有對(duì)象樹(shù)種的公共方法都是開(kāi)放訪問(wèn)的回右。安全起見(jiàn)隆圆,要么自己掌控局面,要么嚴(yán)格控制不要暴露自己的接口翔烁。
深入學(xué)習(xí):WebView 升級(jí)
KitKat 4.4(API 19)發(fā)布的WebView經(jīng)歷了一次大修渺氧,新WebView使用了和Android版Chrome一樣的渲染引擎。
WebView終于支持使用 Chrome DevTools進(jìn)行遠(yuǎn)程調(diào)試了(調(diào)用WebView. setWebContentsDebuggingEnabled()方法開(kāi)啟)
自Lollipop(Android 5.0)開(kāi)始蹬屹,WebView的Chromium層會(huì)自動(dòng)從Google Play商店更新侣背。
Nougat(Android 7.0),WebView的Chromium層又改為直接來(lái)自Chrome APK安裝包慨默。
挑戰(zhàn)練習(xí):使用后退鍵瀏覽歷史網(wǎng)頁(yè)
題目見(jiàn)書(shū)贩耐,突然也想起,我們項(xiàng)目中有個(gè)詳細(xì)文章的瀏覽业筏,可以從中直接進(jìn)入到另外一篇詳細(xì)文章,也是一個(gè)網(wǎng)頁(yè)鸟赫,然后回退直接回退到文章列表了蒜胖,而沒(méi)有回退到歷史網(wǎng)頁(yè),這里來(lái)解決一下這個(gè)問(wèn)題抛蚤,首先覆蓋onBackPressed()方法能監(jiān)控用戶是否按了回退建台谢,然后使用WebView.canGoBack()和WebView.goBack()方法來(lái)實(shí)現(xiàn)這一邏輯,代碼如下:
@Override
public void onBackPressed() {
if(wvArticle.canGoBack()){
wvArticle.goBack();
}else {
super.onBackPressed();
}
}
挑戰(zhàn)練習(xí):非HTTP鏈接支持
有時(shí)候傳入url岁经,萬(wàn)一不是HTTP鏈接朋沮,WebView就會(huì)顯示一段錯(cuò)誤文字,由于我們覆蓋了WebViewClient.shouldOverrideUrlLoading(...)方法返回false缀壤,這樣WebView總是會(huì)嘗試自己加載URL樊拓,所以為了代碼的健全性,在加載URI之前塘慕,先檢測(cè)它的scheme筋夏,若不是HTTP或者HTTPS,就根據(jù)需求做一些其他處理图呢。