您的位置:首页 > 移动开发

webview中有输入框,输入法挤压页面,在低端机器出现页面错乱

2015-10-19 11:52 323 查看
最近手机要加入web化的东西,Android端要提供一个容器给web前端,涉及到几个东西,一个是模拟登陆,还有webview的配置。遇到一个奇怪的BUG,如标题。

A、分析一下这个过程:

1、有输入框,获取焦点后输入法弹出

2、点击“提交”按钮,用layer.mobile ( 后文用layer指代它 ) 弹出遮罩

3、输入法失去焦点自动隐藏

4、触发WebView页面重绘,layer.mobile遮罩被重新定位并绘制

B、问题出现在第四步,有几种表现形式:

1、红米,有一定概率出现,页面错误,上方空白,在页面下方出现原来输入法压缩后页面的高度的webview,点击页面,可以正常响应,刚觉就像原来的页面被一层错乱的页面遮住了,但是页面是绘制完成的。

2、某低端机酷派,有一定概率出现,页面下方空白,上方有东西,目测上方高度也是输入法压缩前高度,空白点击无任何响应,目测是绘制失败,webview放弃了绘制。

3、某华为机,贵一点,正常。

4、系统自带浏览器没有问题,webview才有问题

C、尝试解决方法:

从过程来看,web端那样写是有一点问题的,layer出现后,页面重绘,又得重新定位,重新绘制,很考究浏览器性能,但是为什么系统自带的就可以呢???!!!

(PS:丢!我怎么知道,我又不是没有参与webview和系统浏览器的开发。后来查资料说是两个团队在负责的,不知道真假)

观察系统浏览器,其实也有错位的问题,不过错位后它自己会重新绘制一边,如果web端不动,只能我这边在页面完成后通知webview去重新绘制一次。

或者web端的同学配合一下,webview嵌套在scrollview里面,不让输入法挤压webview,layer重新绘制的问题也不会这么突兀。(后来是web端的同学配合一起搞定的)

1、注册webview的onGlobalLayout:

mWebView.getViewTreeObserver().addOnGlobalLayoutListener(this);

@Override
public void onGlobalLayout() {
mWebView.invalidate();
}
手动重绘后B中,1,2俩部机器都没有变化!观察2,好像只要webview往上拉就没问题,于是

mWebView.getViewTreeObserver().addOnGlobalLayoutListener(this);

@Override
public void onGlobalLayout() {
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.scrollTo(0, 0);
}};
mWebView.invalidate();
}


然后机器2的问题就解决了,但是在红米上,问题似乎更加严重了,几乎是重绘后立刻就会错位。考虑是不是硬件渲染的问题,禁用了硬件渲染也不行,remove,addview,visible,invisible webview也是不行。是重绘不彻底?

感觉是底层的东西出了问题,正准备去读读源代码.... (如果看到这里您有 “解决方法” 希望您能在后面评论回复)

然而时间有限,web端的同学也有空了,就一起搞咯,有几个问题:

1、在scrollview中,web端在viewport中拿不到页面高度。

2、因为在scrollview中,输入法获取焦点后不会自动定位到输入框处

3、layer遮罩的无法定位到页面中心,弹窗会漂到页面顶部,如果网页内容大于页面内容,layer还会随着页面滑动飘

第三个问题不是我解决的,我这边给了两个方法用来修正第一二个问题:

public class JsObject {
@JavascriptInterface
public void scrollTo(int dp) {
Activity.this.scrollTo(dp);
}

@JavascriptInterface
public int getHeight(){
return ScrollViewHeight;
}
}

mWebView.addJavascriptInterface(new JsObject(), "nativeJava");
web端可以这样调用:

window.nativeJava.getHeight();
window.nativeJava.scrollTo(300);
有几个小细节:

1、是web端用的px直接就是android的dp了,所以getHeight()不用再转化成android端物理的px了。但是scrollTo用的是android端物理的px,这里需要手动转一下dp-> px

2、scrollTo在输入发弹出之后还要在自己滑动一下,因为scrollview的高度变了,别告诉我你不知道怎么监听输入法的弹出与收起

3、ScrollView在onCreate()里面是不能直接geiHeight()的,要拿它的高度,也可以像我第一步(1、注册webview的onGlobalLayout)那样,在接口实现处getHeight()

大概就是这样,web端怎么修改layer.mobile代码我就看不见咯.

2016.12

后来我知道web上怎么做了,比预期中简单了不少,不贴细节了。

回头看web端的同学当时实际上也是没处理好,问题还不到要原生配合调整的地步。web当时如果有做这样的设置

http://blog.csdn.net/yeshennet/article/details/51222947

原生这边不用动也是可以的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息