Làm thế nào để loại bỏ hộp thoại với nhấp vào bên ngoài hộp thoại?


Câu trả lời:


356

Bạn có thể sử dụng dialog.setCanceledOnTouchOutside(true);sẽ đóng hộp thoại nếu bạn chạm vào bên ngoài hộp thoại.

Cái gì đó như,

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

Hoặc nếu Hộp thoại của bạn không theo mô hình thì,

1 - Đặt cờ- FLAG_NOT_TOUCH_MODALcho thuộc tính cửa sổ của hộp thoại của bạn

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

2 - Thêm một cờ khác vào thuộc tính windows ,, FLAG_WATCH_OUTSIDE_TOUCH- cái này dành cho hộp thoại để nhận sự kiện chạm bên ngoài vùng nhìn thấy của nó.

3 - Ghi đè onTouchEvent()hộp thoại và kiểm tra loại hành động. nếu loại hành động là ' MotionEvent.ACTION_OUTSIDE' nghĩa là người dùng đang tương tác bên ngoài vùng hộp thoại. Vì vậy, trong trường hợp này, bạn có thể làm mờ hộp thoại của mình hoặc quyết định những gì bạn muốn thực hiện. xem đồng bằng?

public boolean onTouchEvent(MotionEvent event)  
{  

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

Để biết thêm thông tin, hãy xem Làm thế nào để loại bỏ hộp thoại tùy chỉnh dựa trên các điểm chạm? Cách loại bỏ hộp thoại không theo phương thức của bạn, khi chạm vào vùng hộp thoại


9
Điều này hoạt động rất tốt ngoại trừ hoạt động bên dưới cũng phản ứng với sự kiện chạm. Có cách nào để ngăn chặn điều này?
howettl

Vâng. window.setFlags (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); gây ra vấn đề này Tôi đã đăng một giải pháp bên dưới :)
Unknownweirdo

Có thể truyền các sự kiện 'chạm vào bên ngoài' cho hoạt động bên dưới bằng hộp thoại không tùy chỉnh không?
jc

1
@howettl Tôi đã giải quyết vấn đề của bạn trong giải pháp của tôi mà tôi đã đăng bên dưới , nơi tôi không cần đặt bất kỳ cờ nào cho cửa sổ.
Roman Nazarevych

@MuhammedRefaat - Vui lòng xem chủ đề này nhóm.google.com/forum/# !topic/ android-developers/VhaiIMl6E_w . Họ mô tả độc đáo nó.
dùng370305

18

Đơn giản chỉ cần sử dụng

dialog.setCanceledOnTouchOutside(true);

Tôi biết rằng đây là câu trả lời đúng, nhưng không hiệu quả với tôi và tôi không biết tại sao.
IgniteCoders

16

Bạn có thể sử dụng triển khai này của onTouchEvent. Nó ngăn không cho phản ứng bên dưới hoạt động với sự kiện chạm (như đã đề cập 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 );
}

Nguồn: http://blog.twimager.com/2010/08/closes-activity-by-touching-outside.html


9

Hoặc, nếu bạn đang tùy chỉnh hộp thoại bằng một chủ đề được xác định trong xml kiểu của bạn, hãy đặt dòng này trong chủ đề của bạn:

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

Điều này không hoạt động với tôi trên Samsung Galaxy Tab 2 WiFi. dialog.setCanceledOnTouchOutside(true);làm việc tuyệt vời
doplumi

7
dialog.setCanceledOnTouchOutside(true); 

để đóng hộp thoại khi chạm bên ngoài.

Và nếu bạn không muốn đóng liên lạc bên ngoài, hãy sử dụng mã dưới đây:

dialog.setCanceledOnTouchOutside(false);

6

Phương pháp này sẽ hoàn toàn tránh các hoạt động bên dưới vùng màu xám lấy các sự kiện nhấp chuột.

Xóa dòng này nếu bạn có nó:

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

Đặt điều này vào hoạt động của bạn được tạo

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

sau đó ghi đè sự kiện chạm bằng cái này

@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

Bạn có thể thử điều này: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

hoặc là

alertDialog.setCancelable(true);

Và nếu bạn có AlterDialog.Builderthì bạn có thể thử điều này: -

alertDialogBuilder.setCancelable(true);

4

Mã này được sử dụng khi sử dụng nhấp vào hộp thoại có thời gian ẩn và khi người dùng nhấp vào bên ngoài hộp thoại, thời điểm đó cả hai hộp mềm và hộp thoại đều đóng.

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

Một giải pháp khác, mã này được lấy từ mã nguồn Android của Window Bạn chỉ nên thêm hai phương thức này vào mã nguồn hộp thoại của bạn.

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

Giải pháp này không có vấn đề này:

Điều này hoạt động rất tốt ngoại trừ hoạt động bên dưới cũng phản ứng với sự kiện chạm. Có cách nào để ngăn chặn điều này? - hú


Bạn không thể làm cho hộp thoại của bạn chạm vào chế độ nếu bạn không muốn các cửa sổ khác nhận các sự kiện?

1

Gọi dialog.setCancelable(false);từ hoạt động / đoạn của bạn.



0

Bạn có thể thực hiện backgroundchiếm toàn bộ kích thước màn hình transparentvà lắng nghe onClicksự kiện dismiss.


10
Câu trả lời rất tệ! Tất nhiên điều này có thể được thực hiện, nhưng xin vui lòng làm nó đúng cách!
jc

-1

Đây là mã

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

Hãy thử cái này bạn có thể ẩn bàn phím khi bạn chạm vào bên ngoài

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.