Android:使用PopupWindow.update( )碰到的坑

背景

前期做项目实现了一个自定义键盘的控件,主要是通过extends PopupWindow来实现,后期我会考虑把这个自定义键盘开源,敬请关注。其中用到了PopupWindow.update( )方法,在Android7.0正式发布前,即在Android7.0以下的系统上没有问题,最近Android7.0的手机已经陆续进入市场。

就在这几天,有同事反应我们项目里面那个自定义键盘原来在界面底部,是正常,但是在Android7.0系统上就跑到界面顶部了,不正常了。

如下图,第1张图是不正常的,第2张图是正常的。

这里写图片描述

这里写图片描述

原因

1.自定义键盘的布局。初步从自定义键盘的布局入手,检查是否由布局引起,经过再三调试发现,布局没有问题。
2.断点调试。

public void show(View parent){
   if (parent != null) {
      mPopupWindow.showAtLocation(parent, Gravity.BOTTOM, 0, 0);
   }
   mPopupWindow.update();
}

调试这个方法,发现问题出在PopupWindow.update( )这里。
PopupWindow.update( )是做什么的呢?查看源码,系统解释是:

Updates the state of the popup window, if it is currently being displayed,from the currently set state.

中文意思:更新PopupWindow状态,如果当前已是显示状态,就从当前状态更新。
Android7.0以下的系统:

public void update() {
    if (!isShowing() || mContentView == null) {
        return;
    }

    WindowManager.LayoutParams p = (WindowManager.LayoutParams)
         mPopupView.getLayoutParams();

    boolean update = false;

    final int newAnim = computeAnimationResource();
    if (newAnim != p.windowAnimations) {
        p.windowAnimations = newAnim;
        update = true;
    }

    final int newFlags = computeFlags(p.flags);
    if (newFlags != p.flags) {
        p.flags = newFlags;
        update = true;
    }

    if (update) {
        setLayoutDirectionFromAnchor();
        mWindowManager.updateViewLayout(mPopupView, p);
    }
}

Android7.0系统:

public void update() {
    if (!isShowing() || mContentView == null) {
        return;
    }

    final WindowManager.LayoutParams p = (WindowManager.LayoutParams)     mDecorView.getLayoutParams();

    boolean update = false;

    final int newAnim = computeAnimationResource();
    if (newAnim != p.windowAnimations) {
        p.windowAnimations = newAnim;
        update = true;
    }

    final int newFlags = computeFlags(p.flags);
    if (newFlags != p.flags) {
        p.flags = newFlags;
        update = true;
    }

    final int newGravity = computeGravity();
    if (newGravity != p.gravity) {
        p.gravity = newGravity;
        update = true;
    }

    if (update) {
        setLayoutDirectionFromAnchor();
        mWindowManager.updateViewLayout(mDecorView, p);
    }
}

经过对比发现,主要区别是下面这段代码:

final int newGravity = computeGravity();
if (newGravity != p.gravity) {
    p.gravity = newGravity;
    update = true;
}

接下来我们再看computeGravity()这个方法

private int computeGravity() {
   int gravity = Gravity.START | Gravity.TOP;
   if (mClipToScreen || mClippingEnabled) {
       gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
   }
   return gravity;
}

在computeGravity()这个方法可以看出,在Android7.0系统上,调用PopupWindow.update( )方法会导致PopupWindow的位置出现在界面顶部,而不是我们自己定义的位置,如:界面底部。

解决办法

PopupWindow.update( )在自定义键盘根本没有起到实质作用,注释掉即可。如下:

public void show(View parent){
    if (parent != null) {
        mPopupWindow.showAtLocation(parent, Gravity.BOTTOM, 0, 0);
    }
// mPopupWindow.update(); //因android7.0此方法有改动,不适用android7.0系统以下使用,所以不再调用此方法
}

猜你喜欢

转载自blog.csdn.net/weiren1101/article/details/54577025
今日推荐