谈谈WebView的使用-(从零开始搭建android框架系列(5))

转载地址:http://blog.csdn.net/u014315849/article/details/51385266




本篇文章项目github地址:MVPCommon 
本文章原地址:简书博客 
项目效果

1 前言

这篇文章将从webview的基础,介绍到项目中的真实使用。以及怎么样通过注入js脚本的方式来改变网页内容,从而在本地展示新闻体育列表。制作出一个像模像样的app。 
严正声明,网页数据来自 虎扑体育,仅作学习用途,请勿在任何商业用途中使用。

2 webview基础

WebView是手机中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装的一个组件。没有提供地址栏和导航栏,WebView只是单纯的展示一个网页界面。在开发中经常都会用到。

2.1 添加webview到应用中

直接将webview添加到layout文件中

<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"    
android:id="@+id/webview"   
 android:layout_width="fill_parent"    
android:layout_height="fill_parent"/>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

使用webview加载url使用loadUrl方法:

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");
   
   
  • 1
  • 2
  • 1
  • 2

AndroidManifest.xml 中必须添加访问网络权限。

<manifest ... >   
 <uses-permission android:name="android.permission.INTERNET" />  
  ...
</manifest>
   
   
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

 #####2.2 支持JavaScript 
如果访问的页面中有 Javascript,则 WebView 初始化的时候必须设置支持 Javascript。(WebSetting中提供了很多有用的api, 点击链接查看)

WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
   
   
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

通过创建JavaScript的接口可以让JavaScript和安卓客户端进行交互。比如说JavaScript可以调用本地的安卓代码展示一个Dialog而不是使用JavaScript的alter()方法。通过addJavascriptInterface()方法创建接口。 
示例: 
定义一个“接口”类

public class WebAppInterface {
    Context mContext;

    /** Instantiate the interface and set the context */
    WebAppInterface(Context c) {
        mContext = c;
    }

