Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android技術基礎 >> 7.5.1 WebView(網頁視圖)基本用法

7.5.1 WebView(網頁視圖)基本用法

編輯:Android技術基礎

本節引言

本節給大家帶來的是Android中的一個用於顯示網頁的控件:WebView(網頁視圖)。

現在Android應用 層開發的方向有兩種:客戶端開發和HTML5移動端開發!

所謂的HTML5端就是:HTML5 + CSS + JS來構建 一個網頁版的應用,而這中間的媒介就是這個WebView,而Web和網頁端可以通過JS來進行交互,比如, 網頁讀取手機聯系人,調用手機相關的API等!

而且相比起普通的客戶端開發,HTML5移動端有個優勢: 可以用百分比來布局,而且如果HTML5端有什麼大改,我們不用像客戶端那樣去重新下一個APP,然後 覆蓋安裝,我們只需修改下網頁即可!而客戶端...慘不忍睹,當然HTML5也有個缺點,就是性能的問題, 數據積累,耗電問題,還有閃屏等等...

另外,針對這種跨平台我們可以使用其他的第三方快速開發 框架,比如PhoneGap,對了,還有現在網絡上很多一鍵生成APP類的網站,用戶通過拖拉,設置圖片 之類的簡單操作就可以生成一個應用,大部分都是用的HTML5來完成的!有模板,直接套,你懂的~ 好的,話不多說,開始本節內容!

1.什麼是WebView?

答:Android內置webkit內核的高性能浏覽器,而WebView則是在這個基礎上進行封裝後的一個 控件,WebView直譯網頁視圖,我們可以簡單的看作一個可以嵌套到界面上的一個浏覽器控件!

2.相關方法

先上官方文檔:WebView 並不打算一個個地去講屬性,用到哪個寫哪個,其他的自行查閱文檔! 除了直接WebView外我們還可以添加你自己的行為,可以自行定制下述類:


WebChromeClient:輔助WebView處理Javascript的對話框、網站圖標、網站title、加載進度等! 比如下面這些:

方法 作用 onJsAlert(WebView view,String url,String message,JsResult result) 處理Js中的Alert對話框 onJsConfirm(WebView view,String url,String message,JsResult result) 處理Js中的Confirm對話框 onJsPrompt(WebView view,String url,String message,String defaultValue,JsPromptResult result) 處理Js中的Prompt對話框 onProgressChanged(WebView view,int newProgress) 當加載進度條發生改變時調用 onReceivedIcon(WebView view, Bitmap icon) 獲得網頁的icon onReceivedTitle(WebView view, String title) 獲得網頁的標題

WebViewClient:輔助WebView處理各種通知與請求事件! 比如下面這些方法:

方法 作用 onPageStared(WebView view,String url) 通知主程序網頁開始加載 onPageFinished(WebView view,String url,Bitmap favicon) 通知主程序,網頁加載完畢 doUpdateVisitedHistory(WebView view,String url,boolean isReload) 更新歷史記錄 onLoadResource(WebView view,String url) 通知主程序WebView即將加載指定url的資源 onScaleChanged(WebView view,float oldScale,float newScale) ViewView的縮放發生改變時調用 shouldOverrideKeyEvent(WebView view,KeyEvent event) 控制webView是否處理按鍵時間,如果返回true,則WebView不處理,返回false則處理 shouldOverrideUrlLoading(WebView view,String url) 控制對新加載的Url的處理,返回true,說明主程序處理WebView不做處理,返回false意味著WebView會對其進行處理 onReceivedError(WebView view,int errorCode,String description,String failingUrl) 遇到不可恢復的錯誤信息時調用

WebSettings:WebView相關配置的設置,比如setJavaScriptEnabled()設置是否允許JS腳本執行 部分方法如下:

