对话框:阻塞式PopupWindow 和非阻塞AlertDialog

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LANG791534167/article/details/37706293
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.BOTTOM10,10);
第一个参数指定PopupWindow的锚点view,即依附在哪个view上。
第二个参数指定起始点为parent的右下角,第三个参数设置以parent的右下角为原点,向左、上各偏移10像素。
//将PopupWindow作为anchor的下拉窗口显示。即在anchor的左下角显示
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);
}







阅读更多
换一批

没有更多推荐了,返回首页