转载 //www.greatytc.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);
}
}
}