示例效果图:
更新1:背景变暗配置示例:
//创建并显示popWindow
mCustomPopWindow= new CustomPopWindow.PopupWindowBuilder(this)
.setView(contentView)
.enableBackgroundDark(true) //弹出popWindow时,背景是否变暗
.setBgDarkAlpha(0.7f) // 控制亮度
.create()
.showAsDropDown(mButton5,0,20);
更新2:显示消失动画配置:
CustomPopWindow popWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(R.layout.pop_layout1)
.setFocusable(true)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.CustomPopWindowStyle) // 添加自定义显示和消失动画
.create()
.showAsDropDown(mButton1,0,10);
更新3:点击PopupWindow以外区域不让关闭(默认DisMiss):
mPopWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(view)
.enableOutsideTouchableDissmiss(false)// 设置点击PopupWindow之外的地方,popWindow不关闭,如果不设置这个属性或者为true,则关闭
.create();
mPopWindow.showAsDropDown(mButton7,0,10);
1,简便写法
CustomPopWindow popWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(R.layout.pop_layout1)//显示的布局,还可以通过设置一个View
// .size(600,400) //设置显示的大小,不设置就默认包裹内容
.setFocusable(true)//是否获取焦点,默认为ture
.setOutsideTouchable(true)//是否PopupWindow 以外触摸dissmiss
.create()//创建PopupWindow
.showAsDropDown(mButton1,0,10);//显示PopupWindow
以上就是弹出一个简单的PopupWindow,是不是看起来很优雅和简单,还可以简单一点:
CustomPopWindow popWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(R.layout.pop_layout1)//显示的布局
.create()//创建PopupWindow
.showAsDropDown(mButton1,0,10);//显示PopupWindow
如果是一个简单的只展示文案的弹窗,就可以只设置一个View,就可以了,很简单吧!!!
2,展示一个PopupWindow 弹窗菜单(像手机QQ,微信的顶部菜单)
View contentView = LayoutInflater.from(this).inflate(R.layout.pop_menu,null);
//处理popWindow 显示内容
handleLogic(contentView);
//创建并显示popWindow
mCustomPopWindow= new CustomPopWindow.PopupWindowBuilder(this)
.setView(contentView)
.create()
.showAsDropDown(mButton3,0,20);
如果PopupWindow 展示的内容需要在程序代码中设置或者响应点击事件等,可以现获取到这个View,然后处理一些显示和点击事件逻辑,再交给CustomPopWindow 创建显示。比如响应菜单点击事件的逻辑处理:
/**
* 处理弹出显示内容、点击事件等逻辑
* @param contentView
*/
private void handleLogic(View contentView){
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mCustomPopWindow!=null){
mCustomPopWindow.dissmiss();
}
String showContent = "";
switch (v.getId()){
case R.id.menu1:
showContent = "点击 Item菜单1";
break;
case R.id.menu2:
showContent = "点击 Item菜单2";
break;
case R.id.menu3:
showContent = "点击 Item菜单3";
break;
case R.id.menu4:
showContent = "点击 Item菜单4";
break;
case R.id.menu5:
showContent = "点击 Item菜单5" ;
break;
}
Toast.makeText(MainActivity.this,showContent,Toast.LENGTH_SHORT).show();
}
};
contentView.findViewById(R.id.menu1).setOnClickListener(listener);
contentView.findViewById(R.id.menu2).setOnClickListener(listener);
contentView.findViewById(R.id.menu3).setOnClickListener(listener);
contentView.findViewById(R.id.menu4).setOnClickListener(listener);
contentView.findViewById(R.id.menu5).setOnClickListener(listener);
}
}
3,展示一个ListView,其实跟上面是一样的,这里贴一下实例代码:
private void showPopListView(){
View contentView = LayoutInflater.from(this).inflate(R.layout.pop_list,null);
//处理popWindow 显示内容
handleListView(contentView);
//创建并显示popWindow
mListPopWindow= new CustomPopWindow.PopupWindowBuilder(this)
.setView(contentView)
.size(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)//显示大小
.create()
.showAsDropDown(mButton4,0,20);
}
private void handleListView(View contentView){
RecyclerView recyclerView = (RecyclerView) contentView.findViewById(R.id.recyclerView);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);
MyAdapter adapter = new MyAdapter();
adapter.setData(mockData());
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
/**
* 自定义PopWindow类,封装了PopWindow的一些常用属性,用Builder模式支持链式调用
* 我自己后来又修改了一点代码,使弹窗的宽等于屏幕的宽!
*/
public class PopwindownUtils implements PopupWindow.OnDismissListener {
private static final String TAG = "CustomPopWindow";
private static final float DEFAULT_ALPHA = 0.7f;
private Context mContext;
private int mWidth;
private int mHeight;
private boolean mIsFocusable = true;
private boolean mIsOutside = true;
private int mResLayoutId = -1;
private View mContentView;
private PopupWindow mPopupWindow;
private int mAnimationStyle = -1;
private boolean mClippEnable = true;//default is true
private boolean mIgnoreCheekPress = false;
private int mInputMode = -1;
private PopupWindow.OnDismissListener mOnDismissListener;
private int mSoftInputMode = -1;
private boolean mTouchable = true;//default is ture
private View.OnTouchListener mOnTouchListener;
private Window mWindow;//当前Activity 的窗口
/**
* 弹出PopWindow 背景是否变暗,默认不会变暗。
*/
private boolean mIsBackgroundDark = false;
private float mBackgroundDrakValue = 0;// 背景变暗的值,0 - 1
/**
* 设置是否允许点击 PopupWindow之外的地方,关闭PopupWindow
*/
private boolean enableOutsideTouchDisMiss = true;// 默认点击pop之外的地方可以关闭
private PopwindownUtils(Context context) {
mContext = context;
}
public int getWidth() {
return mWidth;
}
public int getHeight() {
return mHeight;
}
/**
* @param anchor
* @param xOff
* @param yOff
* @return
*/
public PopwindownUtils showAsDropDown(View anchor, int xOff, int yOff) {
if (mPopupWindow != null) {
mPopupWindow.showAsDropDown(anchor, xOff, yOff);
}
return this;
}
public PopwindownUtils showAsDropDown(View anchor) {
if (mPopupWindow != null) {
mPopupWindow.showAsDropDown(anchor);
}
return this;
}
/**
* 在某一个控件的周边位置显示
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public PopwindownUtils showAsDropDown(View anchor, int gravity, int xOff, int yOff) {
if (mPopupWindow != null) {
mPopupWindow.showAsDropDown(anchor, xOff, yOff, gravity);
}
return this;
}
/**
* 相对于父控件的位置(通过设置Gravity.CENTER,下方Gravity.BOTTOM等 ),可以设置具体位置坐标
*
* @param parent 父控件
* @param gravity
* @param x the popup's x location offset
* @param y the popup's y location offset
* @return
*/
public PopwindownUtils showAtLocation(View parent, int gravity, int x, int y) {
if (mPopupWindow != null) {
mPopupWindow.showAtLocation(parent, gravity, x, y);
}
return this;
}
/**
* 添加一些属性设置
*
* @param popupWindow
*/
private void apply(PopupWindow popupWindow) {
popupWindow.setClippingEnabled(mClippEnable);
if (mIgnoreCheekPress) {
popupWindow.setIgnoreCheekPress();
}
if (mInputMode != -1) {
popupWindow.setInputMethodMode(mInputMode);
}
if (mSoftInputMode != -1) {
popupWindow.setSoftInputMode(mSoftInputMode);
}
if (mOnDismissListener != null) {
popupWindow.setOnDismissListener(mOnDismissListener);
}
if (mOnTouchListener != null) {
popupWindow.setTouchInterceptor(mOnTouchListener);
}
popupWindow.setTouchable(mTouchable);
}
private PopupWindow build() {
if (mContentView == null) {
mContentView = LayoutInflater.from(mContext).inflate(mResLayoutId, null);
}
// 2017.3.17 add
// 获取当前Activity的window
Activity activity = (Activity) mContentView.getContext();
if (activity != null && mIsBackgroundDark) {
//如果设置的值在0 - 1的范围内,则用设置的值,否则用默认值
final float alpha = (mBackgroundDrakValue > 0 && mBackgroundDrakValue < 1) ? mBackgroundDrakValue : DEFAULT_ALPHA;
mWindow = activity.getWindow();
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = alpha;
mWindow.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
mWindow.setAttributes(params);
}
if (mWidth != 0 && mHeight != 0) {
mPopupWindow = new PopupWindow(mContentView, mWidth, mHeight);
} else {
/*PopupWindow弹窗的宽度 不充满 全屏宽度*/
// mPopupWindow = new PopupWindow(mContentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
/*PopupWindow弹窗的宽度 充满 全屏宽度*/
mPopupWindow = new PopupWindow(mContentView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
if (mAnimationStyle != -1) {
mPopupWindow.setAnimationStyle(mAnimationStyle);
}
apply(mPopupWindow);//设置一些属性
if (mWidth == 0 || mHeight == 0) {
mPopupWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
//如果外面没有设置宽高的情况下,计算宽高并赋值
mWidth = mPopupWindow.getContentView().getMeasuredWidth();
mHeight = mPopupWindow.getContentView().getMeasuredHeight();
}
// 添加dissmiss 监听
mPopupWindow.setOnDismissListener(this);
//设置 setOutsideTouchable(false)点击外部取消的bug.
// 判断是否点击PopupWindow之外的地方关闭 popWindow
if (!enableOutsideTouchDisMiss) {
//注意这三个属性必须同时设置,不然不能disMiss,以下三行代码在Android 4.4 上是可以,然后在Android 6.0以上,下面的三行代码就不起作用了,就得用下面的方法
mPopupWindow.setFocusable(true);
mPopupWindow.setOutsideTouchable(false);
mPopupWindow.setBackgroundDrawable(null);
//注意下面这三个是contentView 不是PopupWindow
mPopupWindow.getContentView().setFocusable(true);
mPopupWindow.getContentView().setFocusableInTouchMode(true);
mPopupWindow.getContentView().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mPopupWindow.dismiss();
return true;
}
return false;
}
});
//在Android 6.0以上 ,只能通过拦截事件来解决
mPopupWindow.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
if ((event.getAction() == MotionEvent.ACTION_DOWN)
&& ((x < 0) || (x >= mWidth) || (y < 0) || (y >= mHeight))) {
Log.e(TAG, "out side ");
Log.e(TAG, "width:" + mPopupWindow.getWidth() + "height:" + mPopupWindow.getHeight() + " x:" + x + " y :" + y);
return true;
} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
Log.e(TAG, "out side ...");
return true;
}
return false;
}
});
} else {
mPopupWindow.setFocusable(mIsFocusable);
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
mPopupWindow.setOutsideTouchable(mIsOutside);
}
// update
mPopupWindow.update();
return mPopupWindow;
}
@Override
public void onDismiss() {
if (addDismissListend != null) {
addDismissListend.addonDismissListen();
}
dissmiss();
}
//通过接口监听onDismiss()事件
private addDismissListen addDismissListend;
public void addDismisslistenq(addDismissListen addDismissListend) {
this.addDismissListend = addDismissListend;
}
public interface addDismissListen {
public void addonDismissListen();
}
/**
* 关闭popWindow
*/
public void dissmiss() {
if (mOnDismissListener != null) {
mOnDismissListener.onDismiss();
}
//如果设置了背景变暗,那么在dissmiss的时候需要还原
if (mWindow != null) {
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = 1.0f;
mWindow.setAttributes(params);
}
if (mPopupWindow != null && mPopupWindow.isShowing()) {
mPopupWindow.dismiss();
}
}
public PopupWindow getPopupWindow() {
return mPopupWindow;
}
public static class PopupWindowBuilder {
private PopwindownUtils mCustomPopWindow;
public PopupWindowBuilder(Context context) {
mCustomPopWindow = new PopwindownUtils(context);
}
public PopupWindowBuilder size(int width, int height) {
mCustomPopWindow.mWidth = width;
mCustomPopWindow.mHeight = height;
return this;
}
public PopupWindowBuilder setFocusable(boolean focusable) {
mCustomPopWindow.mIsFocusable = focusable;
return this;
}
/**
* 显示的布局,还可以通过设置一个View
*/
public PopupWindowBuilder setView(int resLayoutId) {
mCustomPopWindow.mResLayoutId = resLayoutId;
mCustomPopWindow.mContentView = null;
return this;
}
/**
* 显示的布局,还可以通过设置一个View
*/
public PopupWindowBuilder setView(View view) {
mCustomPopWindow.mContentView = view;
mCustomPopWindow.mResLayoutId = -1;
return this;
}
/**
* 是否PopupWindow 以外触摸dissmiss
*/
public PopupWindowBuilder setOutsideTouchable(boolean outsideTouchable) {
mCustomPopWindow.mIsOutside = outsideTouchable;
return this;
}
/**
* 设置弹窗动画
*
* @param animationStyle
* @return
*/
public PopupWindowBuilder setAnimationStyle(int animationStyle) {
mCustomPopWindow.mAnimationStyle = animationStyle;
return this;
}
public PopupWindowBuilder setClippingEnable(boolean enable) {
mCustomPopWindow.mClippEnable = enable;
return this;
}
public PopupWindowBuilder setIgnoreCheekPress(boolean ignoreCheekPress) {
mCustomPopWindow.mIgnoreCheekPress = ignoreCheekPress;
return this;
}
public PopupWindowBuilder setInputMethodMode(int mode) {
mCustomPopWindow.mInputMode = mode;
return this;
}
public PopupWindowBuilder setOnDissmissListener(PopupWindow.OnDismissListener onDissmissListener) {
mCustomPopWindow.mOnDismissListener = onDissmissListener;
return this;
}
public PopupWindowBuilder setSoftInputMode(int softInputMode) {
mCustomPopWindow.mSoftInputMode = softInputMode;
return this;
}
public PopupWindowBuilder setTouchable(boolean touchable) {
mCustomPopWindow.mTouchable = touchable;
return this;
}
public PopupWindowBuilder setTouchIntercepter(View.OnTouchListener touchIntercepter) {
mCustomPopWindow.mOnTouchListener = touchIntercepter;
return this;
}
/**
* 设置背景变暗是否可用
*
* @param isDark
* @return
*/
public PopupWindowBuilder enableBackgroundDark(boolean isDark) {
mCustomPopWindow.mIsBackgroundDark = isDark;
return this;
}
/**
* 设置背景变暗的值
*
* @param darkValue
* @return
*/
public PopupWindowBuilder setBgDarkAlpha(float darkValue) {
mCustomPopWindow.mBackgroundDrakValue = darkValue;
return this;
}
/**
* 设置是否允许点击 PopupWindow之外的地方,关闭PopupWindow
*
* @param disMiss
* @return
*/
public PopupWindowBuilder enableOutsideTouchableDissmiss(boolean disMiss) {
mCustomPopWindow.enableOutsideTouchDisMiss = disMiss;
return this;
}
/**
* 创建PopupWindow
*/
public PopwindownUtils create() {
//构建PopWindow
mCustomPopWindow.build();
return mCustomPopWindow;
}
}
}