【发布时间】:2012-01-13 02:52:30
【问题描述】:
我已经为我的应用程序实现了一个自定义对话框。我想实现当用户在对话框外单击时,对话框将被关闭。 我该怎么办?
【问题讨论】:
标签: android android-layout android-emulator dialog android-dialog
我已经为我的应用程序实现了一个自定义对话框。我想实现当用户在对话框外单击时,对话框将被关闭。 我该怎么办?
【问题讨论】:
标签: android android-layout android-emulator dialog android-dialog
您可以使用dialog.setCanceledOnTouchOutside(true);,如果您在对话框之外触摸,它将关闭对话框。
类似的,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
或者,如果您的 Dialog 在非模型中,那么,
1 - 为对话框的窗口属性设置标志-FLAG_NOT_TOUCH_MODAL
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - 向 Windows 属性添加另一个标志,FLAG_WATCH_OUTSIDE_TOUCH - 这个标志用于对话框在其可见区域之外接收触摸事件。
3 - 覆盖对话框的onTouchEvent() 并检查操作类型。如果动作类型是
'MotionEvent.ACTION_OUTSIDE' 表示用户正在对话区域之外进行交互。因此,在这种情况下,您可以关闭对话或决定要执行的操作。
查看普通版?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
更多信息请查看How to dismiss a custom dialog based on touch points? 和 How to dismiss your non-modal dialog, when touched outside dialog region
【讨论】:
简单地使用
dialog.setCanceledOnTouchOutside(true);
【讨论】:
您可以使用 onTouchEvent 的这个实现。它防止在活动下对触摸事件做出反应(如 howettl 所述)。
@Override
public boolean onTouchEvent ( MotionEvent event ) {
// I only care if the event is an UP action
if ( event.getAction () == MotionEvent.ACTION_UP ) {
// create a rect for storing the window rect
Rect r = new Rect ( 0, 0, 0, 0 );
// retrieve the windows rect
this.getWindow ().getDecorView ().getHitRect ( r );
// check if the event position is inside the window rect
boolean intersects = r.contains ( (int) event.getX (), (int) event.getY () );
// if the event is not inside then we can close the activity
if ( !intersects ) {
// close the activity
this.finish ();
// notify that we consumed this event
return true;
}
}
// let the system handle the event
return super.onTouchEvent ( event );
}
来源:http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html
【讨论】:
或者,如果您使用样式 xml 中定义的主题自定义对话框,请将此行放在您的主题中:
<item name="android:windowCloseOnTouchOutside">true</item>
【讨论】:
dialog.setCanceledOnTouchOutside(true); 确实工作得很好。
dialog.setCanceledOnTouchOutside(true);
在触摸外部时关闭对话框。
如果您不想在外部触摸时关闭,请使用以下代码:
dialog.setCanceledOnTouchOutside(false);
【讨论】:
此方法应完全避免灰色区域以下的活动检索点击事件。
删除如果有此行:
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
将此放在您创建的活动中
getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
然后用这个覆盖触摸事件
@Override
public boolean onTouchEvent(MotionEvent ev)
{
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
displayYourDialog();
return false; // stop activity closing
}
}
// Touch events inside are fine.
return super.onTouchEvent(ev);
}
【讨论】:
你可以试试这个:-
AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);
或
alertDialog.setCancelable(true);
如果你有AlterDialog.Builder 那么你可以试试这个:-
alertDialogBuilder.setCancelable(true);
【讨论】:
此代码用于当使用单击对话框时隐藏软输入时以及当用户单击对话框外侧时软输入和对话框都关闭。
dialog = new Dialog(act) {
@Override
public boolean onTouchEvent(MotionEvent event) {
// Tap anywhere to close dialog.
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) event.getX(),
(int) event.getY())) {
// You have clicked the grey area
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
dialog.dismiss();
// stop activity closing
} else {
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
}
return true;
}
};
【讨论】:
另一种解决方案,此代码取自Window的android源代码
您应该将这两个方法添加到您的对话框源代码中。
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isShowing() && (event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(getContext(), event) && getWindow().peekDecorView() != null)) {
hide();
}
return false;
}
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
final View decorView = getWindow().getDecorView();
return (x < -slop) || (y < -slop)
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
这个解决方案没有这个问题:
这很好用,只是下面的活动也会对触摸事件做出反应。有什么方法可以防止这种情况吗? – 豪特尔
【讨论】:
以下对我有用:
myDialog.setCanceledOnTouchOutside(true);
【讨论】:
从您的活动/片段中调用dialog.setCancelable(false);。
【讨论】:
您可以制作一个background 占据所有屏幕尺寸transparent 并将onClick 事件监听到dismiss 它。
【讨论】:
我尝试了一些答案,但我仍然遇到了一个问题,比如当我在对话框之外按下时,对话框隐藏但显示了一个暗淡的视图,再次按下将转到父活动。但实际上我想在第一次点击后去父活动。 所以我做的是
dialog.setOnCancelListener(this);
并更改了我的活动以实现DialogInterface.OnCancelListener
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
然后繁荣,它奏效了。
【讨论】:
这里是代码
dialog.getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
dialog. getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
UiUtils.hideKeyboard2(getActivity());
return false; // stop activity closing
}
}
getActivity().dispatchTouchEvent(ev);
return false;
}
});
试试这个。触摸外部时可以隐藏键盘
【讨论】: