アプリケーションにカスタムダイアログを実装しました。ユーザーがダイアログの外側をクリックすると、ダイアログが閉じられるように実装したいと思います。これには何をしなければなりませんか?
ダイアログの外側をタッチするとダイアログを閉じるdialog.setCanceledOnTouchOutside(true);
を使用できます。
何かのようなもの、
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
または、ダイアログが非モデルの場合、
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;
}
詳細については、 タッチポイントに基づいてカスタムダイアログを閉じる方法 および ダイアログ領域外でタッチしたときに非モーダルダイアログを閉じる方法 を参照してください。
この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
単に使用する
dialog.setCanceledOnTouchOutside(true);
または、スタイルxmlで定義されたテーマを使用してダイアログをカスタマイズする場合は、テーマに次の行を追加します。
<item name="Android:windowCloseOnTouchOutside">true</item>
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);
このコードは、hidesoftinputのときにダイアログボックスをクリックするとき、およびsoftinputとdialogboxの両方が閉じるときにダイアログボックスの外側をクリックするときに使用します。
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ソースコードからカットされた別のソリューションこの2つのメソッドをダイアログのソースコードに追加するだけです。
@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));
}
このソリューションにはこの問題はありません。
これは、下のアクティビティがタッチイベントにも反応することを除いて、非常に効果的です。これを防ぐ方法はありますか? –ハエットル
アクティビティ/フラグメントからdialog.setCancelable(false);
を呼び出します。
すべての画面サイズbackground
を占有するtransparent
を作成し、onClick
に対するdismiss
イベントをリッスンできます。