日常开发中或多或少都会使用到PopupWindow,每次都需要自定义继承至PopupWindow的view,写多了不胜其烦,今天我们对PopupWindow做个封装,可通过链式构建,支持View方式或ViewDataBinding方式设置ContentView(类似的封装可看我的另外一篇文章Android通用Dialog的封装)。  先看使用示例:
1、通过View的方式构建,这里的SortingFilterLayout是我们自定义的一个View
new CommonPopupWindow.ViewBuilder<SortingFilterLayout>()
.width(ConstraintLayout.LayoutParams.WRAP_CONTENT)
.height(ConstraintLayout.LayoutParams.WRAP_CONTENT)
.outsideTouchable(true)
.focusable(true)
.animationStyle(R.style.sorting_filter_pop_animation)
.clippingEnabled(false)
.alpha(0.618f)
.view(new SortingFilterLayout(context))
.intercept(new CommonPopupWindow.ViewEvent<SortingFilterLayout>() {
@Override
public void getView(CommonPopupWindow commonPopupWindow, SortingFilterLayout view) {
}
})
.onShowBefore(new CommonPopupWindow.OnShowBefore<SortingFilterLayout>() {
@Override
public void showBefore(CommonPopupWindow popupWindow, SortingFilterLayout view) {
}
})
.onDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
}
})
.build(context)
.showAtLocation(view, Gravity.RIGHT, 0, 0);
2、通过ViewDataBinding的方式构建,这里的layout_sorting_filter是我们自定义View的xml文件,LayoutSortingFilterBinding是对应的ViewDataBinding
new CommonPopupWindow.ViewDataBindingBuilder<LayoutSortingFilterBinding>()
.width(ConstraintLayout.LayoutParams.WRAP_CONTENT)
.height(ConstraintLayout.LayoutParams.WRAP_CONTENT)
.outsideTouchable(true)
.focusable(true)
.animationStyle(R.style.sorting_filter_pop_animation)
.clippingEnabled(false)
.alpha(0.618f)
.layoutId(mRootView.getActivity(),R.layout.layout_sorting_filter)
.intercept(new CommonPopupWindow.ViewEvent<LayoutSortingFilterBinding>() {
@Override
public void getView(CommonPopupWindow commonPopupWindow, LayoutSortingFilterBinding binding) {
}
})
.onShowBefore(new CommonPopupWindow.OnShowBefore<LayoutSortingFilterBinding>() {
@Override
public void showBefore(CommonPopupWindow popupWindow, LayoutSortingFilterBinding binding) {
}
})
.onDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
}
})
.build(context)
.showAtLocation(view,Gravity.RIGHT,0,0);
 CommonPopupWindow完整的代码如下:
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
public abstract class CommonPopupWindow<V extends View, Binding extends ViewDataBinding> extends PopupWindow {
private OnDismissListener onDismissListener;
private CommonPopupWindow(Context context, ViewDataBindingBuilder<Binding> builder) {
super(context);
getIntercept().intercept();
setContentView(builder.mBinding.getRoot());
setWidth(builder.mWidth);
setHeight(builder.mHeight);
setOutsideTouchable(builder.mOutsideTouchable);
setBackgroundDrawable(builder.mBackground);
setFocusable(builder.mFocusable);
setClippingEnabled(builder.mClippingEnabled);
setAnimationStyle(builder.mAnimationStyle);
onDismissListener = builder.onDismissListener;
super.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
if (context instanceof Activity) {
WindowManager.LayoutParams lp = ((Activity) context).getWindow().getAttributes();
if (lp != null && lp.alpha != 1.0f) {
lp.alpha = 1.0f;
((Activity) context).getWindow().setAttributes(lp);
}
}
if (onDismissListener != null) {
onDismissListener.onDismiss();
}
if (builder.mBinding != null) {
builder.mBinding.unbind();
}
}
});
}
private CommonPopupWindow(Context context, ViewBuilder<V> builder) {
super(context);
getIntercept().intercept();
setContentView(builder.view);
setWidth(builder.mWidth);
setHeight(builder.mHeight);
setOutsideTouchable(builder.mOutsideTouchable);
setBackgroundDrawable(builder.mBackground);
setFocusable(builder.mFocusable);
setClippingEnabled(builder.mClippingEnabled);
setAnimationStyle(builder.mAnimationStyle);
onDismissListener = builder.onDismissListener;
super.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
if (context instanceof Activity) {
WindowManager.LayoutParams lp = ((Activity) context).getWindow().getAttributes();
if (lp != null && lp.alpha != 1.0f) {
lp.alpha = 1.0f;
((Activity) context).getWindow().setAttributes(lp);
}
}
if (onDismissListener != null) {
onDismissListener.onDismiss();
}
}
});
}
@Override
public void showAsDropDown(View anchor, int xoff, int yoff) {
if (getContentView() != null) {
Context context = getContentView().getContext();
if (context instanceof Activity) {
WindowManager.LayoutParams lp = ((Activity) context).getWindow().getAttributes();
if (lp != null && lp.alpha != getAlpha()) {
lp.alpha = getAlpha();
((Activity) context).getWindow().setAttributes(lp);
}
}
}
getIntercept().showBefore();
super.showAsDropDown(anchor, xoff, yoff);
getIntercept().showAfter();
}
@Override
public void showAtLocation(View parent, int gravity, int x, int y) {
if (getContentView() != null) {
Context context = getContentView().getContext();
if (context instanceof Activity) {
WindowManager.LayoutParams lp = ((Activity) context).getWindow().getAttributes();
if (lp != null && lp.alpha != getAlpha()) {
lp.alpha = getAlpha();
((Activity) context).getWindow().setAttributes(lp);
}
}
}
getIntercept().showBefore();
super.showAtLocation(parent, gravity, x, y);
getIntercept().showAfter();
}
@Override
public void setOnDismissListener(OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
}
abstract float getAlpha();
abstract CommonPopupWindow getInstance();
abstract InterceptTransform getIntercept();
public static class ViewDataBindingBuilder<Binding extends ViewDataBinding> {
private Binding mBinding;
private int mWidth;
private int mHeight;
private boolean mOutsideTouchable;
private ViewEvent<Binding> mEvent;
private Drawable mBackground;
private boolean mFocusable;
private float alpha = 1.0f;
private boolean mClippingEnabled = true;
private OnShowBefore<Binding> mOnShowBefore;
private OnShowAfter<Binding> mOnShowAfter;
private int mAnimationStyle = -1;
private OnDismissListener onDismissListener;
public ViewDataBindingBuilder<Binding> layoutId(Context context, int layoutId) {
this.mBinding = DataBindingUtil.inflate(LayoutInflater.from(context), layoutId, null, false);
return this;
}
public ViewDataBindingBuilder<Binding> viewDataBinding(Binding mBinding) {
this.mBinding = mBinding;
return this;
}
public ViewDataBindingBuilder<Binding> width(int width) {
this.mWidth = width;
return this;
}
public ViewDataBindingBuilder<Binding> height(int height) {
this.mHeight = height;
return this;
}
public ViewDataBindingBuilder<Binding> outsideTouchable(boolean outsideTouchable) {
this.mOutsideTouchable = outsideTouchable;
return this;
}
public ViewDataBindingBuilder<Binding> backgroundDrawable(Drawable background) {
this.mBackground = background;
return this;
}
public ViewDataBindingBuilder<Binding> focusable(boolean focusable) {
this.mFocusable = focusable;
return this;
}
public ViewDataBindingBuilder<Binding> alpha(float alpha) {
this.alpha = alpha;
return this;
}
public ViewDataBindingBuilder<Binding> clippingEnabled(boolean clippingEnabled) {
this.mClippingEnabled = clippingEnabled;
return this;
}
public ViewDataBindingBuilder<Binding> onShowBefore(OnShowBefore<Binding> showBefore) {
this.mOnShowBefore = showBefore;
return this;
}
public ViewDataBindingBuilder<Binding> onShowAfter(OnShowAfter<Binding> showAfter) {
this.mOnShowAfter = showAfter;
return this;
}
public ViewDataBindingBuilder<Binding> animationStyle(int animationStyle) {
this.mAnimationStyle = animationStyle;
return this;
}
public ViewDataBindingBuilder<Binding> intercept(ViewEvent<Binding> event) {
this.mEvent = event;
return this;
}
public ViewDataBindingBuilder<Binding> onDismissListener(OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
return this;
}
public <V extends View> CommonPopupWindow<V, Binding> build(Context context) {
return new CommonPopupWindow<V, Binding>(context, this) {
@Override
public float getAlpha() {
return alpha;
}
@Override
CommonPopupWindow getInstance() {
return this;
}
@Override
InterceptTransform getIntercept() {
return new InterceptTransform<Binding>() {
@Override
public void showBefore() {
if (mOnShowBefore != null) {
mOnShowBefore.showBefore(getInstance(), mBinding);
}
}
@Override
public void showAfter() {
if (mOnShowAfter != null) {
mOnShowAfter.showAfter(getInstance(), mBinding);
}
}
@Override
public void intercept() {
if (mEvent != null) {
mEvent.getView(getInstance(), mBinding);
}
}
};
}
};
}
}
public static class ViewBuilder<V extends View> {
private V view;
private int mWidth;
private int mHeight;
private boolean mOutsideTouchable;
private ViewEvent<V> mEvent;
private Drawable mBackground;
private boolean mFocusable;
private float alpha = 1.0f;
private boolean mClippingEnabled = true;
private OnShowBefore<V> mOnShowBefore;
private OnShowAfter<V> mOnShowAfter;
private int mAnimationStyle = -1;
private OnDismissListener onDismissListener;
public ViewBuilder<V> view(@NonNull V view) {
this.view = view;
return this;
}
public ViewBuilder<V> width(int width) {
this.mWidth = width;
return this;
}
public ViewBuilder<V> height(int height) {
this.mHeight = height;
return this;
}
public ViewBuilder<V> outsideTouchable(boolean outsideTouchable) {
this.mOutsideTouchable = outsideTouchable;
return this;
}
public ViewBuilder<V> backgroundDrawable(Drawable background) {
this.mBackground = background;
return this;
}
public ViewBuilder<V> focusable(boolean focusable) {
this.mFocusable = focusable;
return this;
}
public ViewBuilder<V> alpha(float alpha) {
this.alpha = alpha;
return this;
}
public ViewBuilder<V> clippingEnabled(boolean clippingEnabled) {
this.mClippingEnabled = clippingEnabled;
return this;
}
public ViewBuilder<V> onShowBefore(OnShowBefore<V> showBefore) {
this.mOnShowBefore = showBefore;
return this;
}
public ViewBuilder<V> onShowAfter(OnShowAfter<V> showAfter) {
this.mOnShowAfter = showAfter;
return this;
}
public ViewBuilder<V> animationStyle(int animationStyle) {
this.mAnimationStyle = animationStyle;
return this;
}
public ViewBuilder<V> intercept(ViewEvent<V> event) {
this.mEvent = event;
return this;
}
public ViewBuilder<V> onDismissListener(OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
return this;
}
public <T extends ViewDataBinding> CommonPopupWindow<V, T> build(Context context) {
return new CommonPopupWindow<V, T>(context, this) {
@Override
public float getAlpha() {
return alpha;
}
@Override
CommonPopupWindow getInstance() {
return this;
}
@Override
InterceptTransform getIntercept() {
return new InterceptTransform<V>() {
@Override
public void showBefore() {
if (mOnShowBefore != null) {
mOnShowBefore.showBefore(getInstance(), view);
}
}
@Override
public void showAfter() {
if (mOnShowAfter != null) {
mOnShowAfter.showAfter(getInstance(), view);
}
}
@Override
public void intercept() {
if (mEvent != null) {
mEvent.getView(getInstance(), view);
}
}
};
}
};
}
}
public interface ViewEvent<T> {
void getView(CommonPopupWindow popupWindow, T view);
}
public static abstract class InterceptTransform<V> {
public abstract void showBefore();
public abstract void showAfter();
public abstract void intercept();
}
public interface OnShowBefore<V> {
void showBefore(CommonPopupWindow popupWindow, V view);
}
public interface OnShowAfter<V> {
void showAfter(CommonPopupWindow popupWindow, V view);
}
}
代码的注释比较清晰,就不做过多说明了,有疑问的朋友欢迎在评论区留言。  搞定,收工。
希望本文可以帮助到您,也希望各位不吝赐教,提出您在使用中的宝贵意见,谢谢。
如果可以的话,也可以扫一扫下方的二维码请作者喝一杯奶茶哈  谢谢您的观看。 有问题可发送至:1966353889@qq.com 欢迎交流,共同进步。
|