使用CrossWork替代WebView中的一个问题

记录一个在使用XWalkView的时候的问题;


情景再现


一个HTML页面中有个输入框,在点击这输入框,弹出软键盘时,软键盘会遮盖到输入框.


经百度一番,这个问题可以用AndroidBug5497Workaround这个工具类解决


经过一段时间的使用,发现如果Theme中设置了<item name="android:windowIsTranslucent">true</item>,


则键盘下落时会显示上一层页面,一闪而过,在性能较差的机器上尤为明显,经放慢截图是这样:




如果Theme中设置了<item name="android:windowIsTranslucent">false</item>,


则键盘下落时会显示黑色,一闪而过,在性能较差的机器上尤为明显


经过一番折腾,发现只要XWalkView改变Size,就会出现黑屏或者透明的问题.点进去,看了一下XWalkView的代码,

发现在创建XWalkView对象的时候,创建了一个SurfaceView对象,会不会是SurfaceView的锅呢?

百度了一下SurfaceView的遮盖,背景之类的问题,发现给XWalkView在onXWalkReady()方法中设置

walkView.setZOrderOnTop(true)会解决黑屏

walkView.setZOrderOnTop(true)这行代码就是设置内部SurfaceView对象的,使之显示在SurfaceView所在window窗体的最上



心里是乐开了花啊,感觉全世界都是渣渣,我特么最牛逼




但是好景不长,walkView.setZOrderOnTop(true)代码之后,只有第一次进入页面可以显示数据,从第二次开始就再也无法显示数据



重新打开其他的页面,还是可以显示的...内心一万只草泥马在奔腾...




从此疑惑一段时间,最终决定把walkView.setZOrderOnTop(true)这行代码下掉


一段时间后,迫于老总压力,重新研究这个bug.


经google,(https://crosswalk-project.org/jira/browse/XWALK-6628)发现可以用


1), Apply XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, true); before new XWalkView

2), mXWalkView.setBackgroundColor(Color.TRANSPARENT);

这两行代码解决下落时的黑色,果断尝试了一下.


第一次在4.4的机器上成功了,也是舒了一口气,终于解决了这个问题吗?都不敢相信了,所以换了个高档手机试了一下


并没有什么卵用,XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, true)这行代码在Android7.0

以上会抛运行时异常:

TextureView doesn't support displaying a background drawable,直接闪退,绝不犹豫

查了XWalkView的源码,果然在ANIMATABLE_XWALK_VIEW为true时,会用TextureView来渲染数据,在

ANIMATABLE_XWALK_VIEW为false时,

用SurfaceView来渲染 所以这种方法GG



又看到SurfaceView,我赶紧百度了下,SurfaceView到底是个什么神奇的东西,说什么独立的window,什么什么的,可是独立的

window,为啥我让他显示在最上面了,还是出问题呢?而且第一次好像是成功了啊,之后在进入为啥就黑屏了呢?很纳闷...

想了一会儿,是不是有其他的SurfaceView覆盖在上面了呢?但是XWalkView中只有实例化的时候创建了一个SurfaceView啊

决定遍历一下XWalkView的视图树,发现SurfaceView就给设置setZOrderOnTop(true),

private void setZOrderOnTopFlag(ViewGroup viewGroup, boolean flag) {
        int childCount = viewGroup.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = viewGroup.getChildAt(i);
            if (child instanceof SurfaceView) {
                ((SurfaceView) (child)).setZOrderOnTop(flag);
                LogUtils.tag("设置setZOrderOnTop").e(viewGroup.getClass().getName() + "中" + child.toString());
                return;
            }
            if (child instanceof ViewGroup) {
                setZOrderOnTopFlag((ViewGroup) child, flag);
            }


        }
    }


经过这个代码一跑,我擦,第一次进入都不显示数据了....凉凉


又点了一次,卧槽,竟然第二次可以,再点,第三次也可以,再点.....

发现了规律,只有第一次显示不了...

我敲里吗,这都行?一开始只有第一次可以,现在只有第一次不可以...神bug,牛逼!!!

既然如此,就不要怪我心狠手辣了...


于是乎,我在onXWalkReady()方法中写了walkView.setZOrderOnTop(true)

跑一下,完美~~~



可是,为什么呢?

打log,观察到,除了XWalkView中有SurfaceView,在XWalkView内部中的XWalkContent这个对象也有一个SurfaceView对象,

当时就觉得...哇~~~果然如我只所料,不是一个SurfaceView在闹腾啊

多次运行,打log发现,首次进入的时候,用XWalkView中的SurfaceView渲染数据,之后用XWalkContent中的SurfaceView渲染数据,

这也就合理的解释了,为什么会有"只有第一次可以"和"只有第一次不可以"两种情况了



特此记录,







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章