編輯:Android技術基礎
本節給大家帶來的是Android中的一個用於顯示網頁的控件:WebView(網頁視圖)。
現在Android應用 層開發的方向有兩種:客戶端開發和HTML5移動端開發!
所謂的HTML5端就是:HTML5 + CSS + JS來構建 一個網頁版的應用,而這中間的媒介就是這個WebView,而Web和網頁端可以通過JS來進行交互,比如, 網頁讀取手機聯系人,調用手機相關的API等!
而且相比起普通的客戶端開發,HTML5移動端有個優勢: 可以用百分比來布局,而且如果HTML5端有什麼大改,我們不用像客戶端那樣去重新下一個APP,然後 覆蓋安裝,我們只需修改下網頁即可!而客戶端...慘不忍睹,當然HTML5也有個缺點,就是性能的問題, 數據積累,耗電問題,還有閃屏等等...
另外,針對這種跨平台我們可以使用其他的第三方快速開發 框架,比如PhoneGap,對了,還有現在網絡上很多一鍵生成APP類的網站,用戶通過拖拉,設置圖片 之類的簡單操作就可以生成一個應用,大部分都是用的HTML5來完成的!有模板,直接套,你懂的~ 好的,話不多說,開始本節內容!
答:Android內置webkit內核的高性能浏覽器,而WebView則是在這個基礎上進行封裝後的一個 控件,WebView直譯網頁視圖,我們可以簡單的看作一個可以嵌套到界面上的一個浏覽器控件!
先上官方文檔:WebView 並不打算一個個地去講屬性,用到哪個寫哪個,其他的自行查閱文檔! 除了直接WebView外我們還可以添加你自己的行為,可以自行定制下述類:
WebChromeClient:輔助WebView處理Javascript的對話框、網站圖標、網站title、加載進度等! 比如下面這些:
WebViewClient:輔助WebView處理各種通知與請求事件! 比如下面這些方法:
WebSettings:WebView相關配置的設置,比如setJavaScriptEnabled()設置是否允許JS腳本執行 部分方法如下:
這裡重要區分三個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文檔
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試試~
我們都知道監聽滾動事件一般都是設置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(); } } } }
運行效果圖:
當網頁開始滾動,會呈現一個呵呵的按鈕,我們點擊呵呵按鈕可以回到頂部! 然後呵呵按鈕會隱藏~
你可能用的屬性如下:
- setHorizontalScrollBarEnabled(false);//水平不顯示
- setVerticalScrollBarEnabled(false); //垂直不顯示
- setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);//滾動條在WebView內側顯示
- setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY)//滾動條在WebView外側顯示
根據我們一般的習慣打開網頁對於看不清楚的地方,我們喜歡雙指來縮放網頁,而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%)。
我們都知道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); }
嘿嘿,我們上面獲取到了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()之前!
WebViewDemo1:下載 WebViewDemo1.zip
WebViewDemo2:下載 WebViewDemo2.zip
好的,本節給大家介紹了一下WebView的基本用法,加載網頁,設置縮放,字體縮放, 自適應屏幕,以及Cookie的獲取以及設置;相信日常開發中還有各種奇葩的需求,不過 限於篇幅就寫這麼多,有idea的歡迎留言,下節我們來學習HTML5端如何通過JavaScript 來與WebView交互,並獲取手機的相關數據!敬請期待~謝謝~
本章著重了解一下Handle、Message、Looper用法。一、設計界面 1、布局文件 打開res/layout/activity_main.xml文件。 輸入
本節引言:本節給帶來的是Android動畫中的第三種動畫——屬性動畫(Property Animation),記得在上一節8.4.2 Android
本節引言:本節帶來的是Android三種動畫中的第二種——補間動畫(Tween),和前面學的幀動畫不同,幀動畫是通過連續播放圖片來模擬動畫效果,而補
本節引言:第二章我們學習的是Android的UI控件,我們可以利用這些控件構成一個精美的界面,但是僅僅是界面而已;下一步就要開始學習邏輯與業務實現了