PopupWindow-외부 클릭시 해제


93

내 활동에 PopupWindow가 있는데, 내 활동과 상호 작용할 때에도 내 PopupWindow가 여전히 표시됩니다 (예 : 내 목록 스크롤). 내 목록을 스크롤 할 수 있고 PopupWindow가 여전히 있습니다.

내가 달성하고 싶은 것은 PopupWindow가 아닌 ​​화면에서 터치 / 스크롤 / 클릭 / 등을 할 때 PopupWindow를 닫고 싶습니다. 메뉴가 작동하는 방식과 같습니다. 메뉴 외부를 클릭하면 메뉴가 사라집니다.

시도 setOutsideTouchable(true)했지만 창을 닫지 않습니다. 감사.

답변:


129

세트에 시도하십시오 setBackgroundDrawablePopupWindow당신이 밖에서 그것을 만지면 창을 닫도록.


5
나는 그것을 놓쳤다. popupWindow에서 setBackgroundDrawable을 사용하고 있습니까? 나는 널의 배경 드로어 블을 설정하면 OnTouchListener를 죽이는 것을 알고있다
마르신 S.

31
그게 다야! thnx 남자! 이 경우 터치 이벤트도 제대로 처리 할 수 ​​있습니다. popupWindow.setOutsideTouchable (true); popupWindow.setTouchable (true); popupWindow.setBackgroundDrawable (new BitmapDrawable ()); popupWindow.setTouchInterceptor (new OnTouchListener () {@Override public boolean onTouch (View v, MotionEvent event) {if (AppContext.isDebugMode ()) Log.d ( "POPUP_WINDOW", "v :"+ v.getTag () + " | 이벤트 : "+ event.getAction ()); popupWindow.dismiss (); return true;}});
beerstorm

3
배경 드로어 블을 null로 설정하면 작동하지 않습니다. 다른 사람이 문제가 있으면 내 대답을 참조하십시오.
mpellegr 2013-07-31

2
@WareNinja, 귀하의 의견이 작동했습니다! 어쩌면 당신은 더 나은이 후 질문에 전체 answeir을 떠날 것이다, 그것은 다른 사람을 위해 유용 할 것이다
안톤 Kizema

3
@WareNinja BitmapDrawable()는 더 이상 사용되지 않습니다. ColorDrawable()대신 사용하십시오 .
Srujan Barai 2015

125

나는 WareNinja가 받아 들여진 답변에 대한 의견을 제외하고는 제공된 답변 중 어느 것도 나를 위해 일하지 않았으며 Marcin S.도 아마도 작동 할 것입니다. 저에게 적합한 부분은 다음과 같습니다.

myPopupWindow.setBackgroundDrawable(new BitmapDrawable());
myPopupWindow.setOutsideTouchable(true);

또는 :

myPopupWindow.setFocusable(true);

차이점이 무엇인지 확실하지 않지만 ListPopupWindow 소스 코드는 setModal을 사용하여 모달리티가 true로 설정된 경우 실제로 후자를 사용하므로 적어도 Android 개발자는 이것을 실행 가능한 접근 방식으로 간주하며 한 줄에 불과합니다.


6
정말 고맙습니다. 다른 답변 중 어느 것도 나를 위해 일하지 않았거나 충분히 잘 설명하지 못했습니다. 두 번째 옵션은 나를 위해 작동하지 않습니다.
JDN

2
또한 BitmapDrawable은 더 이상 사용되지 않습니다. 최신 API 버전에서 지원되지 않을 수있는 임시 해결 방법처럼 보이므로 문제에 대한 실제 해결책이 있으면 좋을 것입니다.
HAL9000

BitmapDrawable deprecated 생성자를 사용하지 않으려면 다음을 참조하십시오 : stackoverflow.com/a/21680637/2048266 . popupWindow.setBackgroundDrawable (new BitmapDrawable (getResources (), ""));
nommer

의 다른 방법을 사용하는 동안 setFocusable첫 번째 방법으로는 : 잘 작동 (버튼이 팝업 외부에 배치되는 경우), 우리는 두 번 버튼을 클릭해야
조이 렉스

BitmapDrawable()더 이상 사용되지 않습니다. ColorDrawable()대신 사용하십시오 .
Srujan Barai

59

나는 같은 문제를 만났고 아래 코드와 같이 수정했습니다. 그것은 나를 위해 잘 작동합니다.

    // Closes the popup window when touch outside.
    mPopupWindow.setOutsideTouchable(true);
    mPopupWindow.setFocusable(true);
    // Removes default background.
    mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

BTW, 더 이상 사용되지 않는 BitmapDrawable 생성자를 사용하지 말고이 새로운 ColorDrawable (android.R.color.transparent) 을 사용하여 기본 배경을 바꿉니다 .

