PopupWindow 在 Android N(7.0) 的兼容性问题

转载 http://www.jianshu.com/p/0df10893bf5b,并在此基础上完善了下

packagecn.kidyn.qdmedical160.view;

importandroid.content.Context;

importandroid.os.Build;

importandroid.text.TextUtils;

importandroid.util.AttributeSet;

importandroid.view.Gravity;

importandroid.view.View;

importandroid.view.WindowManager;

importandroid.widget.PopupWindow;

importjava.lang.reflect.Field;

importjava.lang.reflect.Method;

/**

* Fix 7.0 showLocation,showAsDropDown兼容问题

* Created by qulj on 2017/4/10.

*/

public classFixedPopupWindowextendsPopupWindow{

publicFixedPopupWindow(Contextcontext) {

super(context);

}

publicFixedPopupWindow(Contextcontext,AttributeSetattrs) {

super(context,attrs);

}

publicFixedPopupWindow(Contextcontext,AttributeSetattrs,intdefStyle) {

super(context,attrs,defStyle);

}

publicFixedPopupWindow(Contextcontext,AttributeSetattrs,intdefStyleAttr,intdefStyleRes) {

super(context,attrs,defStyleAttr,defStyleRes);

}

publicFixedPopupWindow(ViewcontentView) {

super(contentView);

}

publicFixedPopupWindow() {

super();

}

publicFixedPopupWindow(intwidth,intheight) {

super(width,height);

}

publicFixedPopupWindow(ViewcontentView,intwidth,intheight,booleanfocusable) {

super(contentView,width,height,focusable);

}

publicFixedPopupWindow(ViewcontentView,intwidth,intheight) {

super(contentView,width,height);

}

@Override

public voidupdate(intx,inty,intwidth,intheight,booleanforce) {

if(Build.VERSION.SDK_INT!=24) {

super.update(x,y,width,height,force);

return;

}

if(width>=0) {

setParam("mLastWidth",width);

setWidth(width);

}

if(height>=0) {

setParam("mLastHeight",height);

setHeight(height);

}

Objectobj=getParam("mContentView");

ViewmContentView=null;

if(objinstanceofView) {

mContentView= (View)obj;

}

if(!isShowing() ||mContentView==null) {

return;

}

obj=getParam("mDecorView");

ViewmDecorView=null;

if(objinstanceofView) {

mDecorView= (View)obj;

}

finalWindowManager.LayoutParamsp=

(WindowManager.LayoutParams)mDecorView.getLayoutParams();

booleanupdate=force;

obj=getParam("mWidthMode");

intmWidthMode=obj!=null? (Integer)obj:0;

obj=getParam("mLastWidth");

intmLastWidth=obj!=null? (Integer)obj:0;

final intfinalWidth=mWidthMode<0?mWidthMode:mLastWidth;

if(width!= -1&&p.width!=finalWidth) {

p.width=finalWidth;

setParam("mLastWidth",finalWidth);

update=true;

}

obj=getParam("mHeightMode");

intmHeightMode=obj!=null? (Integer)obj:0;

obj=getParam("mLastHeight");

intmLastHeight=obj!=null? (Integer)obj:0;

final intfinalHeight=mHeightMode<0?mHeightMode:mLastHeight;

if(height!= -1&&p.height!=finalHeight) {

p.height=finalHeight;

setParam("mLastHeight",finalHeight);

update=true;

}

if(p.x!=x) {

p.x=x;

update=true;

}

if(p.y!=y) {

p.y=y;

update=true;

}

//        obj = execMethod("computeAnimationResource");

obj=execMethod("computeAnimationResource",newClass[]{int.class},null);

final intnewAnim=obj==null?0: (Integer)obj;

if(newAnim!=p.windowAnimations) {

p.windowAnimations=newAnim;

update=true;

}

obj=execMethod("computeFlags",newClass[]{int.class},newObject[]{p.flags});

final intnewFlags=obj==null?0: (Integer)obj;

if(newFlags!=p.flags) {

p.flags=newFlags;

update=true;

}

if(update) {

execMethod("setLayoutDirectionFromAnchor",null,null);

obj=getParam("mWindowManager");

WindowManagermWindowManager=objinstanceofWindowManager? (WindowManager)obj:null;

if(mWindowManager!=null) {

mWindowManager.updateViewLayout(mDecorView,p);

}

}

}

/**

*反射获取对象

*@paramparamName

*@return

*/

privateObject getParam(StringparamName) {

if(TextUtils.isEmpty(paramName)) {

return null;

}

try{

Fieldfield=PopupWindow.class.getDeclaredField(paramName);

field.setAccessible(true);

returnfield.get(this);

}catch(Exceptione) {

e.printStackTrace();

}

return null;

}

/**

*反射赋值对象

*@paramparamName

*@paramobj

*/

private voidsetParam(StringparamName,Objectobj) {

if(TextUtils.isEmpty(paramName)) {

return;

}

try{

Fieldfield=PopupWindow.class.getDeclaredField(paramName);

field.setAccessible(true);

field.set(this,obj);

}catch(Exceptione) {

e.printStackTrace();

}

}

/**

*反射执行方法

*@parammethodName

*@paramargs

*@return

*/

privateObject execMethod(StringmethodName,Class[]cls,Object[]args) {

if(TextUtils.isEmpty(methodName)) {

return null;

}

try{

Methodmethod=getMethod(PopupWindow.class,methodName,cls);

method.setAccessible(true);

returnmethod.invoke(this,args);

}catch(Exceptione) {

e.printStackTrace();

}

return null;

}

/**

*利用递归找一个类的指定方法,如果找不到,去父亲里面找直到最上层Object对象为止。

*

*@paramclazz

*目标类

*@parammethodName

*方法名

*@paramclasses

*方法参数类型数组

*@return方法对象

*@throwsException

*/

privateMethod getMethod(Classclazz,StringmethodName,

finalClass[]classes)throwsException{

Methodmethod=null;

try{

method=clazz.getDeclaredMethod(methodName,classes);

}catch(NoSuchMethodExceptione) {

try{

method=clazz.getMethod(methodName,classes);

}catch(NoSuchMethodExceptionex) {

if(clazz.getSuperclass() ==null) {

returnmethod;

}else{

method=getMethod(clazz.getSuperclass(),methodName,

classes);

}

}

}

returnmethod;

}

@Override

public voidshowAsDropDown(ViewanchorView) {

if(Build.VERSION.SDK_INT==24) {

int[]a=new int[2];

anchorView.getLocationInWindow(a);

showAtLocation(anchorView,Gravity.NO_GRAVITY,0,a[1] +anchorView.getHeight() +0);

}else{

super.showAsDropDown(anchorView);

}

}

}

你可能感兴趣的:(PopupWindow 在 Android N(7.0) 的兼容性问题)