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. Qt on Android:添加分享功能
  2. android 面试题经典
  3. Android(安卓)Framework 框架系列之 PhoneWindowManager
  4. Android(安卓)Service——在子线程中更新UI
  5. Android(安卓)Webview开发基本使用总结(一)
  6. Android设置TextView显示指定个数字符,超过部分显示...(省略号)的
  7. 浅谈Java中Collections.sort对List排序的两种方法
  8. mybatisplus的坑 insert标签insert into select无参数问题的解决
  9. Python list sort方法的具体使用

随机推荐

  1. Android(安卓)-- 隐藏式抽屉(SlidingDrawe
  2. android SQLite查询
  3. Android(安卓)封装实现各种样式对话框
  4. Android屏蔽Home键
  5. [转载]Android(安卓)by example : MVVM +
  6. Android外部存储/内部存储路径获取大全
  7. Android(安卓)xml文件里读取string array
  8. 使用Android内置httpRequest发起httpRequ
  9. android CVE 漏洞汇总
  10. Android(安卓)Widget桌面组件创建