재미있게 보내세요 @. @


3
당신의 popoupWindow 표시하기 전에이 코드를 추가해야합니다
snersesyan

팝업에 포커스가 필요하지 않은 경우 포커스 가능을 true로 설정해야합니까?
Levor

이 기능이 작동한다는 사실에 놀랐지 만 API 21에서는 필요합니다. 이로 인해 팝업 창이 잘못 애니메이션되는 문제도 해결되었습니다.
EpicPandaForce

24

늦었지만 사람들이 여전히 팝업 창에 문제가 있음을 알았습니다. 팝업 창 외부를 터치하거나 클릭하거나 창 자체를 터치하여 팝업 창을 닫을 수있는 완전히 작동하는 예제를 작성하기로 결정했습니다. 이렇게하려면 새 PopupWindow 클래스를 만들고 다음 코드를 복사합니다.

PopupWindow.class

public class PopupWindow extends android.widget.PopupWindow
{
Context ctx;
Button btnDismiss;
TextView lblText;
View popupView;

public PopupWindow(Context context)
{
    super(context);

    ctx = context;
    popupView = LayoutInflater.from(context).inflate(R.layout.popup, null);
    setContentView(popupView);

    btnDismiss = (Button)popupView.findViewById(R.id.btn_dismiss);
    lblText = (TextView)popupView.findViewById(R.id.text);

    setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
    setWidth(WindowManager.LayoutParams.WRAP_CONTENT);

    // Closes the popup window when touch outside of it - when looses focus
    setOutsideTouchable(true);
    setFocusable(true);

    // Removes default black background
    setBackgroundDrawable(new BitmapDrawable());

    btnDismiss.setOnClickListener(new Button.OnClickListener(){

        @Override
        public void onClick(View v) {


         dismiss();
        }});

    // Closes the popup window when touch it
/*     this.setTouchInterceptor(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_MOVE) {
                dismiss();
            }
            return true;
        }
    }); */   
   } // End constructor

   // Attaches the view to its parent anchor-view at position x and y
   public void show(View anchor, int x, int y)
   {
      showAtLocation(anchor, Gravity.CENTER, x, y);
   }
}

이제 팝업 창의 레이아웃을 만듭니다. popup.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout     
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="1dp"
    android:orientation="vertical"
    android:padding="10dp" >

<TextView 
    android:id="@+id/text" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"  
    android:gravity="center" 
    android:padding="5dp" 
    android:text="PopupWindow Example"
    android:textColor="#000000" 
    android:textSize="17sp" 
    android:textStyle="italic" />

<FrameLayout
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center_vertical">

    <Button
        android:id="@+id/btn_dismiss" 
        style="?android:attr/buttonStyleSmall" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Dismiss" 
        android:visibility="gone" />

    <TextView
        android:id="@+id/lbl_dismiss"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Touch outside of this box to dismiss"
        android:textColor="#ffffff"
        android:textStyle="bold" />

</FrameLayout>      

기본 활동에서 PopupWindow 클래스의 인스턴스를 만듭니다.

final PopupWindow popupWindow = new PopupWindow(this);
popupWindow.show(findViewById(R.id.YOUR_MAIN_LAYOUT), 0, -250);

여기서 YOUR_MAIN_LAYOUT은 popupWindow가 팝업되는 현재 활동의 레이아웃입니다.


1
감사합니다-이것은 나를 위해 일했습니다. 한 가지 작은 참고 사항은 사용자 지정 클래스에 PopupWindow 이외의 다른 이름을 사용하는 것입니다. Android가 표준 Android 클래스와 사용자 지정 클래스 사이에 혼동되지 않도록 Popupwindow 대신 MyPopupWindow를 호출 할 수 있습니다.
Simon

@Marcin S. findViewById (R.id.YOUR_MAIN_LAYOUT) ?? 그것은 R.layout.My_Layout 수 있을까요
Ankesh 쿠마 Jaisansaria

@Simon findViewById (R.id.YOUR_MAIN_LAYOUT) ?? R.layout.My_Layout일까요?
Ankesh kumar Jaisansaria 2016 년

15

@LunaKong의 답변과 @HourGlass의 확인에 감사드립니다. 중복 된 댓글을 남기고 싶지 않고 명확하고 간결하게 만들고 싶습니다.

// Closes the popup window when touch outside. This method was written informatively in Google's docs.
mPopupWindow.setOutsideTouchable(true);

// Set focus true to prevent a touch event to go to a below view (main layout), which works like a dialog with 'cancel' property => Try it! And you will know what I mean.
mPopupWindow.setFocusable(true);

// Removes default background.
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

Mttdat.


외부를 클릭하여 팝업 창을 닫을 수 있기를 원했지만, 그렇게했을 때 그 아래의보기 (팝업 창의 일부가 아니라 활동의 일부)가 클릭되었습니다. setFocusabl (true)는 내가 찾던 것이었다. 감사!
hellaandrew

