Android Spinner: Seçili öğe değiştirme etkinliğini al


407

Seçilen öğe değiştiğinde bir Spinner için olay dinleyicisini nasıl ayarlayabilirsiniz?

Temelde ne yapmaya çalışıyorum buna benzer bir şeydir:

spinner1.onSelectionChange = handleSelectionChange;

void handleSelectionChange(Object sender){
    //handle event
}

Bu cevapları denedim ama kimse yardımcı olmadı. Spinner bileşeni öğe tıklama etkinliklerini desteklemediğinde. Spinner Belgeleri

Yanıtlar:


812

Önceki cevaplardan bazıları doğru değil. Diğer widget'lar ve görünümler için çalışırlar, ancak Spinner widget'ının belgeleri açıkça şunları belirtir:

Bir değer değiştirici öğe tıklama etkinliklerini desteklemez. Bu yöntemin çağrılması bir istisna doğuracaktır.

Daha iyi kullanım OnItemSelectedListener () yerine:

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
        // your code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // your code here
    }

});

Bu benim için çalışıyor.

Görünüm oluşturulurken onItemSelected yönteminin de çağrıldığından, onCreate()yöntem çağrısının içine koymayı düşünebilirsiniz .


47
Bu sorun, görünüm oluşturulurken onItemSelected yöntemi de çağrılır olmasıdır. Böylece orada yazılan kod başlangıçta da yürütülür. İçeren kodu yalnızca kullanıcı tarafından çağrılan gerçek bir öğe seçimi varsa yürütmenin bir yolu var mı?
Kennethvr

39
aslında bu sorun setOnItemSelectedListener öğesini onCreate yöntemine değil, geçersiz kılma OnStart yöntemine koyarak çözülebilir. aptal bana ...
Kennethvr

16
Dinleyiciyi onStart yöntemine koydum, ancak kullanıcı herhangi bir şey görmeden önce çağrılıyor, tıpkı onCreate gibi, bu yüzden, benim durumumda, kullanıcı bir şey seçinceye kadar görünmez olması gereken bir "devam" düğmesinin olduğu, düğme ilk gösterimde görünür hale getirilir. Deneyiminizin farklı olduğunu mu söylüyorsunuz? Öyleyse, eksik olduğum onStart yönteminde farklı olarak ne yapıyorsunuz?
Yevgeny Simkin

7
İlk seçimi kaydetmek için anonim dinleyicinizin içinde başka bir alan kullanın ve bir seçim ile karşılaşılmadığı sürece onItemSelected'a hiçbir şey yapmamasını mı söylersiniz? Sadece bir düşünce.
Sam Svenbjorgchristiensensen

4
Ancak kullanıcı "varsayılan" öğeyi seçerse, en üstteki öğeyi seçer mi? Sonra onItemSelected(...)vurulmaz. (Biliyorum, çünkü bunu zor yoldan öğrendim.)
Andrew Wyld

55
Spinner spnLocale = (Spinner)findViewById(R.id.spnLocale);

spnLocale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
        // Your code here
    } 

    public void onNothingSelected(AdapterView<?> adapterView) {
        return;
    } 
}); 

Not: Bir şeyi hatırlayın.

Spinner OnItemSelectedListeneretkinliği iki kez yürütülür:

  1. Spinner başlatma
  2. Kullanıcı manuel olarak seçildi

Flag değişkenini kullanarak bu ikisini ayırt etmeye çalışın.


3
Benimki de iki kez çağrıldı! İkisini nasıl ayırdığınızı anlayamıyorum?
MAC

18
Sadece Boolean gibi küresel bir Boolean ayarlayın initialDisplay = true; Ve sonra onSelect'inizde doğru olup olmadığını görün ve eğer öyleyse, seçeceğiniz başka ne yapmayın, bir dahaki sefere çağrıldığında bayrağı yanlış olarak ayarlayın (kullanıcı gerçekten seçtiğinde).
Yevgeny Simkin

OnclickListener'ın yürütülmesi hakkında en iyi açıklama.
Pankaj Kumar

6
Şahsen çok basit bir şeyin - böyle temel bir UI widget'ının - uygulanması çok kanlı olduğu konusunda ciddiyim ... cidden - 'varsayılan gösteren öğe' özelliği oluşturmak ve nesneye Boolean bayrak özelliğini oluşturmak ne kadar zor olurdu sınıfın kendisi ?? Objective C hayranıyım ama iOS widget uygulamasının Android'de yaptığı sürenin yaklaşık 1 / 10'unu aldığını söyleyeceğim.
Bennett Von Bennett

