需要点击返回键和点击popuwindown外部使popwindow消失
showAtLocation调用之前,设置以下此参数
popupWindow.setBackgroundDrawable(new BitmapDrawable());
// 设置点击窗口外边窗口消失
popupWindow.setOutsideTouchable(true);
// 设置此参数获得焦点,否则无法点击
popupWindow.setFocusable(true);
在4.0/5.0的 PopupWindow.java
源码中发现是在 PopupViewContainer
类中设置的,而在6.0源码中则是位于 PopupDecorView
类;
继续查找在哪里初始化的,发现 preparePopup()
,它是在显示(showAtLocation()
, showAsDropDown()
)的时候调用的,而 preparePopup()
的具体内容:
// PopupWindow.java @ api 14/19/21
private void preparePopup(WindowManager.LayoutParams p) {
if (mContentView == null || mContext == null || mWindowManager == null) {
throw new IllegalStateException("You must specify a valid content view by "
+ "calling setContentView() before attempting to show the popup.");
}
if (mBackground != null) {
final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
int height = ViewGroup.LayoutParams.MATCH_PARENT;
if (layoutParams != null &&
layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
height = ViewGroup.LayoutParams.WRAP_CONTENT;
}
// when a background is available, we embed the content view
// within another view that owns the background drawable
PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, height
);
popupViewContainer.setBackgroundDrawable(mBackground);
popupViewContainer.addView(mContentView, listParams);
mPopupView = popupViewContainer;
} else {
mPopupView = mContentView;
}
mPopupWidth = p.width;
mPopupHeight = p.height;
}
这里可以看到当background不为null的时候,在contentView外面套了一层PopupViewContainer,而PopupViewContainer中才有关于touch,key的监听事件,因此若未设置背景,则点击外部区域无法取消popupwindow,即使设置了:popupWindow.setOutsideTouchable(true);
而在android6.0中:
// PopupWindow.java @ api 23
private void preparePopup(WindowManager.LayoutParams p) {
......
// When a background is available, we embed the content view within
// another view that owns the background drawable.
if (mBackground != null) {
mBackgroundView = createBackgroundView(mContentView);
mBackgroundView.setBackground(mBackground);
} else {
mBackgroundView = mContentView;
}
// 无论background是否为空,都会创建decorView,它是PopupDecorView的实例,其实就是一个FrameLayout,里面有touch事件的监听,因此无需设置背景也可以点击外部区域取消popupwindow的
mDecorView = createDecorView(mBackgroundView);
......
}
总之添加背景图片就可以了:
popupWindow.setBackgroundDrawable(drawable);