方法 作用 getSettings() 返回一個WebSettings對象,用來控制WebView的屬性設置 loadUrl(String url) 加載指定的Url loadData(String data,String mimeType,String encoding) 加載指定的Data到WebView中.使用"data:"作為標記頭,該方法不能加載網絡數據.其中mimeType為數據類型如:textml,image/jpeg. encoding為字符的編碼方式 loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) 比上面的loadData更加強大 setWebViewClient(WebViewClient client) 為WebView指定一個WebViewClient對象.WebViewClient可以輔助WebView處理各種通知,請求等事件。 setWebChromeClient(WebChromeClient client) 為WebView指定一個WebChromeClient對象,WebChromeClient專門用來輔助WebView處理js的對話框,網站title,網站圖標,加載進度條等

這裡重要區分三個load方法的區別:

loadUrl():直接顯示網頁內容(單獨顯示網絡圖片),一般不會出現亂碼。 loadData(data, "text/html", "UTF-8"):用來加載URI格式的數據,不能通過網絡來加載內容, 不能加載圖片,而且經常會遇到亂碼的問題,我們知道String類型的數據主要是Unicode編碼的, 而WebView一般為了節省資源使用的是UTF-8編碼,盡管我們按上面寫了,但是還需要為webView設置: webview.getSettings().setDefaultTextEncodingName("UTF -8"); loadDataWithBaseURL(baseUrl, string, "text/html", "utf-8", null):loadData類的一個 增強類,可以加載圖片,baseUrl為你存儲的圖片路徑,而且只需在這裡設置utf-8就可以解決亂碼 問題了!

這裡只是列舉了部分屬性而已,其他的還需自行查閱官方文檔:

WebChromeClient文檔

WebViewClient文檔

WebSettings文檔


3.一些常見需求講解

需求1:根據URL加載網頁

1)直接在Activity上加載一個WebView

運行效果圖

實現代碼

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private long exitTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = new WebView(this);
        webView.setWebViewClient(new WebViewClient() {
            //設置在webView點擊打開的新網頁在當前界面顯示,而不跳轉到新的浏覽器中
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
        webView.getSettings().setJavaScriptEnabled(true);  //設置WebView屬性,運行執行js腳本
        webView.loadUrl("http://www.baidu.com/");          //調用loadUrl方法為WebView加入鏈接
        setContentView(webView);                           //調用Activity提供的setContentView將webView顯示出來
    }


    //我們需要重寫回退按鈕的時間,當用戶點擊回退按鈕:
    //1.webView.canGoBack()判斷網頁是否能後退,可以則goback()
    //2.如果不可以連續點擊兩次退出App,否則彈出提示Toast
    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(getApplicationContext(), "再按一次退出程序",
                        Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                super.onBackPressed();
            }

        }
    }
}

2)布局代碼中設置WebView

相信大家都見過很多的新聞類App吧或者門戶信息類的App,他的結構可能是這樣的:

左上角一個點擊關閉當前Activity的按鈕,中間是新聞的title,右面是一個刷新按鈕, 而在右下角可能有這樣一個懸浮的按鈕,當我們滑動超過屏幕寬度他就會顯示出來, 當用戶點擊後又會回滾到網頁的頂部!下面我們來簡單的實現下!

運行效果圖

實現代碼

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    private Button btn_back;
    private TextView txt_title;
    private Button btn_top;
    private Button btn_refresh;
    private WebView wView;
    private long exitTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
    }


    private void bindViews() {
        btn_back = (Button) findViewById(R.id.btn_back);
        txt_title = (TextView) findViewById(R.id.txt_title);
        btn_top = (Button) findViewById(R.id.btn_top);
        btn_refresh = (Button) findViewById(R.id.btn_refresh);
        wView = (WebView) findViewById(R.id.wView);

        btn_back.setOnClickListener(this);
        btn_refresh.setOnClickListener(this);
        btn_top.setOnClickListener(this);

        wView.loadUrl("http://www.baidu.com");
        wView.setWebChromeClient(new WebChromeClient() {
            //這裡設置獲取到的網站title
            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
                txt_title.setText(title);
            }
        });


        wView.setWebViewClient(new WebViewClient() {
            //在webview裡打開新鏈接
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_back:
                finish();          //關閉當前Activity
                break;
            case R.id.btn_refresh:
                wView.reload();    //刷新當前頁面
                break;
            case R.id.btn_top:
                wView.setScrollY(0);   //滾動到頂部
                break;
        }
    }
    
    @Override
    public void onBackPressed() {
        if (wView.canGoBack()) {
            wView.goBack();
        } else {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(getApplicationContext(), "再按一次退出程序",
                        Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                finish();
            }

        }
    }
}

問題答疑

相信細心的朋友看到,我們回到一開始加載的頁面後,按返回鍵,按了多次還是沒有退出 當前的APP,後來還是我們手動去點back鍵通過調用finish方法才能關閉當前的Activity? 這是為什麼呢?明明百度一下已經是第一個頁面啊?

答:其實發生這個的原因是:網址的重定向問題引起的,其實我們在訪問百度的時候:

盡管我們load的是www.baidu.com,但是百度做了重定向,跳轉到了手機版百度一下網頁: 即實際你的流程是:www.baidu.com -> 手機版百度一下 -> 打開其他的鏈接!

我們看到我們上面shouldOverrideUrlLoading()方法是這樣寫的:

view.loadUrl(url);return true; 我們知道用戶點擊一次回退鍵,那麼webview會調用一次goback方法(),我們把上面三個 設做A,B,C三個站點,在C時點回退,C - > B沒問題,接著再點 B -> A,這個時候問題 就來了盡管B來到了A,但是因為重定向又跳轉到了B,如此循環往復...這就是為什麼 點擊回退鍵並沒有推出WebView的原因,解決方法:手速,在webview未加載完網頁 錢連續雙擊回退鍵,手速要夠快,哈哈!說笑而已,要解決這個問題,我們只需將 shouldOverrideUrlLoading裡的東東刪掉,然後寫上return false;即可! 不信是重定向,可以自己修改下URL試試~


需求2:WebView滾動事件的監聽

我們都知道監聽滾動事件一般都是設置setOnScrollChangedListener,可惜的是 WebView並沒有給我們提供這樣的方法,但是我們可以重寫WebView,覆蓋裡面的一個方法: protected void onScrollChanged(final int l, final int t, final int oldl,final int oldt){} 然後再對外提供一個接口,示例代碼如下:

MyWebViewDemo.java

/**
 * Created by Jay on 2015/9/11 0011.
 */
public class MyWebView extends WebView {

    private OnScrollChangedCallback mOnScrollChangedCallback;

    public MyWebView(Context context) {
        super(context);
    }

    public MyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollChangedCallback != null) {
            mOnScrollChangedCallback.onScroll(l - oldl, t - oldt);
        }
    }

    public OnScrollChangedCallback getOnScrollChangedCallback() {
        return mOnScrollChangedCallback;
    }

    public void setOnScrollChangedCallback(
            final OnScrollChangedCallback onScrollChangedCallback) {
        mOnScrollChangedCallback = onScrollChangedCallback;
    }

    public static interface OnScrollChangedCallback {
        //這裡的dx和dy代表的是x軸和y軸上的偏移量,你也可以自己把l, t, oldl, oldt四個參數暴露出來
        public void onScroll(int dx, int dy);
    }

}

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private MyWebView wView;
    private Button btn_icon;
    private long exitTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_icon = (Button) findViewById(R.id.btn_icon);
        wView = (MyWebView) findViewById(R.id.wView);
        wView.loadUrl("http://www.hao123.com");
        wView.setWebViewClient(new WebViewClient() {
            //在webview裡打開新鏈接
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });

        //比如這裡做一個簡單的判斷,當頁面發生滾動,顯示那個Button
        wView.setOnScrollChangedCallback(new MyWebView.OnScrollChangedCallback() {
            @Override
            public void onScroll(int dx, int dy) {
                if (dy > 0) {
                    btn_icon.setVisibility(View.VISIBLE);
                } else {
                    btn_icon.setVisibility(View.GONE);
                }
            }
        });

        btn_icon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                wView.setScrollY(0);
                btn_icon.setVisibility(View.GONE);
            }
        });

    }

    @Override
    public void onBackPressed() {
        if (wView.canGoBack()) {
            wView.goBack();
        } else {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(getApplicationContext(), "再按一次退出程序",
                        Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                finish();
            }

        }
    }
}

運行效果圖

當網頁開始滾動,會呈現一個呵呵的按鈕,我們點擊呵呵按鈕可以回到頂部! 然後呵呵按鈕會隱藏~


需求3:滾動條的問題

你可能用的屬性如下:

  • setHorizontalScrollBarEnabled(false);//水平不顯示
  • setVerticalScrollBarEnabled(false); //垂直不顯示
  • setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);//滾動條在WebView內側顯示
  • setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY)//滾動條在WebView外側顯示

需求4:設置縮放以及自適應屏幕

根據我們一般的習慣打開網頁對於看不清楚的地方,我們喜歡雙指來縮放網頁,而WebView 則需要我們自己手動來設置這個是否支持縮放了!

只需要在加入下述代碼即可:

WebSettings settings = wView.getSettings();
settings.setUseWideViewPort(true);//設定支持viewport
settings.setLoadWithOverviewMode(true);   //自適應屏幕
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setSupportZoom(true);//設定支持縮放

使用上述代碼後,進去頁面就會是這樣一個效果:

當我們縮放時,出現了一個惡心的問題,就是很常見的縮放控件,我們肯定是不想要的啦, 那麼加上下面句代碼就可以把縮放控件給隱藏掉了!

settings.setDisplayZoomControls(false);

我們也可以自行設置初始的縮放比例,只需為webView:

wView.setInitialScale(25);//為25%,最小縮放等級

嘿嘿,上面是整個網頁都縮放的,不過可能有時我們僅僅是需要對字體進行縮放,那麼可以 這樣做:

settings.setTextZoom(int);

也可以直接通過:

settings.setTextSize(TextSize.LARGER);

來設置大小。

Android自帶五個可選字體大小的值:SMALLEST(50%),SMALLER(75%),NORMAL(100%),LARGER(150%), LARGEST(200%)。


需求5.獲取WebView的Cookie數據

我們都知道Cookie其實只是一個代表用戶唯一標識的字符串,情景一般是: 用戶輸入賬號密碼後,點擊登陸,用戶要拿著這個Cookie去訪問服務器提供的相關服務! 我們可以把cookie的獲取寫到onPageFinsihed的方法中,簡單的可以這樣寫:

@Override
public void onPageFinished(WebView view, String url) {             
    CookieManager cookieManager = CookieManager.getInstance();
    String CookieStr = cookieManager.getCookie(url);
    Log.e("HEHE", "Cookies = " + CookieStr);
    super.onPageFinished(view, url);
}

需求6.設置WebView的Cookie數據

嘿嘿,我們上面獲取到了Cookie或者通過其他途徑獲得了Cookie,我們如何為WebView設置Cookie呢? 我們可以在需要設置Cookie的地方加入下述代碼:

CookieSyncManager.createInstance(MainActivity.this);  
CookieManager cookieManager = CookieManager.getInstance();  
cookieManager.setAcceptCookie(true);  
cookieManager.setCookie(url, cookies);  //cookies是要設置的cookie字符串 
CookieSyncManager.getInstance().sync();

對了,上述代碼需要寫在loadUrl()之前,而且如果設置了Cookie了,盡量別再進行其他的設置 不然可能會無效,建議設置cookie的寫在webView相關設置的最後面~loadUrl()之前!


4.示例代碼下載:

WebViewDemo1:下載 WebViewDemo1.zip

WebViewDemo2:下載 WebViewDemo2.zip


本節小結:

好的,本節給大家介紹了一下WebView的基本用法,加載網頁,設置縮放,字體縮放, 自適應屏幕,以及Cookie的獲取以及設置;相信日常開發中還有各種奇葩的需求,不過 限於篇幅就寫這麼多,有idea的歡迎留言,下節我們來學習HTML5端如何通過JavaScript 來與WebView交互,並獲取手機的相關數據!敬請期待~謝謝~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved