PopupWindow - Dışarıda tıklandığında kapat


95

Aktivitemde bir PopupWindow var, mesele şu ki PopupWindow'um aktivitemle etkileşim kurduğumda bile hala görünüyor (listemde kaydırma deyin). Listemde gezinebilirim ve PopupWindow hala orada.

Elde etmek istediğim şey, PopupWindow olmayan ekranda / vb. Üzerine dokunduğumda / kaydırdığımda / tıkladığımda, PopupWindow'u kapatmak istiyorum. Tıpkı bir menünün nasıl çalıştığı gibi. Menünün dışına tıklarsanız, menü kapatılacaktır.

Denedim setOutsideTouchable(true)ama pencereyi kapatmayacak . Teşekkürler.

Yanıtlar:


131

Kümesine deneyin setBackgroundDrawableüzerinde PopupWindowdışarıda bunun dokunursanız penceresini kapatmak gerektiğini söyledi.


5
Özledim PopupWindow'unuzda setBackgroundDrawable kullanıyor musunuz? Arka planı boş olarak ayarlamanın OnTouchListener
Marcin

31
bu kadar! teşekkürler adamım! bu durumda, dokunma olayları bile doğru şekilde işlenebilir. popupWindow.setOutsideTouchable (true); popupWindow.setTouchable (true); popupWindow.setBackgroundDrawable (yeni BitmapDrawable ()); popupWindow.setTouchInterceptor (new OnTouchListener () {@Override public boolean onTouch (View v, MotionEvent olayı) {if (AppContext.isDebugMode ()) Log.d ("POPUP_WINDOW", "v:" + v.getTag () + " | olay: "+ event.getAction ()); popupWindow.dismiss (); dönüş true;}});
beerstorm

3
Arka plan çizilebilirliğini null olarak ayarlamak benim için çalışmıyor. Başka birinin sorunu varsa cevabıma bakın.
mpellegr

2
@WareNinja, yorumunuz işe yaradı! Belki bir cevabın tamamını bu soruya bıraksanız daha iyi olur, diğerleri için faydalı olur
Anton Kizema

3
@WareNinja BitmapDrawable()depricated. ColorDrawable()Bunun yerine kullanın .
Srujan Barai

127

WareNinja'nın kabul edilen cevap hakkındaki yorumu dışında verilen cevaplardan hiçbirinin benim için işe yaramadığını ve Marcin S.'nin de muhtemelen işe yarayacağını buldum. İşte benim için çalışan kısım:

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

Alternatif olarak:

myPopupWindow.setFocusable(true);

Farklılıkların ne olduğundan emin değilim, ancak ListPopupWindow kaynak kodu aslında modalitesi setModal ile doğru olarak ayarlandığında ikincisini kullanıyor, bu nedenle en azından Android geliştiricileri bunu uygun bir yaklaşım olarak görüyor ve bu sadece bir satır.


6
Çok teşekkür ederim. Diğer cevapların hiçbiri benim için işe yaramadı veya yeterince iyi açıklamadı. İkinci seçenek benim için işe yaramıyor.
JDN

2
Ayrıca BitmapDrawable'ın kullanımdan kaldırıldığını da not ediyorum. Soruna gerçek bir çözüme sahip olmak güzel olurdu, çünkü bunlar daha yeni API sürümlerinde destekleneceği garanti edilmeyen geçici bir çözüm gibi görünüyor.
HAL9000

BitmapDrawable'ın kullanımdan kaldırılmış yapıcısını kullanmamak için buraya bakın: stackoverflow.com/a/21680637/2048266 . popupWindow.setBackgroundDrawable (yeni BitmapDrawable (getResources (), ""));
nommer

Alternatif yöntemini kullanırken, setFocusabledüğmeye iki kez tıklamamız gerekir (düğmenin açılır pencerenin dışına yerleştirildiği yer) burada 1. yöntemde olduğu gibi iyi çalışıyor :)
Joy Rex

BitmapDrawable()depricated. ColorDrawable()Bunun yerine kullanın .
Srujan Barai

61

Aynı sorunlarla karşılaştım ve aşağıdaki kodlarla düzelttim. Benim için iyi çalışıyor.

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

BTW, BitmapDrawable kullanımdan kaldırılmış yapıcıyı kullanmayın, varsayılan arka planı değiştirmek için bu yeni ColorDrawable'ı (android.R.color.transparent) kullanın.

İyi eğlenceler@.@


3
PopoupWindow
snersesyan

Pop-up'ın odaklanmaya ihtiyacı yoksa gerçekten odaklanabilirliği doğru olarak ayarlamam gerekir mi?
Levor

Bunun işe yaramasına şaşırdım, ancak API 21'de gerekli. Bu aynı zamanda açılır penceremin yanlış şekilde animasyon göstermesi sorununu da giderdi.
EpicPandaForce

24

Geç olduğunu biliyorum, ancak insanların hala açılır pencereyle ilgili bir sorunu olduğunu fark ettim. Açılır pencereyi dokunarak veya dışını tıklayarak veya sadece pencerenin kendisine dokunarak kapatabileceğiniz, tamamen çalışan bir örnek yazmaya karar verdim. Bunu yapmak için yeni bir PopupWindow sınıfı oluşturun ve bu kodu kopyalayın:

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

Şimdi açılır pencere için düzeni oluşturun: 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>      

Ana etkinliğinizde PopupWindow sınıfının bir örneğini oluşturun:

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

YOUR_MAIN_LAYOUT, popupWindow'un açılacağı mevcut etkinliğin düzenidir


1
Teşekkürler - bu benim için çalıştı. Sadece küçük bir not, özel sınıfınız için PopupWindow dışında başka bir ad kullanmaktır, belki buna Popupwindow yerine MyPopupWindow diyebilirsiniz, böylece android, standart android sınıfınız ile özel sınıfınız arasında karışmaz.
Simon

@Marcin S. findViewById (R.id.YOUR_MAIN_LAYOUT) ?? R.layout.My_Layout
Ankesh kumar Jaisansaria

@Simon findViewById (R.id.YOUR_MAIN_LAYOUT) ?? R.layout.My_Layout olacak mı?
Ankesh kumar Jaisansaria

15

@ LunaKong'un yanıtı ve @ HourGlass'ın onayı için teşekkürler. Yinelenen bir yorum yapmak istemiyorum, ancak yalnızca açık ve kısa olmasını istiyorum.

// 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.


Açılır pencerenin dışına tıklayarak kapatabilmek istedim, ancak yaptığımda altındaki görünümler (açılır pencerenin bir parçası değil, etkinliğin bir parçası) tıklanıyordu. setFocusabl (true) aradığım şeydi. Teşekkürler!
hellaandrew

@hellaandrew, yardımcı olmanıza sevindim :)
Nguyen Tan Dat

8

Bir ListPopupWindowküme için, pencere gösterildiğinde modal olacaktır.

mListPopupWindow.setModal(true);

Bu şekilde, dışını tıklamak ListPopupWindowonu reddeder.


Teşekkürler, sadece bununla ilgileniyordum. Bu sadece listpopuppenceresini görünümün dışına dokunduktan sonra kapatılamaz hale getirmekle kalmaz, aynı zamanda dokunma olayını liste penceresinin yanındaki diğer görünümlere de geçirmez. Çaresizce bunu arıyordum, çünkü benim durumumda listpopwindow'a dokunmak olayı listpopupindow'u kapatmanın yanındaki geri dönüşümlü görünüme geçiriyor ve geri dönüşümlü görüntüleme öğesi istemediğim bir şekilde seçiliyordu.
shankar_vl

Ayrıca mListPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);, açılır pencerenin ekran klavyesine müdahale etmesini önlemek için de ihtiyacınız olabilir .
Mr-IDE

6

İle iptal popupWindow.setOutsideTouchable(true)etmek için wrap_contentaşağıdaki kod gibi genişlik ve yükseklik yapmanız gerektiğine dikkat edin :

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

Ekranda tıklandığında / dokunduğunda PopupWindow'u kapatır. ShowAtLocation'dan önce odaklanabilirliği doğru ayarladığınızdan emin olun.


1
Lütfen bunun sorulan soruya nasıl doğru bir cevap verdiğini detaylandırmak için biraz açıklayıcı metin ekleyin. Teşekkürler.
philantrovert

Teşekkürler! ShowAtLocation () öğesini çağırmadan önce ayarlayıcıları aramanız gerekir.
droid256

5

Sen kullanabilirsiniz isOutsideTouchable VEYA isFocusable dissmiss Pop-up penceresine zaman dokunmatik dışında

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

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

Not

  • Şu anda, testten sonra açılır pencereyi kapatmamıza yardımcı setBackgroundDrawable olmadığını görüyorum

  • PopupWindow( PopupWindow->PopupDecorView->dispatchKeyEventVe PopupWindow->PopupDecorView->onTouchEvent) 'de görevden alma koduna bakarsanız Geri düğmesine bastığında, kapandıklarını ACTION_UPve dışarıya dokunduklarında kapatıldıklarını ACTION_UPveyaACTION_OUTSIDE


4
mPopWindow.setFocusable(true);

1
Gerekli olan tek şey bu. Kabul edilen cevabın neden bu kadar ağır bir şekilde oy verildiğini anlamıyorum.
sziraqui

4

@LunaKong önerisi bir cazibe gibi.

Ancak mPopupWindow.setFocusable (false) ayarlanıyor. açılır pencerenin kaybolması için gerekli olan gereksiz dokunuşu kaldırır.

Örneğin: Ekranda görünen bir açılır pencere olduğunu ve bir düğmeye tıklamak üzeresiniz diyelim. Dolayısıyla bu durumda, (eğer mpopwindow.setFocusable (true)) bir düğmenin ilk tıklandığında açılır pencere kapatılır. Ancak düğmenin çalışması için tekrar tıklamanız gerekir. eğer ** (mpopwindwo.setFocusable (false) ** düğmeye tek tıklama açılır pencereyi kapatır ve düğme tıklamasını tetikler. Umarım yardımcı olur.


1
Çok teşekkürler! Tam olarak aynısını arıyordum
Ganesh

3

Pencere arka planını şeffaf olarak ayarlayın:

PopupWindow.getBackground().setAlpha(0);

Arka planınızı düzende ayarladıktan sonra. İyi çalışıyor.


1
getBackground () boş olabilir.
Jared Rummler

1

Bazı durumlarda, pop-up'ı odaklanabilir hale getirmek arzu edilmez (örneğin, başka bir görünümden odağı çalmasını istemeyebilirsiniz).

Alternatif bir yaklaşım, bir dokunma engelleyici kullanmaktır:

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

1

Bu Açılır Pencere başka bir etkinlikse ve boyutunu orijinal ekrana düşürdüyseniz ve dış alanı etkinleştirmek veya devre dışı bırakmak istiyorsanız, bu kodla dış alanı kolayca etkinleştirebilir veya devre dışı bırakabilirsiniz:

etkinleştirme:

YourActivity.this.setFinishOnTouchOutside(true);

devre dışı bırak:

YourActivity.this.setFinishOnTouchOutside(false);


0

PopupWindow'u kapatmak için Açılır pencereyi Görüntüle'yi kullanın

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

`Bunu kullanırsanız, ayrıcaOnClickListener öğesini popupWindow içindeki herhangi bir düğmeye ayarlayabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.