@hellaandrew, 도움이되어 기쁩니다. :)
Nguyen Tan Dat

8

A에 대한 ListPopupWindow표시 할 때 설정 창이 모달 수 있습니다.

mListPopupWindow.setModal(true);

이렇게하면 외부를 클릭하면 ListPopupWindow해제됩니다.


고마워요. 이걸 찾고 있었어요. 이는 뷰 외부를 터치 한 후 listpopupwindow를 해제 할 수 있도록 설정할뿐만 아니라 listpopwindow 옆에있는 다른 뷰에 터치 이벤트를 전달하지 않습니다. 필자의 경우 listpopwindow 외부를 터치하면 listpopupwindow를 닫고 그 아래에있는 recyclerview에 이벤트를 전달하고 내가 원하지 않는 recyclerview 항목이 선택되는 것처럼 필사적으로 이것을 찾고있었습니다.
shankar_vl

mListPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);팝업 창이 화상 키보드를 방해하지 않도록하기 위해이 필요할 수도 있습니다 .
Mr-IDE

6

로 취소 popupWindow.setOutsideTouchable(true)하려면 wrap_content아래 코드와 같이 너비와 높이를 만들어야 합니다.

PopupWindow popupWindow = new PopupWindow(
            G.layoutInflater.inflate(R.layout.lay_dialog_support, null, false),
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT, true);

popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
popupWindow.showAtLocation(view, Gravity.RIGHT, 0, 0);

5
  popupWindow.setTouchable(true);
  popupWindow.setFocusable(true);
  popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);

화면에서 클릭 / 터치 할 때 PopupWindow를 닫습니다. showAtLocation 전에 focusable을 true로 설정했는지 확인하십시오.


1
질문에 대한 정확한 답변을 제공하는 방법을 자세히 설명하기 위해 설명 텍스트를 추가하십시오. 감사.
philantrovert

감사! showAtLocation ()을 호출하기 전에 setter를 호출해야합니다.
droid256

5

isOutsideTouchable OR isFocusable 을 사용 하여 외부를 터치 할 때 팝업 창을 닫을 수 있습니다.

popupWindow.isOutsideTouchable = true // dismiss popupwindow when touch outside

popupWindow.isFocusable = true // dismiss popupwindow when touch outside AND when press back button

노트

  • 현재 테스트 후 팝업 창을 닫는 데 도움 setBackgroundDrawable 이되지 않습니다.

  • PopupWindow( PopupWindow->PopupDecorView->dispatchKeyEventPopupWindow->PopupDecorView->onTouchEvent) 에서 해제에 대한 코드를 보면 . 당신은 보도 뒤로 버튼, 그들은에 해고 할 때 것을 볼 ACTION_UP때 터치가에 기각 외부 ACTION_UP또는ACTION_OUTSIDE


4

@LunaKong 제안 작업은 매력 같다.

그러나 mPopupWindow.setFocusable (false) 설정 . 팝업창을 사라지게하는 데 필요한 불필요한 터치를 제거합니다.

예 : 화면에 팝업 창이 표시되고 버튼을 클릭하려고한다고 가정 해 보겠습니다. 따라서이 경우 (if mpopwindow.setFocusable (true)) 버튼을 처음 클릭 할 때 popupwindow가 닫힙니다. 그러나 버튼이 작동하도록하려면 다시 클릭해야합니다. if ** (mpopwindwo.setFocusable (false) ** 버튼을 한 번만 클릭 하면 팝업 창이 닫히고 버튼 클릭이 트리거 됩니다. 도움이 되기를 바랍니다 .


1
고맙습니다! 나는 정확히 똑같은 것을 찾고 있었다
Ganesh


3

창 배경을 투명하게 설정 :

PopupWindow.getBackground().setAlpha(0);

레이아웃에서 배경을 설정 한 후. 잘 작동합니다.


1
getBackground ()는 null 일 수 있습니다.
자레드 Rummler

1

어떤 경우에는 팝업을 포커스 가능하게 만드는 것이 바람직하지 않습니다 (예 : 다른 뷰에서 포커스를 훔치는 것을 원하지 않을 수 있음).

다른 방법은 터치 인터셉터를 사용하는 것입니다.

popupWindow.setOutsideTouchable(true);
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
            popupWindow.dismiss();
        }
        return false;
    }
});

0

View popupView를 사용하여 popupWindow를 닫습니다.

`popupView.setOnClickListener(new View.OnClickListener() {
                   @Override
                   public void onClick(View view) {
                       popupWindow.dismiss();
                   }
               }); 

`이것을 사용하면 popupWindow 내의 모든 버튼에 setOnClickListener를 설정할 수도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.