Bagaimana cara mengabaikan dialog dengan klik di luar dialog?


Jawaban:


356

Anda dapat menggunakan dialog.setCanceledOnTouchOutside(true);yang akan menutup dialog jika Anda menyentuh di luar dialog.

Sesuatu seperti,

  Dialog dialog = new Dialog(context)
  dialog.setCanceledOnTouchOutside(true);

Atau jika Dialog Anda bukan model,

1 - Tetapkan flag- FLAG_NOT_TOUCH_MODALuntuk atribut jendela dialog Anda

Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

2 - Tambahkan bendera lain ke properti windows ,, FLAG_WATCH_OUTSIDE_TOUCH- ini untuk dialog untuk menerima acara sentuh di luar wilayah yang terlihat.

3 - Ganti onTouchEvent()dialog dan periksa jenis tindakan. jika jenis tindakan adalah ' MotionEvent.ACTION_OUTSIDE' berarti, pengguna berinteraksi di luar wilayah dialog. Jadi dalam hal ini, Anda dapat mengabaikan dialog Anda atau memutuskan apa yang ingin Anda lakukan. lihat cetak polos?

public boolean onTouchEvent(MotionEvent event)  
{  

       if(event.getAction() == MotionEvent.ACTION_OUTSIDE){  
        System.out.println("TOuch outside the dialog ******************** ");  
               this.dismiss();  
       }  
       return false;  
}  

Untuk info lebih lanjut, lihat Cara mengabaikan dialog khusus berdasarkan titik sentuh? dan Cara mengabaikan dialog non-modal Anda, ketika disentuh di luar wilayah dialog


9
Ini berfungsi baik kecuali bahwa aktivitas di bawahnya juga bereaksi terhadap peristiwa sentuhan. Apakah ada cara untuk mencegahnya?
Howettl

Ya. window.setFlags (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); menyebabkan masalah ini. Saya telah memposting solusi di bawah ini :)
Unknownweirdo

Apakah mungkin untuk menyebarkan acara 'on-touch-outside' ke aktivitas di bawahnya menggunakan dialog non-kustom juga?
jc

1
@ howettl Saya telah memecahkan masalah Anda dalam solusi saya yang telah saya posting di bawah ini di mana saya tidak perlu mengatur bendera ke jendela.
Roman Nazarevych

@MuhammedRefaat - Silakan melihat thread ini groups.google.com/forum/#!topic/android-developers/VhaiIMl6E_w . Mereka menggambarkannya dengan baik.
user370305

18

Cukup gunakan

dialog.setCanceledOnTouchOutside(true);

Saya tahu bahwa ini seharusnya jawaban yang tepat, tetapi tidak berhasil untuk saya, dan saya tidak tahu mengapa.
IgniteCoders

16

Anda dapat menggunakan implementasi onTouchEvent ini. Ini mencegah dari bereaksi di bawah aktivitas ke acara sentuhan (seperti yang disebutkan 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 );
}

Sumber: http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html


9

Atau, jika Anda menyesuaikan dialog menggunakan tema yang ditentukan dalam xml gaya Anda, masukkan baris ini dalam tema Anda:

<item name="android:windowCloseOnTouchOutside">true</item>

Ini tidak berfungsi untuk saya di Samsung Galaxy Tab 2 WiFi. dialog.setCanceledOnTouchOutside(true);bekerja dengan sangat baik.
doplumi

7
dialog.setCanceledOnTouchOutside(true); 

untuk menutup dialog saat disentuh di luar.

Dan jika Anda tidak ingin menutup sentuhan di luar, gunakan kode di bawah ini:

dialog.setCanceledOnTouchOutside(false);

6

Metode ini harus sepenuhnya menghindari aktivitas di bawah area abu-abu yang mengambil peristiwa klik.

Hapus baris ini jika Anda memilikinya:

window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

Letakkan ini di aktivitas Anda yang dibuat

getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);

kemudian timpa acara sentuh dengan ini

@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);
}

4

Anda dapat mencoba ini: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

atau

alertDialog.setCancelable(true);

Dan jika Anda memiliki AlterDialog.BuilderMaka Anda dapat mencoba ini: -

alertDialogBuilder.setCancelable(true);

4

Kode ini digunakan untuk ketika menggunakan klik pada kotak dialog yang menyembunyikan input dan ketika pengguna mengklik sisi luar kotak dialog yang waktu softinput dan kotak dialog ditutup.

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;
    }
};

2

Solusi lain, kode ini diambil dari kode sumber android. Window Anda harus menambahkan kedua metode ini ke kode sumber dialog Anda.

@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));
}

Solusi ini tidak memiliki masalah ini:

Ini berfungsi baik kecuali bahwa aktivitas di bawahnya juga bereaksi terhadap peristiwa sentuhan. Apakah ada cara untuk mencegahnya? - howettl


Tidak bisakah Anda hanya membuat modal sentuhan dialog jika Anda tidak ingin acara penerimaan jendela lainnya?

1

Panggil dialog.setCancelable(false);dari aktivitas / fragmen Anda.



0

Anda dapat membuat backgroundmenempati semua ukuran layar transparentdan mendengarkan onClickacara dismissitu.


10
Jawaban yang sangat buruk! Tentu saja ini bisa dilakukan, tetapi tolong lakukan dengan cara yang benar!
jc

-1

Ini kodenya

    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;
        }
    });

Coba yang ini . Anda dapat menyembunyikan keyboard saat menyentuh di luar

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.