Android与H5交互,以及WebView加载进度条
前言
虽然项目主体是原生Android开发,但是难免会遇到一些H5页面,如:首页Banner的活动推送。我们之所以选择H5来实现,因为它相对灵活,可以多平台运行,从而提高开发效率,节约开发成本。
文章分为两个章节:Android与H5交互、WebView加载进度条。
一、Android与H5交互
Android与H5的简单交互.gif1、WebView加载HTML页面
// 加载一个网页:webView.loadUrl("http://www.baidu.com/");// 加载assets文件夹下的test.html页面webView.loadUrl("file:///android_asset/test.html");
为了点击HTML的内部的链接不跳到外部浏览器,我们还需要setWebViewClient:
// 帮助WebView处理各种通知、请求事件,不写html页面里的链接会跳到外部浏览器哦mWebView.setWebViewClient(new WebViewClient());
2、本地Java调用js方法
想要调用js方法,就需要让webView支持才可以:
WebSettings webSettings = mWebView.getSettings();// 设置为可调用js方法webSettings.setJavaScriptEnabled(true);
若调用的js方法没有返回值,则直接可以调用mWebView.loadUrl("javascript:show()"),其中show是js中的方法;
若有返回值时我们可以调用mWebView.evaluateJavascript()方法:
// 直接访问H5里不带返回值的方法,show()为H5里的方法mWebView.loadUrl("JavaScript:show()");// Android调用有返回值js方法,安卓4.4以上才能用这个方法mWebView.evaluateJavascript("sum(1,2)", new ValueCallback() { @Override public void onReceiveValue(String value) { Log.e(TAG, "js返回的结果为 = " + value); Toast.makeText(MainActivity.this, "js返回的结果为 = " + value, Toast.LENGTH_LONG).show(); }});
js代码如下:
3、js调用本地Java方法
在Android4.2以上可以直接使用@JavascriptInterface注解来声明,下面是在一个本地Java方法:
public class JsInteration { // 一定要写,不然H5调不到这个方法 @JavascriptInterface public String back() { return "我是java方法的返回值"; } @JavascriptInterface public void goNewAct(String str) { // 也可接收js中的参数 Log.e(TAG, "goNewAct: " + str); startActivity(new Intent(MainActivity.this, NewActivity.class)); }}
定义完这个方法后再调用mWebView.addJavascriptInterface()方法:
// 打开js接口給H5调用,参数1为本地类名,参数2为别名;h5用window.别名.类名里的方法名才能调用方法里面的内容// 例如:window.android.back();mWebView.addJavascriptInterface(new JsInteration(), "android");
js代码如下:
4、WebView监听返回键
当webview包含多个页面的时候,当我们点击返回键的时候,更多时候我们需要的是返回上个页面,而不是直接关闭webview。所以我们需要重写返回键事件:
@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { if (webView.canGoBack()) { // goBack()表示返回WebView的上一页面 webView.goBack(); return true; } else { finish(); return true; } } return false;}
项目源码在文章末尾给出,已上传至GitHub。
二、WebView加载进度条
在实现基本功能的同时,我们还要注重用户体验,所以加载进度条也就变得不可或缺。本着用户是上帝的原则,还能说些什么(摊手)。。
ProgressWebView.gif
实现思路
首先在自定义的WebView中加入了一个水平方向的ProgressBar,然后为这个ProgressBar设置progressDrawable;创建WebChromeClient 继承 WebChromeClie,监听加载进度的变化onProgressChanged,并做出相应的设置;重写onScrollChanged方法,防止因滑动而造成ProgressBar的移动。
完整代码如下:
public class ProgressWebView extends WebView { private ProgressBar mProgressBar; public ProgressWebView(Context context) { super(context); } public ProgressWebView(Context context, AttributeSet attrs) { super(context, attrs); // 使用ProgressBar作为加载进度条,当然也可使用其他view作为进度显示 mProgressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 8); mProgressBar.setLayoutParams(layoutParams); // 获取Drawable资源,并为ProgressBar设置setProgressDrawable Drawable drawable = ContextCompat.getDrawable(context, R.drawable.web_progress_bar_states); mProgressBar.setProgressDrawable(drawable); addView(mProgressBar); // 辅助WebView处理js的对话框,网站图标,网站title,加载进度等 setWebChromeClient(new WebChromeClient()); } public class WebChromeClient extends android.webkit.WebChromeClient { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress == 100) { // 加载完成,将进度条隐藏 mProgressBar.setVisibility(GONE); } else { if (mProgressBar.getVisibility() == GONE) { mProgressBar.setVisibility(VISIBLE); } // 设置加载进度 mProgressBar.setProgress(newProgress); } super.onProgressChanged(view, newProgress); } } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { // 使进度条始终固定在顶部位置,快速滑动时还是会有影响,日常使用ok // 使用ViewGroup.LayoutParams滑动会消失,原因不详,求大神告知 LayoutParams lp = (LayoutParams) mProgressBar.getLayoutParams(); lp.x = l; lp.y = t; mProgressBar.setLayoutParams(lp); super.onScrollChanged(l, t, oldl, oldt); }}
进度条Drawable这里写的比较简单,当然也可以写的炫酷点。web_progress_bar_states.xm代码如下:
-
-
完整的MainActivity代码:
public class MainActivity extends AppCompatActivity { private static final String TAG = "--->"; private ProgressWebView mWebView; @SuppressLint({"JavascriptInterface", "SetJavaScriptEnabled"}) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = findViewById(R.id.webview); // 加载本地asset下面的test.html文件 mWebView.loadUrl("file:///android_asset/test.html"); // 加载普通网页// mWebView.loadUrl("http://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gbk&word=%CD%BC%C6%AC&fr=ala&ala=1&alatpl=others&pos=0"); WebSettings webSettings = mWebView.getSettings(); // 打开js支持 webSettings.setJavaScriptEnabled(true); // 打开js接口給H5调用,参数1为本地类名,参数2为别名;h5用window.别名.类名里的方法名才能调用方法里面的内容,例如:window.android.back() mWebView.addJavascriptInterface(new JsInteration(), "android"); // 帮助WebView处理各种通知、请求事件,不写html页面里的链接会跳到外部浏览器哦 mWebView.setWebViewClient(new WebViewClient()); // 辅助WebView处理js的对话框,网站图标,网站title,加载进度等,非必须(由于ProgressWebView重写了该方法,这里应该注销,否则自定义无效)// mWebView.setWebChromeClient(new WebChromeClient()); // 缓存模式(方便测试加载进度条) webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); } /** * 自己写一个类,里面是提供给H5访问的方法 */ public class JsInteration { /** * 一定要写,不然H5调不到这个方法 */ @JavascriptInterface public String back() { return "我是java方法的返回值"; } @JavascriptInterface public void goNewAct(String str) { // 可接收js中的参数 Log.e(TAG, "goNewAct: " + str); Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show(); startActivity(new Intent(MainActivity.this, NewActivity.class)); } } /** * 点击按钮,访问H5里带返回值的方法 */ @TargetApi(Build.VERSION_CODES.KITKAT) public void onClick(View v) { // 直接访问H5里不带返回值的方法,show()为H5里的方法 mWebView.loadUrl("JavaScript:show()"); // 传固定字符串可以直接用单引号括起来 // 访问H5里带参数的方法,alertMessage(message)为H5里的方法 mWebView.loadUrl("javascript:alertMessage('哈哈')"); // 当出入变量名时,需要用转义符隔开 String content = "2333"; mWebView.loadUrl("javascript:alertMessage(\"" + content + "\")"); // Android调用有返回值js方法,安卓4.4以上才能用这个方法 mWebView.evaluateJavascript("sum(1,2)", new ValueCallback() { @Override public void onReceiveValue(String value) { Log.e(TAG, "js返回的结果为 = " + value); Toast.makeText(MainActivity.this, "js返回的结果为 = " + value, Toast.LENGTH_LONG).show(); } }); }}
项目源码:https://github.com/princekin-f/webview
随缘点赞,传播正能量~
更多相关文章
- Android(安卓)Service生命周期及用法!
- android多线程编程总结
- Android(安卓)Activity生命周期具体内容概述
- Android的SQLite学习及使用方法(1)
- Android自适应不同屏幕几种方法
- Android:异步调用详解
- Android(安卓)AIDL(Android(安卓)Interface Definition Language
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用