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.