4
Ben de katılıyorum. Spinner bir vidalı widget. Açılır pencerenin veya açığın ne zaman açık veya kapalı olduğunu bilmek çok zor. Bunun için bir etkinlik eklemek çok zor olurdu mı? Yukarıdaki çözüm ALMOST'un listenin ne zaman açık veya kapalı olduğunu ancak üç problemi olduğunu size söyleyebilir: (1) zaten seçilen öğeyi seçmek için bir etkinlik yoktur (ve liste kapanır) ve (2) iptal için bir etkinlik yoktur (dokunma kapatmak için liste dışı) ve (3) onNothingSelected benim için hiç ateş etmiyor gibi görünüyor.
Batdude

19

AdapterView.OnItemSelectedListenerEtkinliğinize sınıf uygulayabilirsiniz .

Ve sonra aşağıdaki satırı kullanın onCreate()

Spinner spin = (Spinner) findViewById(R.id.spinner);
spin.setOnItemSelectedListener(this);

Ardından bu iki yöntemi geçersiz kılın:

public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
    selection.setText(items[position]);
}

public void onNothingSelected(AdapterView<?> parent) {
    selection.setText("");
}

16

https://stackoverflow.com/q/1714426/811625

OnItemSelectedListener () yönteminin basit bir denetimle çağrılmasını önleyebilirsiniz: Geçerli seçim dizinini bir tamsayı değişkeninde saklayın ve bir şey yapmadan önce onItemSelected (..) içinde denetleyin.

Örneğin:

Spinner spnLocale;

spnLocale = (Spinner)findViewById(R.id.spnLocale);

int iCurrentSelection = spnLocale.getSelectedItemPosition();

spnLocale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
    if (iCurrentSelection != i){
            // Your code here
    }
    iCurrentSelection = i;
    } 

    public void onNothingSelected(AdapterView<?> adapterView) {
        return;
    } 
}); 

Nedeni iCurrentSelectionçalışmalarına bu nesne kapsamında olmalı!


1
Anonim bir iç sınıfta son olmayan bir değişkeni kullanamazsınız. Eğer iCurrentSelectiondeğişken bu anonim sınıf içinde bildirilmiş iyi çalışır. İlk çağrıda kodun yürütülmesi için -1 olarak başlatabilirsiniz.
dahvyd

2
@dahvyd doğru kullanırsanız int int nihai olmalıdır. Her durumda gerçekten iyi çalışıyor. Konum 0 seçilmemişse ve değiştirilmişse EditText alanını devre dışı bırakıyordum ve yeniden etkinleştirin. Bunun için teşekkürler.
natur3

8

Spinner adınızı bulun ve kimliği bulun ve ardından bu yöntemi uygulayın.

spinnername.setOnItemSelectedListener(new OnItemSelectedListener() {

    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
        // your code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // your code here
    }
});

8

OnIcreate veya onStart üzerinde OnItemSelectedListener'ı ayarlamanız önemli değil - yine de Etkinlik oluşturma veya başlatma sırasında (sırasıyla) çağrılır.
Böylece onCreate'de (ve onStart'da DEĞİL!)
İlk başlatmayı anlamak için bir bayrak ekleyin:

private Spinner mSpinner;
private boolean mSpinnerInitialized;

onCreate'de (veya onCreateView'da) sadece:

mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                if (!mSpinnerInitialized) {
                    mSpinnerInitialized = true;
                    return;
                }

                // do stuff
            }

            public void onNothingSelected(AdapterView<?> adapterView) {
                return;
            }
        });

1
Bu bayrağı kullandığınız için teşekkür ederiz.
Javan R.

7

Dönücü-widget'ı için belgeler

Bir değer değiştirici öğe tıklama etkinliklerini desteklemez.

setOnItemSelectedListenerSorununuzu çözmek için kullanmalısınız .


6
spinner1.setOnItemSelectedListener(
    new AdapterView.OnItemSelectedListener() {
        //add some code here
    }
);

1
Bu, geri çağrıcının ilk başlatıldığında çağrıldığı bu geri çağırma sorununu ele almaz (böylece, gerçekten seçilen bir öğeyle ilgisi olmayan bir yanıtı kışkırtır).
Yevgeny Simkin

4

mevcut spinner seçimi için global bir değişken alır:

int currentItem = 0;

spinner_counter = (Spinner)findViewById(R.id.spinner_counter);
String[] value={"20","40","60","80","100","All"};
aa=new ArrayAdapter<String>(this,R.layout.spinner_item_profile,value);
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_counter.setAdapter(aa);

spinner_counter.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if(currentItem == position){
                return; //do nothing
            }
            else
            {
                 TextView spinner_item_text = (TextView) view;
                 //write your code here
            }
            currentItem = position;
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

//R.layout.spinner_item_profile
<?xml version="1.0" encoding="utf-8"?>

<TextView  android:id="@+id/spinner_item_text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" 
android:layout_height="wrap_content"
android:background="@drawable/border_close_profile"
android:gravity="start"  
android:textColor="@color/black"         
android:paddingLeft="5dip"
android:paddingStart="5dip"
android:paddingTop="12dip"
android:paddingBottom="12dip"
/>

//drawable/border_close_profile
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
   <shape android:shape="rectangle">
    <solid android:color="#e2e3d7" />
   </shape>
 </item>
<item android:left="1dp"
android:right="1dp"
android:top="1dp"
android:bottom="1dp">
<shape android:shape="rectangle">
    <solid android:color="@color/white_text" />
</shape>
</item>
</layer-list>

4

Gerçek bir onChangedListener () istiyorsanız. Başlangıç ​​değerini işleyicide saklayın ve değişip değişmediğini kontrol edin. Bu basit ve yok değil global bir değişkeni gerekiyor. Sayfada birden fazla döndürücünüz varsa çalışır.

String initialValue = // get from Database or your object
mySpinner.setOnItemSelectedListener(new SpinnerSelectedListener(initialValue));

...

protected class SpinnerSelectedListener implements AdapterView.OnItemSelectedListener {

        private SpinnerSelectedListener() {
            super();
        }

        public SpinnerSelectedListener(String initialValue) {
            this();
            this.initialValue = initialValue;
        }

        private String initialValue;

        // getter and setter removed.  

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            final String newValue = (String) spinHeight.getItemAtPosition(position);
            if (newValue.equals(initialValue) == false) {
               // Add your code here.  The spinner has changed value. 

               // Maybe useful.   
               // initialValue = newValue;
            }

        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
               // Maybe useful.   
               // initialValue = null; 
        }
    }

Nesneler senin arkadaşın, onları kullan.


3
spinner.setOnItemSelectedListener(
            new AdapterView.OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> arg0, View arg1,
                        int arg2, long arg3) {

                    // TODO Auto-generated method stub
                }

                @Override
                public void onNothingSelected(AdapterView<?> arg0) {
                    // TODO Auto-generated method stub

                }
                //add some code here
            }
        );

1

Bu, spinner'ı ve findviewbyid'i intialize edecek ve kullanacak

    Spinner schemeStatusSpinner;

  schemeStatusSpinner = (Spinner) dialog.findViewById(R.id.spinner);

schemeStatusSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            // your code here
            if(schemeStatusSpinner.getSelectedItemId()==4){
                reasonll.setVisibility(View.VISIBLE);
            }
            else {
                reasonll.setVisibility(View.GONE);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
            // your code here
        }

    });

1

Bence ne iyi yolu bir sahip olacaktır flagitemselected = 0;in onCreate(). Ve öğe işaretli olay artışı yani bayrak flagitemselected++; ve sonra kontrol et

if(flagitemselected!=1)
{
// do your work here
}

Sanırım bu yardımcı olacak.


0

Bulduğum bir numara, setOnItemSelectedListeners'ınızı onCreate yerine onWindowFocusChanged'e koymaktı. Bunu bu şekilde yapmak için herhangi bir kötü yan etki bulamadım. Temel olarak, pencere çizildikten sonra dinleyicileri ayarlayın. WindowsFocusChanged'in ne sıklıkta çalıştığından emin değilim, ancak çok sık çalıştığını düşünüyorsanız kendinize bir kilit değişkeni oluşturmak kolaydır.

Android'in mesaj tabanlı bir işlem sistemi kullanıyor olabileceğini düşünüyorum ve hepsini onCreate'a koyarsanız, döndürücünün çizildikten sonra doldurulduğu durumlarla karşılaşabilirsiniz. Böylece, öğenin konumunu ayarladıktan sonra dinleyiciniz ateşlenir. Bu elbette eğitimli bir tahmindir, ancak beni bu konuda düzeltmekten çekinmeyin.


0

Varsayılan olarak, spinner dizisinin ilk öğesini

value = spinner.getSelectedItem().toString();

Değer değiştiricideki değeri seçtiğinizde, size seçilen değeri verir

eğer seçilen öğenin pozisyonunu istiyorsanız o zaman böyle yapın

pos = spinner.getSelectedItemPosition();

yukarıdaki iki cevap dinleyici uygulamadan

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.