    /** Show a toast from the web page */
    @JavascriptInterface
    public void showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在addJavascriptInterface方法中创建接口

WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
   
   
  • 1
  • 2
  • 1
  • 2

在HTML的JavaScript中调用WebView显示toast消息,

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意: 
1 addJavascriptInterface方法中要绑定的Java对象及方法运行在另外的线程中,而不是运行在构造他的线程中。 
2 使用addJavascriptInterface将会使javaScript可以操控安卓本地代码。因此有可能导致安全性问题,请确保所有HTML代码都是你所知道的。 
3 如果targetSdkVersion是17或者更高(Android 4.2以上),必须使用 @JavascriptInterface 注解,才能让网页访问到本地代码。

2.3 webview页面处理

当用户点击webview中的网页链接的时候,安卓系统默认会启动一个新的应用专门成立url的跳转。如果希望点击链接继续在当前webview中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 WebView的WebViewClient对象. 并重写shouldOverrideUrlLoading方法。 
“` 
WebView myWebView = (WebView) findViewById(R.id.webview); 
myWebView.setWebViewClient.(new WebViewClient(); 
private class MyWebViewClient extends WebViewClient { 
@Override 
public boolean shouldOverrideUrlLoading(WebView view, String url) { 
if (Uri.parse(url).getHost().equals(“www.example.com”)) { 
// This is my web site, so do not override; let my WebView load the page 
return false; 

// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs 
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 
startActivity(intent); 
return true; 

}


#####2.4 webview的页面导航处理 
当webview的url进行跳转的时候,自动回记录进入历史界面,可以使用goBack()方法和goForward()方法,进行返回和前进。
webview的canGoBack方法将会判断历史记录中是否还有页面,如果还有上一级页面,将会返回true
   
   
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

@Override 
public boolean onKeyDown(int keyCode, KeyEvent event) { 
// Check if the key event was the Back button and if there’s history 
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { 
myWebView.goBack(); 
return true; 

// If it wasn’t the Back key or there’s no web page history, bubble up to the default 
// system behavior (probably exit the activity) 
return super.onKeyDown(keyCode, event); 
}


###3 webview在项目中使用
上面介绍了WebView的基础知识,内容是我对[Building Web Apps in WebView(官网)](http://developer.android.com/guide/webapps/webview.html)
的大致翻译内容。如果还需要了解更多,推荐4 参考链接中的深入讲解Webview(上,下)。
这里接着介绍WebView在我项目中的使用。
#####3.1 需求是什么?
当然在我项目中,最开始想做的一个体育新闻资讯,但是苦于自己没有服务器,所以一开始都是模拟的数据。网上的开源api也是将所有新闻数据糅合在一起的,怎么分开呢?比如nba,英超,欧冠,各种不同的新闻数据在哪里获取呢?作为一个体育爱好者,经常会去的虎扑体育,然后找到了手机版的 [虎扑体育](http://www.jianshu.com/m.hupu.com)。这不就是我想要的体育新闻数据嘛,O(∩_∩)O哈哈~。
但是我不想要这个头部和底部呢 ,接下来分析怎么处理,很简单的实现。
![](http://upload-images.jianshu.io/upload_images/1833901-6509df5ac9cb479b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://upload-images.jianshu.io/upload_images/1833901-baae3d25c3979653.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#####3.2 效果怎么样?
看看运行效果,还是有模有样的
![](http://upload-images.jianshu.io/upload_images/1833901-7067542d7d9e7d5a.gif?imageMogr2/auto-orient/strip)

#####3.3 怎么做?
主要就是进行了新闻网页的展示,并且去掉了头部和底部。
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

public class WebViewFragment extends AbsTitleFragment { 
……

    R.layout.fragment_web_view;

……

@Override
protected void initViewsAndEvents(View rootView) {
    mWebView.setVisibility(View.INVISIBLE);
    toggleShowLoading(true, "loading");

    setWebViewOption(mWebView);
    if (getFragmentUrl() != null) {
        mWebView.loadUrl(getFragmentUrl());
    }
}

private void setWebViewOption(WebView webview) {
 ......
    //设置是否支持运行JavaScript,仅在需要时打开
    webview.getSettings().setJavaScriptEnabled(true);

    ......
    //设置WebViewClient
    webview.setWebViewClient(new MyWebViewClient());
    webview.setWebChromeClient(new MyWebChromeClient());
}

private class MyWebViewClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

// view.loadUrl(url); 
Intent intent = new Intent(mContext, WebViewActivity.class); 
intent.putExtra(WebViewActivity.WEB_VIEW_URL, url); 
startActivity(intent); 
return true; 

……

    @Override
    public void onPageFinished(WebView view, String url) {

        super.onPageFinished(view, url);
        toggleShowLoading(false, "");
        if (view.getVisibility() == View.INVISIBLE) {
            view.setVisibility(View.VISIBLE);
        }
    }

…… 
}

private class MyWebChromeClient extends WebChromeClient {
......
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        if (newProgress > 25) {
            injectJS(view);
        }

        super.onProgressChanged(view, newProgress);
    }
}


private void injectJS(WebView webview) {
    webview.loadUrl("javascript:(function() " +
            "{ " +
            "document.getElementsByClassName('m-top-bar')[0].style.display='none'; " +
            "document.getElementsByClassName('m-footer')[0].style.display='none';" +
            "document.getElementsByClassName('m-page')[0].style.display='none';" +
            "})()");
}


“` 
可以看到WebView的初始化在setWebViewOption方法中进行。其中需要关注的有下面三行代码 
 
上面在WebSetting方法中WebViewClient的初始化,这里主要是点击新闻进行页面跳转的处理。 
提供WebViewClient并重写shouldOverrideUrlLoading方法,并返回true 
webview的返回键必须做处理,如果当前webview支持返回(不是点进来的第一个webview,而是再次跳转的),则返回。如果不支持返回(第一个webview界面),则finish当前的页面。 
 
初始化WebView的时候也进行了WebChromeClient的初始化。其中主要是在当进度超过百分之25的时候注入了一段javaScript代码。通过javascript代码去掉了当前网页的头部和底部。 

3.4 为什么这么做?

上面就是通过对网页信息注入js的形式,隐藏了相应的属性。 
如图,去掉标题栏,在网页中通过F12打开开发者工具,发现顶部栏的class的名字是m-top-bar,所以通过注入脚本的时候直接调用了这个class并且将display置为none。对这方面不了解的可以学习一下HTML5相关的知识。 

至于为什么是在进度条进行25之后进行注入,这里主要是在界面加载完成后再进行注入js就会有一定的卡顿闪屏现象。可以自己实践一下。 
本篇文章项目github地址:MVPCommon

4 参考链接

Building Web Apps in WebView(官网) 
webview reference(官网) 
深入讲解WebView-上 
深入讲解WebView-下


本篇文章项目github地址:MVPCommon 
本文章原地址:简书博客 
项目效果

1 前言

这篇文章将从webview的基础,介绍到项目中的真实使用。以及怎么样通过注入js脚本的方式来改变网页内容,从而在本地展示新闻体育列表。制作出一个像模像样的app。 
严正声明,网页数据来自 虎扑体育,仅作学习用途,请勿在任何商业用途中使用。

2 webview基础

WebView是手机中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装的一个组件。没有提供地址栏和导航栏,WebView只是单纯的展示一个网页界面。在开发中经常都会用到。

2.1 添加webview到应用中

直接将webview添加到layout文件中

<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"    
android:id="@+id/webview"   
 android:layout_width="fill_parent"    
android:layout_height="fill_parent"/>
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

使用webview加载url使用loadUrl方法:

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");
    
    
  • 1
  • 2
  • 1
  • 2

AndroidManifest.xml 中必须添加访问网络权限。

<manifest ... >   
 <uses-permission android:name="android.permission.INTERNET" />  
  ...
</manifest>
    
    
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

