《Android編程權(quán)威指南》之網(wǎng)頁(yè)瀏覽(WebView)篇

有時(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圖,(__) 嘻嘻……

圖片取自網(wǎng)絡(luò)

《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控件胶滋。


Demo截圖

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)度條控件

Demo截圖

代碼中聲明進(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)題了


Demo截圖

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ù)需求做一些其他處理图呢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末条篷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蛤织,更是在濱河造成了極大的恐慌赴叹,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件指蚜,死亡現(xiàn)場(chǎng)離奇詭異乞巧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)摊鸡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)摊欠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)丢烘,“玉大人,你說(shuō)我怎么就攤上這事些椒〔ネ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵免糕,是天一觀的道長(zhǎng)赢乓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)石窑,這世上最難降的妖魔是什么牌芋? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮松逊,結(jié)果婚禮上躺屁,老公的妹妹穿的比我還像新娘。我一直安慰自己经宏,他們只是感情好犀暑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著烁兰,像睡著了一般耐亏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沪斟,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天广辰,我揣著相機(jī)與錄音,去河邊找鬼主之。 笑死择吊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的槽奕。 我是一名探鬼主播干发,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼史翘!你這毒婦竟也來(lái)了枉长?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤琼讽,失蹤者是張志新(化名)和其女友劉穎必峰,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體钻蹬,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吼蚁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肝匆。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粒蜈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旗国,到底是詐尸還是另有隱情枯怖,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布能曾,位于F島的核電站度硝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寿冕。R本人自食惡果不足惜蕊程,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驼唱。 院中可真熱鬧藻茂,春花似錦、人聲如沸玫恳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纽窟。三九已至肖油,卻和暖如春兼吓,著一層夾襖步出監(jiān)牢的瞬間臂港,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工视搏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留审孽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓浑娜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拯欧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容