PopupWindow工具类封装
我们这次来对PopupWindow来进行封装,使用Builder模式。
我们先来看我们要注意哪些因素要考虑:
- contentView ,这里有二种可能,一是用户只是传了R.layout.xxx进来,二是用户传了具体的View对象进来。
- PopupWindow的宽和高。 (可能需要传入Px值,可能是dp值,可能是R.dimen.xxx值,如果不传入,就默认为Wrap_Content,也就是会显示你传入的contentView的宽高)
- 是否需要显示动画,如果需要显示动画,那么具体的style参数
- focusable,touchable 的设置
- 是否设置点击外部让PopupWindow消失
- 设置里面的某个View的点击事件
PopuWindow在安卓7布局大小兼容问题的处理
在android7.0上,如果不主动约束PopuWindow的大小,
比如,设置布局大小为 MATCH_PARENT,那么PopuWindow会变得尽可能大,以至于 view下方无空间完全显示PopuWindow,而且view又无法向上滚动,此时PopuWindow会主动上移位置,直到可以显示完全。
解决办法:主动约束PopuWindow的内容大小,重写showAsDropDown方法:
所以初步我们可以写成这样:
public class CustomPopupWindow extends PopupWindow {
private CustomPopupWindow(Builder builder) {
super(builder.context);
builder.view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
setContentView(builder.view);
setHeight(builder.height == 0?ViewGroup.LayoutParams.WRAP_CONTENT:builder.height);
setWidth(builder.width == 0?ViewGroup.LayoutParams.WRAP_CONTENT:builder.width);
if (builder.cancelTouchout) {
setBackgroundDrawable(new ColorDrawable(0x00000000));//设置透明背景
setOutsideTouchable(builder.cancelTouchout);//设置outside可点击
}
setFocusable(builder.isFocusable);
setTouchable(builder.isTouchable);
if(builder.animStyle != 0){
setAnimationStyle(builder.animStyle);
}
}
public static final class Builder {
private Context context;
private int height, width;
private boolean cancelTouchout;
private boolean isFocusable = true;
private boolean isTouchable = true;
private View view;
private int animStyle;
public Builder(Context context) {
this.context = context;
}
public Builder view(int resView) {
view = LayoutInflater.from(context).inflate(resView, null);
return this;
}
public Builder view(View resVew){
view = resVew;
return this;
}
public Builder heightpx(int val) {
height = val;
return this;
}
public Builder widthpx(int val) {
width = val;
return this;
}
public Builder heightdp(int val) {
height = dip2px(context, val);
return this;
}
public Builder widthdp(int val) {
width = dip2px(context, val);
return this;
}
public Builder heightDimenRes(int dimenRes) {
height = context.getResources().getDimensionPixelOffset(dimenRes);
return this;
}
public Builder widthDimenRes(int dimenRes) {
width = context.getResources().getDimensionPixelOffset(dimenRes);
return this;
}
public Builder cancelTouchout(boolean val) {
cancelTouchout = val;
return this;
}
public Builder isFocusable(boolean val) {
isFocusable = val;
return this;
}
public Builder isTouchable(boolean val) {
isTouchable = val;
return this;
}
public Builder animStyle(int val){
animStyle = val;
return this;
}
public Builder addViewOnclick(int viewRes, View.OnClickListener listener) {
view.findViewById(viewRes).setOnClickListener(listener);
return this;
}
public CustomPopupWindow build() {
return new CustomPopupWindow(this);
}
}
@Override
public int getWidth() {
return getContentView().getMeasuredWidth();
}
/**
* PopuWindow在安卓7布局大小兼容问题的处理
* 在android7.0上,如果不主动约束PopuWindow的大小,比如,设置布局大小为 MATCH_PARENT,那么PopuWindow会变得尽可能大,
* 以至于 view下方无空间完全显示PopuWindow,而且view又无法向上滚动,此时PopuWindow会主动上移位置,直到可以显示完全。
* 解决办法:主动约束PopuWindow的内容大小,重写showAsDropDown方法:
* @param anchor
*/
@Override
public void showAsDropDown(View anchor) {
if (Build.VERSION.SDK_INT >= 24){
Rect visibleFrame = new Rect();
anchor.getGlobalVisibleRect(visibleFrame);
int height = anchor.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom;
setHeight(height);
}
super.showAsDropDown(anchor);
}
@Override
public void showAsDropDown(View anchor, int xoff, int yoff) {
if (Build.VERSION.SDK_INT >= 24) {
Rect visibleFrame = new Rect();
anchor.getGlobalVisibleRect(visibleFrame);
int height = anchor.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom;
setHeight(height);
}
super.showAsDropDown(anchor,xoff,yoff);
}
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}
。。。