**
Update 2023/06/26
**
修复上下文被静态变量引用,导致内存泄漏
**
/**
* Synopsis ${SYNOPSIS}
* Author Mosr
* Version ${VERSION}
* Create 2017/11/7 16:06
* Modify 2018/10/18 17:32
* Email intimatestranger@sina.cn
*/
public class PopupWindowManager {
private static volatile PopupWindowManager mPopupWindowManager;
private PopupWindow mPopupWindow;
private WeakReference<Context> mContext;
private boolean bOverLayerEnable;
private WeakReference<View> mOverView;
private WindowManager mWindowManager;
private static final WeakHandler mWeakHandler = new WeakHandler();
private final PopupWindow.OnDismissListener mOnDismissListener = new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if (bOverLayerEnable) {
removeMask();
}
}
};
public static PopupWindowManager getInstance() {
if (null == mPopupWindowManager) {
synchronized (PopupWindowManager.class) {
if (null == mPopupWindowManager) {
mPopupWindowManager = new PopupWindowManager();
}
}
}
//非正常情况处理
if (null != mWeakHandler) {
mWeakHandler
.setPopupWindowManager(mPopupWindowManager)
.obtainMessage(MSG_DISMISS);
}
return mPopupWindowManager;
}
public PopupWindow getPopupWindow() {
if (null == mPopupWindow)
mPopupWindow = new PopupWindow();
mPopupWindow.setOnDismissListener(mOnDismissListener);
return mPopupWindow;
}
public PopupWindowManager mBinding(@NonNull Context mContext) {
if (null == mContext) {
throw new IllegalArgumentException("Context can't be null!");
}
mBinding(mContext, true);
return mPopupWindowManager;
}
public PopupWindowManager mBinding(Context mContext, boolean bOverLayerEnable) {
this.mContext = new WeakReference<>(mContext);
this.bOverLayerEnable = bOverLayerEnable;
return mPopupWindowManager;
}
/**
* 必须设置,否则pop无法填充满整个屏幕
*
* @param background
* @return
*/
public PopupWindowManager mBackground(Drawable background) {
getPopupWindow().setBackgroundDrawable(background);
return mPopupWindowManager;
}
public PopupWindowManager mAnimationStyle(int animationStyle) {
getPopupWindow().setAnimationStyle(animationStyle);
return mPopupWindowManager;
}
public PopupWindowManager mLoadView(int layoutID) {
if (0 == layoutID)
throw new IllegalArgumentException("This layoutID is invalid!");
View contentView = null;
if (null != mContext && null != mContext.get())
contentView = LayoutInflater.from(mContext.get()).inflate(layoutID, null);
if (null == contentView)
throw new RuntimeException("This layout can't be load!");
getPopupWindow().setContentView(contentView);
return mPopupWindowManager;
}
public PopupWindowManager mLoadView(int layoutID, int iTitleResID, String title) {
if (0 == layoutID)
throw new IllegalArgumentException("This layoutID is invalid!");
View contentView = null;
if (null != mContext && null != mContext.get())
contentView = LayoutInflater.from(mContext.get()).inflate(layoutID, null);
if (null == contentView)
throw new RuntimeException("This layout can't be load!");
View mTitleView = contentView.findViewById(iTitleResID);
TextView red_title = mTitleView instanceof TextView ? (TextView) mTitleView : null;
if (null != red_title && !TextUtils.isEmpty(title))
red_title.setText(title);
getPopupWindow().setContentView(contentView);
return mPopupWindowManager;
}
public PopupWindowManager mWidthHeight(int width, int height) {
getPopupWindow().setWidth(width);
getPopupWindow().setHeight(height);
return mPopupWindowManager;
}
public PopupWindowManager mFocusable(boolean able) {
getPopupWindow().setFocusable(able);
return mPopupWindowManager;
}
public PopupWindowManager mTouchable(boolean able) {
getPopupWindow().setTouchable(able);
return mPopupWindowManager;
}
public PopupWindowManager mOutsideTouchable(final boolean able) {
getPopupWindow().setOutsideTouchable(able);
getPopupWindow().setTouchInterceptor(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
if (!getPopupWindow().isOutsideTouchable()) {
View mView = getPopupWindow().getContentView();
if (null != mView)
mView.dispatchTouchEvent(event);
}
return getPopupWindow().isFocusable() && !getPopupWindow().isOutsideTouchable();
}
});
return mPopupWindowManager;
}
public PopupWindowManager mSoftInputMode(int mode) {
getPopupWindow().setSoftInputMode(mode);
return mPopupWindowManager;
}
public <T extends View> PopupWindowManager mViewAction(int mViewID, ViewAction<T> mViewAction) {
View mContentView = getPopupWindow().getContentView();
if (null != mContentView) {
View mView = mContentView.findViewById(mViewID);
if (null != mView)
mViewAction.action(mPopupWindowManager, (T) mView);
}
return mPopupWindowManager;
}
public <T extends View> PopupWindowManager mViewActions(ViewActions<T> mViewActions, Integer... mViewIDs) {
View mContentView = getPopupWindow().getContentView();
if (null != mContentView) {
for (int mViewID : mViewIDs) {
View mView = mContentView.findViewById(mViewID);
mViewActions.action(null != mView ? (T) mView : null, mViewID);
}
}
return mPopupWindowManager;
}
public PopupWindowManager mCheckAction(int mViewID, final PopupAction mPopupAction) {
final View mContentView = getPopupWindow().getContentView();
if (null != mContentView) {
View mView = mContentView.findViewById(mViewID);
if (null != mView && mView instanceof RadioGroup)
((RadioGroup) mView).setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
mPopupAction.action(getPopupWindow(), mContentView, group, checkedId);
}
});
}
return mPopupWindowManager;
}
public PopupWindowManager mClickAction(int mViewID, final PopupAction mPopupAction) {
final View mContentView = getPopupWindow().getContentView();
if (null != mContentView) {
View mView = mContentView.findViewById(mViewID);
if (null != mView)
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPopupAction.action(getPopupWindow(), mContentView, null, -1);
}
});
}
return mPopupWindowManager;
}
public void mShowAtLocation(View parent, int gravity, int x, int y) {
if (getPopupWindow().isShowing()) {
return;
}
if (null != parent && null != parent.getContext() && parent.isShown()) {
if (bOverLayerEnable) {
addOverLayer(parent.getWindowToken());
}
getPopupWindow().showAtLocation(parent, gravity, x, y);
}
}
public void mShowAsDropDown(View parent) {
if (getPopupWindow().isShowing()) {
return;
}
if (null != parent && null != parent.getContext() && parent.isShown()) {
if (bOverLayerEnable) {
addOverLayer(parent.getWindowToken());
}
getPopupWindow().showAsDropDown(parent);
}
}
public void mShowAsDropDown(View parent, int xoff, int yoff) {
if (getPopupWindow().isShowing()) {
return;
}
if (null != parent && null != parent.getContext() && parent.isShown()) {
if (bOverLayerEnable) {
addOverLayer(parent.getWindowToken());
}
getPopupWindow().showAsDropDown(parent, xoff, yoff);
}
}
public void mShowAsDropDown(View parent, int xoff, int yoff, int gravity) {
if (getPopupWindow().isShowing()) {
return;
}
if (null != parent && null != parent.getContext() && parent.isShown()) {
if (bOverLayerEnable) {
addOverLayer(parent.getWindowToken());
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getPopupWindow().showAsDropDown(parent, xoff, yoff, gravity);
}
}
}
public void mShowAsDropDownWithBottomOverLayer(View parent) {
if (getPopupWindow().isShowing()) {
return;
}
if (null != parent && null != parent.getContext() && parent.isShown()) {
if (bOverLayerEnable) {
addBottomOverLayer(parent);
}
getPopupWindow().showAsDropDown(parent);
}
}
public PopupWindowManager mDisMissListener(PopupWindow.OnDismissListener mOnDismissListener) {
getPopupWindow().setOnDismissListener(mOnDismissListener);
return mPopupWindowManager;
}
public PopupWindowManager mDisMissAction(int mViewID) {
View mContentView = getPopupWindow().getContentView();
if (null != mContentView) {
View mView = mContentView.findViewById(mViewID);
if (null != mView)
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDismiss();
}
});
}
return mPopupWindowManager;
}
public PopupWindowManager mDisMissAction(View mView) {
if (null != mView)
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDismiss();
}
});
return mPopupWindowManager;
}
private void mDismiss() {
if (null != getPopupWindow() && getPopupWindow().isShowing()) {
getPopupWindow().dismiss();
}
}
public interface PopupAction {
void action(PopupWindow mPopupWindow, @Nullable View mContentView, @Nullable RadioGroup group, int checkedId);
}
public interface ViewAction<T extends View> {
void action(PopupWindowManager mPopupWindowManager, T mView);
}
public interface ViewActions<T extends View> {
void action(T mView, int mViewId);
}
private void addBottomOverLayer(View mView) {
if (null == mContext || null == mContext.get()) return;
mWindowManager = (WindowManager) mContext.get().getSystemService(Context.WINDOW_SERVICE);
if (null == mWindowManager) {
return;
}
int windowHeight = mWindowManager.getDefaultDisplay().getHeight();
int[] location = new int[2];
mView.getLocationInWindow(location);
int height = mView.getMeasuredHeight();
WindowManager.LayoutParams wl = new WindowManager.LayoutParams();
wl.width = WindowManager.LayoutParams.MATCH_PARENT;
wl.height = windowHeight - location[1] - height;
wl.format = PixelFormat.TRANSLUCENT;
wl.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
wl.token = mView.getWindowToken();
wl.gravity = Gravity.BOTTOM;
if (null == mContext || null == mContext.get()) return;
mOverView = new WeakReference<>(new View(mContext.get()));
mOverView.get().setBackgroundColor(0x99000000);
mOverView.get().setFitsSystemWindows(true);
mOverView.get().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
removeMask();
return true;
}
return false;
}
});
mWindowManager.addView(mOverView.get(), wl);
}
private void addOverLayer(IBinder token) {
if (null == mContext || null == mContext.get()) return;
mWindowManager = (WindowManager) mContext.get().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams wl = new WindowManager.LayoutParams();
wl.width = WindowManager.LayoutParams.MATCH_PARENT;
wl.height = WindowManager.LayoutParams.MATCH_PARENT;
wl.format = PixelFormat.TRANSLUCENT;
wl.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
wl.token = token;
if (null == mContext || null == mContext.get()) return;
mOverView = new WeakReference<>(new View(mContext.get()));
mOverView.get().setBackgroundColor(0x99000000);
mOverView.get().setFitsSystemWindows(true);
mOverView.get().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
removeMask();
return true;
}
return false;
}
});
mWindowManager.addView(mOverView.get(), wl);
}
private void removeMask() {
if (null != mOverView && null != mOverView.get()) {
mWindowManager.removeViewImmediate(mOverView.get());
mWindowManager = null;
mOverView = null;
}
}
private static final int MSG_DISMISS = 0x1001;
private static class WeakHandler extends Handler {
private WeakReference<PopupWindowManager> mPopupWindowManager;
public WeakHandler setPopupWindowManager(PopupWindowManager nPopupWindowManager) {
mPopupWindowManager = new WeakReference<>(nPopupWindowManager);
return this;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (null != msg && msg.what == MSG_DISMISS) {
if (null != mPopupWindowManager && null != mPopupWindowManager.get())
mPopupWindowManager.get().mDismiss();
}
}
}
}
**
Using
**
PopupwindowUtil .getInstance(getContext())
.mLoadView(R.layout.layout_reward_popupwindow)
.mBackground(new BitmapDrawable())
.mAnimationStyle(R.style.popupwindow_fade)
.mFocusable(true)
.mOutsideTouchable(false)
.mWidthHeight(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
.mViewAction(R.id.img_avatar, new RewardPopupwindow.ViewAction<ImageView>() {
@Override
public void action(ImageView mView) {
}
})
.mViewActions(new PopupwindowUtil .ViewActions<View>() {
@Override
public void action(View mView, int mViewId) {
switch (mViewId) {
case R.id.rag_select:
break;
case R.id.frl_crash:
break;
case R.id.frl_point:
break;
case R.id.grv_amount:
break;
case R.id.img_avatar:
break;
case R.id.txt_name:
break;
case R.id.txt_msg:
break;
}
}
}, new Integer[]{R.id.rag_select, R.id.frl_crash, R.id.frl_point, R.id.grv_amount, R.id.img_avatar, R.id.txt_name, R.id.txt_msg})
.mCheckAction(R.id.rag_select, new PopupwindowUtil .PopupAction() {
@Override
public void action(PopupWindow mPopupWindow, @Nullable View mContentView, @Nullable RadioGroup group, int checkedId) {
FrameLayout frl_crash = (FrameLayout) mContentView.findViewById(R.id.frl_crash);
FrameLayout frl_point = (FrameLayout) mContentView.findViewById(R.id.frl_point);
RewardSquaresGridView grv_amount = (RewardSquaresGridView) mContentView.findViewById(R.id.grv_amount);
frl_crash.setVisibility(checkedId == R.id.rab_crash ? View.VISIBLE : View.INVISIBLE);
frl_point.setVisibility(checkedId == R.id.rab_point ? View.VISIBLE : View.INVISIBLE);
switch (checkedId) {
case R.id.rab_crash:
break;
case R.id.rab_point:
break;
}
}
})
.mClickAction(R.id.btn_commit, new PopupwindowUtil .PopupAction() {
@Override
public void action(PopupWindow mPopupWindow, @Nullable View mContentView, @Nullable RadioGroup group, int checkedId) {
if (!BaseUtil.checkLogin(getContext()))
return;
final RewardSquaresGridView grv_amount = (RewardSquaresGridView) mContentView.findViewById(R.id.grv_amount);
RadioGroup rag_select = (RadioGroup) mContentView.findViewById(R.id.rag_select);
String money = grv_amount.getCurrentMoney() + "";
if (rag_select.getCheckedRadioButtonId() == R.id.rab_crash) {
} else {
}
mPopupWindow.dismiss();
}
})
.mDisMissAction(R.id.imb_cancel)
.mShowAtLocation(X5BbsWebView.this, Gravity.CENTER, 0, 0);
About ViewAction
For one:
.mViewAction(R.id.img_avatar, new RewardPopupwindow.ViewAction<ImageView>() {
@Override
public void action(ImageView mView) {
}
})
For more:
.mViewActions(new PopupwindowUtil .ViewActions<View>() {
@Override
public void action(View mView, int mViewId) {
switch (mViewId) {
case R.id.rag_select:
break;
case R.id.frl_crash:
break;
case R.id.frl_point:
break;
case R.id.grv_amount:
break;
case R.id.img_avatar:
break;
case R.id.txt_name:
break;
case R.id.txt_msg:
break;
}
}
}, new Integer[]{R.id.rag_select, R.id.frl_crash, R.id.frl_point, R.id.grv_amount, R.id.img_avatar, R.id.txt_name, R.id.txt_msg})
Other
AboutClickAction
.mClickAction(R.id.btn_commit, new PopupwindowUtil .PopupAction() {
@Override
public void action(PopupWindow mPopupWindow, @Nullable View mContentView, @Nullable RadioGroup group, int checkedId) {
}
})
AboutCheckAction
.mCheckAction(R.id.rag_select, new PopupwindowUtil .PopupAction() {
@Override
public void action(PopupWindow mPopupWindow, @Nullable View mContentView, @Nullable RadioGroup group, int checkedId) {
FrameLayout frl_crash = (FrameLayout) mContentView.findViewById(R.id.frl_crash);
FrameLayout frl_point = (FrameLayout) mContentView.findViewById(R.id.frl_point);
RewardSquaresGridView grv_amount = (RewardSquaresGridView) mContentView.findViewById(R.id.grv_amount);
frl_crash.setVisibility(checkedId == R.id.rab_crash ? View.VISIBLE : View.INVISIBLE);
frl_point.setVisibility(checkedId == R.id.rab_point ? View.VISIBLE : View.INVISIBLE);
switch (checkedId) {
case R.id.rab_crash:
break;
case R.id.rab_point:
break;
}
}
})