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

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

2017-01-16 20:07 453 查看

背景

前期做项目实现了一个自定义键盘的控件,主要是通过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系统以下使用,所以不再调用此方法
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息