Android项目开发中针对webview避免不了混合开发模式,可Android上的webview又很不争气,几乎每个Android版本都有webvie的改动,在国内这种鱼龙混杂环境下出乎意料的问题又很多,这次就谈谈webview高度自适应的问题。

问题

在Android开发生涯中想必大家都遇到过,webview在有些时候展示不完整,在某些时候底部有一片空白,有些时候始终又滑不到底。。。导致这个问题的原因常见有以下三种:

  • 网页高度不固定
  • 嵌套布局导致webview的高度无法自适应
  • 系统原因导致webview在某种特殊情况下不能兼容当前应用的屏幕分辨率

下边就分别说说这三种情况引起的原因以及解决方法。

针对网页高度不固定问题

这部分原因和H5编写方法有很大关系,例如Ajax异步处理结果过慢,webview的高度不能及时更新;也有可能H5编写时预留了一个资源展示区等待将来资源展示,结果资源没有加载出来。这个和H5开发人员说明一下情况,检查一下代码结构。

针对嵌套布局导致webview高度不固定问题

这个是Android开发最常见的事,很多时候是混合开发模式,不得已采用scrollview嵌套webview,但是我们知道scrollview中嵌套其他view常常使某些view的高度(match_parent)失效,当然你可以采用android:fillViewport="true"强制让其撑满,但是似乎其内部的webview又不听话了,这个道理很明显,毕竟webview渲染的是网页,也即是我们能够准确固定webview高度这个问题就迎刃而解了。

针对webview兼容当前应用屏幕密度问题

首先我们要处理的是避免系统字体的缩放影响webview缩放,我们可以用webview.getSettings().setTextZoom(100)来避免。其余的支持自适应即可,在应用屏幕密度设定之后webiview可自动匹配,当然也有一些奇葩设备(被应用商修改过),这部分我们可以忽略了。

针对高度不固定问题解决方案

我这里给出两种解决方案。

布局结构调整

按照官方建议webiview父布局高度采用match_parent

WebView根据网页的高度自动扩展自身高度:

我们按照步骤走:

第一步:本地定义Js交互接口,通常H5需要明确这个接口标识,Android端才能回调相关内容给H5。

mWebView.addJavascriptInterface(this, "App");

第二步:本地实现接口方法,H5通过上边的“APP”接口标识能调用本地该接口里面的方法。

/** * js回调,重新计算webview的高度。 */@JavascriptInterfacepublic void resize(final float clientWidth, final float scrollHeight) {    if (mActivity == null || mWebView == null || clientWidth == 0) {        return;    }    mActivity.runOnUiThread(new Runnable() {        @Override        public void run() {            float rate = mWebView.getWidth() / clientWidth;            Log.i("TAG", "webview---------clientWidth:" + clientWidth + "---------scrollHeight:" + scrollHeight + "---------rate:" + rate);            mWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,                    (int) (scrollHeight * rate)));        }    });}

第三步:本地调用H5的js方法,告诉H5:“我,大Android,需要你H5现在的宽和高”,然后H5乖乖的把界面上宽高回调给本地,就是第二步的方法。但是!我今天说的这个是通用方式,是针对所有的H5的,不可能让每个H5都定义一个js方法供Android端调用,怎么办呢?好办,直接让H5回调本地方法:

mWebView.loadUrl("javascript:App.resize(document.documentElement.clientWidth, document.documentElement.scrollHeight)");

这里的“App”其实就是“this”,那么js回调时机是什么时候呢,我是希望这个页面加载结束的时候告诉我,所以重写WebViewClient里面的onPageFinished方法。由于有些H5采用异步加载的方式,我不知道他到底什么时候完全加载出来,所以这里我分多次让H5帮我回调:

class DefaultWebViewClient extends WebViewClient {    //页面内跳转    @Override    public boolean shouldOverrideUrlLoading(WebView webView, String s) {        webView.loadUrl(s);        return true;    }    @Override    public void onPageFinished(WebView webView, String s) {        super.onPageFinished(webView, s);        //执行网页高度获取,不断获取网页高度        mHandler.post(new Runnable() {            //执行最大次数            int times = 5;            @Override            public void run() {                if (times > 0) {                    mWebView.loadUrl("javascript:App.resize(document.documentElement.clientWidth, document.documentElement.scrollHeight)");                    mHandler.postDelayed(this, 1000);                    times--;                }            }        });    }}

总结

以上是我针对该类问题想到的一些处理方案,大家有更好的处理方式不妨也分享一下,集思广路,一同进步。

更多相关文章

  1. Android设置TextView显示指定个数字符,超过部分显示...(省略号)的
  2. Android使用自定义字体的方法
  3. Android 环信官方Demo3.3.2详细配置方法
  4. Android中经常用到的方法--SDcard下文件的操作
  5. Android Intent调用方法总结
  6. Android 应用程序退出后不在运行列表中显示的方法
  7. ffmpeg neon优化必看!!android下编译ffmpeg with neon的正确方法(已
  8. Android ADB使用方法
  9. Handle详解和使用方法

随机推荐

  1. 无法理解如何使用javascript和jquery代码
  2. 在不触发hashchange事件的情况下更改哈希
  3. 从事件监听器OnClick中排除按钮
  4. Ajax请求等到第一次AJAX调用未完成
  5. jQuery中$.get、$.post、$.getJSON和$.aj
  6. js或Jquery中判断字符串中是否有换行符或
  7. 如何使用javascript或jquery获取图像的自
  8. jQuery——将title属性用作悬停的文本,但
  9. 将AngularJS、jQueryUI、Angular-Drag-Dr
  10. 我需要从jquery ajax post中撤回数据并将