PopupWindow 弹出对话框的一种,和
AlertDialog类似,可以用来
实现一个悬浮的菜单
API定义:A popup window that can be used to display an arbitrary view. The popup
window is a floating container that appears on top of the current
activity.
AlertDialog和Popupwindow的区别:
1)Popupwindow可以全屏,而且可以控制显示在屏幕的位置,这些都是AlertDialog无法做到的。
2)AlertDialog是非阻塞线程的,Popupwindow是阻塞线程的。
关于Popupwindow阻塞线程,写这篇文章之前,我参考了很多朋友的日志,再和自己的程序运行结果对比,发现差异挺大,以下就把自己的结论贴出来,欢迎大家指出错误。
这个是我的界面,每个按钮分别对应不同的弹出对话框,
/**
* 显示AlertDialog对话框:
*
* @see AlertDialog是非阻塞式对话框,可以再oncreate方法中直接调用显示
* :AlertDialog弹出时,点击对话框之外背景,对话框消失,程序不仅响应AlertDialog的操作
* ,还响应其他操作
*/
private void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("标题");
builder.setMessage("AlertDialog对话显示的内容");
// 注意,Dialog内容可以用自定义布局填充
// builder.setView(view);
builder.setPositiveButton("确定", new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO
}
}).setNegativeButton("取消", new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
// 创建对话框
AlertDialog dialog = builder.create();
dialog.show();
}
/**
* 显示PopupWiodow对话框
*
* @see PopupWindow是阻塞式对话框,PopupWindow弹出时
* ,背景没有什么变化,但是当我们点击背景的时候,PopupWindow不会消失,但是PopupWindow对话框之外的按钮依然可以点击。
* Popupwindow可以全屏,而且可以控制显示在屏幕的位置,这些都是AlertDialog无法做到的。
*/
private void showPopupWindow() {
LayoutInflater inflater = LayoutInflater.from(context);
// 加载指定布局作为PopupWindow的显示内容
View contentView = inflater.inflate(R.layout.item_popup, null);
popupWindow = new PopupWindow(contentView, LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
// setPopFoucus();
popupWindow.showAtLocation(btnDialog, Gravity.BOTTOM, 0, 0);
popupWindow.showAsDropDown(btnDialog);
}
如下图:单我点击按钮在指定位置弹出PopupWindow时,再点击PopupWindow之外的按钮,依然能得到响应(弹出土司提示信息,)
甚至在弹出PopupWindow的基础上依然可以点击第一个按钮,依然获得响应可以弹出AlertDialog
关于线程阻塞,在oncrete方法中调用直接调用显示PopupWindow时会报出异常
java.lang.RuntimeException: Unable to start activity
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
由于 PopupWindow是依附于Activity之上,当Activity还未创建完成,所以显示PopupWindow时就发生异常
所以 PopupWindow必须在某个事件中显示或者是开启一个新线程去调用,不能直接在onCreate方法中显示
AlertDialog弹出时,点击对话框之外背景,对话框消失,而默认的PopupWindow却没有效果,所以需要加上以下几行代码
// 设置popupWindow获得焦点
popupWindow.setTouchable(true);
// 设置popupWindow以外的区域可点击,点击后空白处,对话框消失
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable(getResources(),
(Bitmap) null));
PopupWindow的显示及位置设置
window.showAtLocation(parent, Gravity.RIGHT | Gravity.BOTTOM, 10,10);
第一个参数指定PopupWindow的锚点view,即依附在哪个view上。
第二个参数指定起始点为parent的右下角,第三个参数设置以parent的右下角为原点,向左、上各偏移10像素。
第二个参数指定起始点为parent的右下角,第三个参数设置以parent的右下角为原点,向左、上各偏移10像素。
//将PopupWindow作为anchor的下拉窗口显示。即在anchor的左下角显示
window.showAsDropDown(anchor);
//xoff,yoff基于anchor的左下角进行偏移。
window.showAsDropDown(anchor, xoff, yoff);
window.showAsDropDown(anchor);
//xoff,yoff基于anchor的左下角进行偏移。
window.showAsDropDown(anchor, xoff, yoff);
全屏的PopupWindow
/**
* 弹出全屏对话框
*/
private void showPopupFullWindow() {
// 获得LayoutInflater的另外一种方式
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 加载指定布局作为PopupWindow的显示内容
View contentView = inflater.inflate(R.layout.item_popup, null);
// 注意:popup的全屏是不包括顶部状态栏高度,所以 popup的真正高度是屏幕高度减去状态栏高度,否则会部分显示在外
int mScreenWidth = getWindowManager().getDefaultDisplay().getWidth();
int mScreenHeight = getWindowManager().getDefaultDisplay().getHeight();
Rect rect = new Rect();
this.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top; // 状态栏高度
int realHeight = mScreenHeight - statusBarHeight;
// 初始化popupWindow,指定显示内容和宽高
popupWindow = new PopupWindow(contentView, mScreenWidth, realHeight);
setPopFoucus();
popupWindow.showAtLocation(btnDialog, Gravity.BOTTOM, 0, 0);
popupWindow.showAsDropDown(btnDialog);
}