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系统以下使用,所以不再调用此方法
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值