 #####2.2 支持JavaScript 
如果访问的页面中有 Javascript,则 WebView 初始化的时候必须设置支持 Javascript。(WebSetting中提供了很多有用的api, 点击链接查看)

WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
    
    
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

通过创建JavaScript的接口可以让JavaScript和安卓客户端进行交互。比如说JavaScript可以调用本地的安卓代码展示一个Dialog而不是使用JavaScript的alter()方法。通过addJavascriptInterface()方法创建接口。 
示例: 
定义一个“接口”类

public class WebAppInterface {
    Context mContext;

    /** Instantiate the interface and set the context */
    WebAppInterface(Context c) {
        mContext = c;
    }

    /** Show a toast from the web page */
    @JavascriptInterface
    public void showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在addJavascriptInterface方法中创建接口

WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
    
    
  • 1
  • 2
  • 1
  • 2

在HTML的JavaScript中调用WebView显示toast消息,

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意: 
1 addJavascriptInterface方法中要绑定的Java对象及方法运行在另外的线程中,而不是运行在构造他的线程中。 
2 使用addJavascriptInterface将会使javaScript可以操控安卓本地代码。因此有可能导致安全性问题,请确保所有HTML代码都是你所知道的。 
3 如果targetSdkVersion是17或者更高(Android 4.2以上),必须使用 @JavascriptInterface 注解,才能让网页访问到本地代码。

2.3 webview页面处理

当用户点击webview中的网页链接的时候,安卓系统默认会启动一个新的应用专门成立url的跳转。如果希望点击链接继续在当前webview中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 WebView的WebViewClient对象. 并重写shouldOverrideUrlLoading方法。 
“` 
WebView myWebView = (WebView) findViewById(R.id.webview); 
myWebView.setWebViewClient.(new WebViewClient(); 
private class MyWebViewClient extends WebViewClient { 
@Override 
public boolean shouldOverrideUrlLoading(WebView view, String url) { 
if (Uri.parse(url).getHost().equals(“www.example.com”)) { 
// This is my web site, so do not override; let my WebView load the page 
return false; 

// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs 
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 
startActivity(intent); 
return true; 

}


#####2.4 webview的页面导航处理 
当webview的url进行跳转的时候,自动回记录进入历史界面,可以使用goBack()方法和goForward()方法,进行返回和前进。
webview的canGoBack方法将会判断历史记录中是否还有页面,如果还有上一级页面,将会返回true
    
    
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

@Override 
public boolean onKeyDown(int keyCode, KeyEvent event) { 
// Check if the key event was the Back button and if there’s history 
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { 
myWebView.goBack(); 
return true; 

// If it wasn’t the Back key or there’s no web page history, bubble up to the default 
// system behavior (probably exit the activity) 
return super.onKeyDown(keyCode, event); 
}


###3 webview在项目中使用
上面介绍了WebView的基础知识,内容是我对[Building Web Apps in WebView(官网)](http://developer.android.com/guide/webapps/webview.html)
的大致翻译内容。如果还需要了解更多,推荐4 参考链接中的深入讲解Webview(上,下)。
这里接着介绍WebView在我项目中的使用。
#####3.1 需求是什么?
当然在我项目中,最开始想做的一个体育新闻资讯,但是苦于自己没有服务器,所以一开始都是模拟的数据。网上的开源api也是将所有新闻数据糅合在一起的,怎么分开呢?比如nba,英超,欧冠,各种不同的新闻数据在哪里获取呢?作为一个体育爱好者,经常会去的虎扑体育,然后找到了手机版的 [虎扑体育](http://www.jianshu.com/m.hupu.com)。这不就是我想要的体育新闻数据嘛,O(∩_∩)O哈哈~。
但是我不想要这个头部和底部呢 ,接下来分析怎么处理,很简单的实现。
![](http://upload-images.jianshu.io/upload_images/1833901-6509df5ac9cb479b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://upload-images.jianshu.io/upload_images/1833901-baae3d25c3979653.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#####3.2 效果怎么样?
看看运行效果,还是有模有样的
![](http://upload-images.jianshu.io/upload_images/1833901-7067542d7d9e7d5a.gif?imageMogr2/auto-orient/strip)

#####3.3 怎么做?
主要就是进行了新闻网页的展示,并且去掉了头部和底部。
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

public class WebViewFragment extends AbsTitleFragment { 
……

    R.layout.fragment_web_view;

……

@Override
protected void initViewsAndEvents(View rootView) {
    mWebView.setVisibility(View.INVISIBLE);
    toggleShowLoading(true, "loading");

    setWebViewOption(mWebView);
    if (getFragmentUrl() != null) {
        mWebView.loadUrl(getFragmentUrl());
    }
}

private void setWebViewOption(WebView webview) {
 ......
    //设置是否支持运行JavaScript,仅在需要时打开
    webview.getSettings().setJavaScriptEnabled(true);

    ......
    //设置WebViewClient
    webview.setWebViewClient(new MyWebViewClient());
    webview.setWebChromeClient(new MyWebChromeClient());
}

private class MyWebViewClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

// view.loadUrl(url); 
Intent intent = new Intent(mContext, WebViewActivity.class); 
intent.putExtra(WebViewActivity.WEB_VIEW_URL, url); 
startActivity(intent); 
return true; 

……

    @Override
    public void onPageFinished(WebView view, String url) {

        super.onPageFinished(view, url);
        toggleShowLoading(false, "");
        if (view.getVisibility() == View.INVISIBLE) {
            view.setVisibility(View.VISIBLE);
        }
    }

…… 
}

private class MyWebChromeClient extends WebChromeClient {
......
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        if (newProgress > 25) {
            injectJS(view);
        }

        super.onProgressChanged(view, newProgress);
    }
}


private void injectJS(WebView webview) {
    webview.loadUrl("javascript:(function() " +
            "{ " +
            "document.getElementsByClassName('m-top-bar')[0].style.display='none'; " +
            "document.getElementsByClassName('m-footer')[0].style.display='none';" +
            "document.getElementsByClassName('m-page')[0].style.display='none';" +
            "})()");
}


“` 
可以看到WebView的初始化在setWebViewOption方法中进行。其中需要关注的有下面三行代码 
 
上面在WebSetting方法中WebViewClient的初始化,这里主要是点击新闻进行页面跳转的处理。 
提供WebViewClient并重写shouldOverrideUrlLoading方法,并返回true 
webview的返回键必须做处理,如果当前webview支持返回(不是点进来的第一个webview,而是再次跳转的),则返回。如果不支持返回(第一个webview界面),则finish当前的页面。 
 
初始化WebView的时候也进行了WebChromeClient的初始化。其中主要是在当进度超过百分之25的时候注入了一段javaScript代码。通过javascript代码去掉了当前网页的头部和底部。 

3.4 为什么这么做?

上面就是通过对网页信息注入js的形式,隐藏了相应的属性。 
如图,去掉标题栏,在网页中通过F12打开开发者工具,发现顶部栏的class的名字是m-top-bar,所以通过注入脚本的时候直接调用了这个class并且将display置为none。对这方面不了解的可以学习一下HTML5相关的知识。 

至于为什么是在进度条进行25之后进行注入,这里主要是在界面加载完成后再进行注入js就会有一定的卡顿闪屏现象。可以自己实践一下。 
本篇文章项目github地址:MVPCommon

4 参考链接

Building Web Apps in WebView(官网) 
webview reference(官网) 
深入讲解WebView-上 
深入讲解WebView-下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值