最近几年混合应用越来越流行,及一部分功能用原生代码开发,一部分功能用html5实现。那什么时候用原生什么时候用网页呢?很多人第一反应就是经常变化的页面用网页开发,避免经常发包,不全对。其实因为网页使用体验远远不及原生开发,所以一般有以下两种情况建议使用网页代替原生: 1.试水功能 2.类似双11主会场,这类只在固定时间内使用的功能。
1)xml布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/title_name" android:layout_width="match_parent" android:layout_height="44dp" android:gravity="center" android:background="#987654" android:text="title"/> <ProgressBar android:id="@+id/webview_progressbar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="fill_parent" android:layout_height="2dp" /> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent"></WebView> </LinearLayout> 复制代码
2)利用WebSettings设置一些页面属性,比如,页面字体的大小,是否支持js,支持缩小放大,支持本地存储,支持缓存等。
public static void initWebSettings( WebView webView) { WebSettings webSettings = webView.getSettings(); webSettings.setDefaultTextEncodingName("UTF-8");//设置默认为utf-8 webSettings.setTextZoom(100);//设置WebView中加载页面字体变焦百分比,默认100 //属性可以让webview只显示一列,也就是自适应页面大小,不能左右滑动 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING); } else { webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); } //设置此属性,可任意比例缩放 webSettings.setUseWideViewPort(false); webSettings.setLoadWithOverviewMode(true); //页面支持缩放 webSettings.setBuiltInZoomControls(false); webSettings.setSupportZoom(false); webSettings.setDisplayZoomControls(false); //设置支持js webSettings.setJavaScriptEnabled(true); webSettings.setSavePassword(false); //设置 缓存模式 webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // 开启 DOM storage API 功能 webSettings.setDomStorageEnabled(true); webView.setVerticalScrollBarEnabled(false); webView.setVerticalScrollbarOverlay(false); webView.setHorizontalScrollBarEnabled(false); webView.setHorizontalScrollbarOverlay(false); } 复制代码
3)加载内容 (1)加载assets目录下的本地网页 一般我们都是把html文件放在assets目录下, WebView调用assets目录下的本地网页和图片等资源非常方便,如下代码所示:
webView.loadUrl("file:///android_asset/html/intermodulation.html"); 复制代码
(2)加载远程网页
webView.loadUrl("http://www.baidu.com/"); 复制代码
(3)使用 LoadData 或者 loadDataWithBaseURL方法加载内容 有时候我们的webview可能只是html片段,而不是一个完整的网页,事实上绝大多数时候都是如此,完整的网页无需做成应用,而直接在浏览器访问。这种情况我们使用 LoadData 或者 loadDataWithBaseURL方法,后者用的最多:
void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl) 复制代码
loadDataWithBaseURL()比loadData()多两个参数,可以指定HTML代码片段中相关资源的相对根路径,也可以指定历史Url,其余三个参数相同。
这里主要注意参数baseUrl,baseUrl指定了你的data参数中数据是以什么地址为基准的,因为data中的数据可能会有超链接或者是image元素,而很多网站的地址都是用的相对路径,如果没有baseUrl,webview将访问不到这些资源。如下所示:
String body ="示例:这里有个img标签,地址是相对路径<img src='/uploads/allimg/130923/1FP02V7-0.png' />"; mWebView.loadDataWithBaseURL("http://baidu.com", body, "text/html", "utf-8",null); 复制代码
如果baseUrl没有指定为http://baidu.com,那么这张图片将显示不出来。
到这里,基本的webview功能已经可以使用了。
实际项目中,可能会显示网页标题,需要展示加载进度,或者当点击网页中一个按钮或者一个商品,需要跳转到原生界面,这个时候就需要用到两个方法: WebViewClient主要用来拦截网页中的请求,开始,结束请求等操作。
webView.setWebViewClient(new WebViewClient() { //返回值:true 不会显示网页资源,需要等待你的处理,false 就认为系统没有做处理,会显示网页资源 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //当url里面包含webview字段的时候,则跳转到ShowActivity原生页面,否则还是继续显示网页 //比如:在百度输入框里面输入webview在点击搜索,再点击任何有webview字段的链接, //则不继续显示网页,而是跳转到自己定义的原生页面 if (!TextUtils.isEmpty(url) && url.contains("webview")) { Intent intent = new Intent(ClickInterceptionActivity.this, ShowActivity.class); intent.putExtra("url", url); startActivity(intent); return true; } return false; } //在页面开始加载时候做一些操作,比如展示进度条 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { webview_progressbar.setVisibility(View.VISIBLE); super.onPageStarted(view, url, favicon); } //在页面加载完成的时候做一些操作,比如隐藏进度条 @Override public void onPageFinished(WebView view, String url) { webview_progressbar.setVisibility(View.GONE); super.onPageFinished(view, url); } }); 复制代码
WebChromeClient主要辅助WebView处理JavaScript的对话框、网站图标、网站title、加载进度等。
webView.setWebChromeClient(new WebChromeClient(){ @Override public void onProgressChanged(WebView view, int newProgress) { webview_progressbar.setProgress(newProgress); super.onProgressChanged(view, newProgress); } @Override public void onReceivedTitle(WebView view, String title) { title_name.setText(title); super.onReceivedTitle(view, title); } @Override public void onReceivedIcon(WebView view, Bitmap icon) { super.onReceivedIcon(view, icon); } }); 复制代码
效果如下所示:带有加载进度和标题
当在输入框中webview,并点击【百度一下】,正常情况会进入搜索结果网页,由于我们重写了shouldOverrideUrlLoading方法,对url实现了拦截,则跳转到原生页面。
除了上面的简单展示,很多项目中还会有js跟java的双向交互。
1.addJavascriptInterface
webView.addJavascriptInterface(new clickOnJS(), "click"); 复制代码
2.在android中定义待调用方法:
class clickOnJS { @JavascriptInterface public void OnClick() { Toast.makeText(IntermodulationActivity.this, "调用java成功", Toast.LENGTH_SHORT).show(); } } 复制代码
3.js定义方法去调用java方法。
$(function(){ $('.payment').click(function(){ window.click.OnClick(); }); }); 复制代码
效果如下图所示:点击【js调用java】按钮,则弹出toast,证明成功调用java原生方法。
2)android调用js方法当点击android页面上某个按钮的时候,改变js页面的内容,其实就是android原生给js传值。 1.点击标题,则调用js方法
title_name.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //调用js方法 webView.loadUrl("javascript:setcontent(2)"); } }); 复制代码
2.js代码实现,修改cr的值
function setcontent(content){ $('.num ,.cr').text(content); } 复制代码
效果如下图所示:点击标题,则调用js的setcontent方法,【待修改点】变成【2】,则证明成功调用java原生方法。
1)拦截js点击跳转关键代码类:
public class ClickInterceptionActivity extends Activity { private TextView title_name; private ProgressBar webview_progressbar; private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_click_interception); initView(); initWebViewSettings(); } /** * 初始化布局组件 */ private void initView() { title_name = (TextView) findViewById(R.id.title_name); webview_progressbar = (ProgressBar) findViewById(R.id.webview_progressbar); webView = (WebView) findViewById(R.id.webview); } /** * 初始化webview配置 */ private void initWebViewSettings() { WebViewSettings.initWebSettings(webView); webView.setWebViewClient(new WebViewClient() { //返回值:true 不会显示网页资源,需要等待你的处理,false 就认为系统没有做处理,会显示网页资源 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //当url里面包含webview字段的时候,则跳转到ShowActivity原生页面,否则还是继续显示网页 //比如:在百度输入框里面输入webview在点击搜索,再点击任何有webview字段的链接, //则不继续显示网页,而是跳转到自己定义的原生页面 if (!TextUtils.isEmpty(url) && url.contains("webview")) { Intent intent = new Intent(ClickInterceptionActivity.this, ShowActivity.class); intent.putExtra("url", url); startActivity(intent); finish(); return true; } return false; } //在页面开始加载时候做一些操作,比如展示进度条 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { webview_progressbar.setVisibility(View.VISIBLE); super.onPageStarted(view, url, favicon); } //在页面加载完成的时候做一些操作,比如隐藏进度条 @Override public void onPageFinished(WebView view, String url) { webview_progressbar.setVisibility(View.GONE); super.onPageFinished(view, url); } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { webview_progressbar.setProgress(newProgress); super.onProgressChanged(view, newProgress); } @Override public void onReceivedTitle(WebView view, String title) { title_name.setText(title); super.onReceivedTitle(view, title); } @Override public void onReceivedIcon(WebView view, Bitmap icon) { super.onReceivedIcon(view, icon); } }); webView.loadUrl("http://www.baidu.com/"); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) { webView.goBack(); return true; } return super.onKeyDown(keyCode, event); } } 复制代码
2)js跟java交互关键类:
public class IntermodulationActivity extends Activity { private TextView title_name; private ProgressBar webview_progressbar; private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.intermodulation); initView(); initWebViewSettings(); } /** * 初始化布局组件 */ private void initView() { title_name = (TextView) findViewById(R.id.title_name); webview_progressbar = (ProgressBar) findViewById(R.id.webview_progressbar); webView = (WebView) findViewById(R.id.webview); title_name.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //调用js方法 webView.loadUrl("javascript:setcontent(2)"); } }); } /** * 初始化webview配置 */ private void initWebViewSettings() { WebViewSettings.initWebSettings(webView); webView.addJavascriptInterface(new clickOnJS(), "click"); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (!TextUtils.isEmpty(url) && url.contains("webview")) { Intent intent = new Intent(IntermodulationActivity.this, ShowActivity.class); intent.putExtra("url", url); startActivity(intent); } return false; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { webview_progressbar.setVisibility(View.VISIBLE); super.onPageStarted(view, url, favicon); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); webview_progressbar.setVisibility(View.GONE); } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { webview_progressbar.setProgress(newProgress); super.onProgressChanged(view, newProgress); } @Override public void onReceivedTitle(WebView view, String title) { title_name.setText(title); super.onReceivedTitle(view, title); } @Override public void onReceivedIcon(WebView view, Bitmap icon) { super.onReceivedIcon(view, icon); } }); webView.loadUrl("file:///android_asset/html/intermodulation.html"); } class clickOnJS { @JavascriptInterface public void OnClick() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } Toast.makeText(IntermodulationActivity.this, "调用java成功", Toast.LENGTH_SHORT).show(); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) { webView.goBack(); return true; } return super.onKeyDown(keyCode, event); } } 复制代码
3)js实现类:
<!doctype html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport"/> <title>js和java交互(点击,点击)</title> <link href="images/styles.css" rel="stylesheet" type="text/css"> <script src="https://code.jquery.com/jquery-3.0.0.min.js"></script> </head> <body class="mbg1"> <div class="paybox pay2box">java修改js============== <span class="cr">待修改点</span></div> <span class="payment"><a href="#">js调用java</a></span> <script> $(function(){ $('.payment').click(function(){ window.click.OnClick(); }); }); function setcontent(content){ $('.num ,.cr').text(content); } </script> </body> </html> 复制代码
6.demo下载地址:
关注下方公众号,留言回复源码即可获取。
如有错误欢迎指出来,一起学习。