关注微信公众号:程序员小安,精彩文章按期推送。javascript
最近几年混合应用愈来愈流行,及一部分功能用原生代码开发,一部分功能用html5实现。那何时用原生何时用网页呢?不少人第一反应就是常常变化的页面用网页开发,避免常常发包,不全对。其实由于网页使用体验远远不及原生开发,因此通常有如下两种状况建议使用网页代替原生: 1.试水功能 2.相似双11主会场,这类只在固定时间内使用的功能。css
1)xml布局:html
<?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,支持缩小放大,支持本地存储,支持缓存等。html5
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目录下的本地网页和图片等资源很是方便,以下代码所示:java
webView.loadUrl("file:///android_asset/html/intermodulation.html");
复制代码
(2)加载远程网页jquery
webView.loadUrl("http://www.baidu.com/");
复制代码
(3)使用 LoadData 或者 loadDataWithBaseURL方法加载内容 有时候咱们的webview可能只是html片断,而不是一个完整的网页,事实上绝大多数时候都是如此,完整的网页无需作成应用,而直接在浏览器访问。这种状况咱们使用 LoadData 或者 loadDataWithBaseURL方法,后者用的最多:android
void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)
复制代码
loadDataWithBaseURL()比loadData()多两个参数,能够指定HTML代码片断中相关资源的相对根路径,也能够指定历史Url,其他三个参数相同。程序员
这里主要注意参数baseUrl,baseUrl指定了你的data参数中数据是以什么地址为基准的,由于data中的数据可能会有超连接或者是image元素,而不少网站的地址都是用的相对路径,若是没有baseUrl,webview将访问不到这些资源。以下所示:web
String body ="示例:这里有个img标签,地址是相对路径<img src='/uploads/allimg/130923/1FP02V7-0.png' />";
mWebView.loadDataWithBaseURL("http://baidu.com", body, "text/html", "utf-8",null);
复制代码
若是baseUrl没有指定为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)js调用android原生方法
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下载地址:
关注下方公众号,留言回复源码便可获取。
若有错误欢迎指出来,一块儿学习。