İlk metni “Birini Seçin” ile bir Android Spinner nasıl yapılır?


569

Başlangıçta (kullanıcı henüz bir seçim yapmadıysa) "Birini Seç" metnini görüntüleyen bir Spinner kullanmak istiyorum. Kullanıcı döndürücüyü tıklattığında, öğelerin listesi görüntülenir ve kullanıcı seçeneklerden birini seçer. Kullanıcı bir seçim yaptıktan sonra, seçilen öğe Spinner'da "Birini Seç" yerine görüntülenir.

Bir Spinner oluşturmak için aşağıdaki kodu var:

String[] items = new String[] {"One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

Bu kodla, başlangıçta "One" öğesi görüntülenir. Öğelere yeni bir öğe "Birini Seçin" ekleyebilirim, ancak daha sonra açılan listede ilk öğe olarak "Birini Seçin" de görüntülenir, bu benim istediğim şey değil.

Bu sorunu nasıl düzeltebilirim?


6
Mükemmel çözüm bu soruda yatmaktadır: stackoverflow.com/questions/9863378/… getDropDownView () yöntemini geçersiz kılın.
Sourab Sharma

Adaptörünüzün ilk elemanını "Birini Seç" olarak ayarlamayı denediniz mi?
IgorGanapolsky

[İşte başka harika bir çözüm!] [1] [1]: stackoverflow.com/questions/9863378/…
AirtonCarneiro

yeniden kullanılabilir spinner: github.com/henrychuangtw/ReuseSpinner
HenryChuang

Yanıtlar:


255

İşte Spinnergörüşü geçersiz kılan genel bir çözüm . setAdapter()Başlangıç ​​konumunu -1 olarak ayarlamak için geçersiz kılınır ve SpinnerAdapter0'dan küçük konum için bilgi istemi dizesini görüntülemek üzere verilen proxy'leri kullanır.

Bu Android 1.5 ila 4.2 üzerinde test edilmiştir, ancak alıcı dikkat! Bu çözüm, özel kişiyi aramak için yansımayı temel aldığından AdapterView.setNextSelectedPositionInt()ve AdapterView.setSelectedPositionInt()gelecekteki işletim sistemi güncellemelerinde çalışacağı garanti edilmez. Muhtemelen olacak gibi görünüyor, ancak hiçbir şekilde garanti edilmez.

Normalde böyle bir şeyi göz ardı etmem, ama bu soru yeterince kez soruldu ve çözümümü göndereceğimi düşündüğüm makul bir istek gibi görünüyor.

/**
 * A modified Spinner that doesn't automatically select the first entry in the list.
 *
 * Shows the prompt if nothing is selected.
 *
 * Limitations: does not display prompt if the entry list is empty.
 */
public class NoDefaultSpinner extends Spinner {

    public NoDefaultSpinner(Context context) {
        super(context);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setAdapter(SpinnerAdapter orig ) {
        final SpinnerAdapter adapter = newProxy(orig);

        super.setAdapter(adapter);

        try {
            final Method m = AdapterView.class.getDeclaredMethod(
                               "setNextSelectedPositionInt",int.class);
            m.setAccessible(true);
            m.invoke(this,-1);

            final Method n = AdapterView.class.getDeclaredMethod(
                               "setSelectedPositionInt",int.class);
            n.setAccessible(true);
            n.invoke(this,-1);
        } 
        catch( Exception e ) {
            throw new RuntimeException(e);
        }
    }

    protected SpinnerAdapter newProxy(SpinnerAdapter obj) {
        return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),
                new Class[]{SpinnerAdapter.class},
                new SpinnerAdapterProxy(obj));
    }



    /**
     * Intercepts getView() to display the prompt if position < 0
     */
    protected class SpinnerAdapterProxy implements InvocationHandler {

        protected SpinnerAdapter obj;
        protected Method getView;


        protected SpinnerAdapterProxy(SpinnerAdapter obj) {
            this.obj = obj;
            try {
                this.getView = SpinnerAdapter.class.getMethod(
                                 "getView",int.class,View.class,ViewGroup.class);
            } 
            catch( Exception e ) {
                throw new RuntimeException(e);
            }
        }

        public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
            try {
                return m.equals(getView) && 
                       (Integer)(args[0])<0 ? 
                         getView((Integer)args[0],(View)args[1],(ViewGroup)args[2]) : 
                         m.invoke(obj, args);
            } 
            catch (InvocationTargetException e) {
                throw e.getTargetException();
            } 
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        protected View getView(int position, View convertView, ViewGroup parent) 
          throws IllegalAccessException {

            if( position<0 ) {
                final TextView v = 
                  (TextView) ((LayoutInflater)getContext().getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE)).inflate(
                      android.R.layout.simple_spinner_item,parent,false);
                v.setText(getPrompt());
                return v;
            }
            return obj.getView(position,convertView,parent);
        }
    }
}

7
@emmby Kullanıcı ayarladıktan sonra seçimi nasıl temizleyeceğinize dair bir fikriniz var mı? Bir clearSelection () yöntemine iki invoke () çağrıları yeniden düzenleme denedim, ama gerçekten çalışmıyor. Açılır liste daha önce seçilen öğeyi seçili olarak göstermese de, döndürücü widget'ı yine de seçildiği gibi gösterir ve kullanıcı aynı öğeyi tekrar seçerse onItemSelected () çağrılmaz.
Qwertie

3
bazıları sınıfın üstünde nasıl kullanıldığını açıklayabilir mi?
Bishan

4
Bu çözüm, android: girişleri kullanarak Android 4.2'de (Cyanogenmod 10.1)% 100 mükemmel değildir. Şişirilmiş TextView yüksekliği, varsayılan Bağdaştırıcının şişirdiği kaynağın yüksekliğinden daha küçüktür. Yani, gerçekten bir seçenek seçtiğinizde, Galaxy S'mde yükseklik kabul edilir, ~ 10 piksel, bu kabul edilemez. Birkaç şey denedim (yerçekimi, dolgu, marj, vb.) Ve hiçbiri cihazlarda güvenilir bir şekilde çalışmadı, bu yüzden farklı bir çözüm seçeceğim.
Maragues

3
@DavidDoria Düzen dosyanızda NoDefaultSpinner sınıfını kullanmanız gerekir. Kaynağı yukarıdan projenize, örneğin com.example.customviews paketine kopyalayın. Şimdi mizanpajınızda xml'de, <Spinner ...> yerine <com.example.customviews.NoDefaultSpinner ...> kullanın Kodun geri kalanı aynı kalabilir. Düzeninizde <com.example.customviews.NoDefaultSpinner> görünümüne android: istem özniteliğini eklemeyi unutmayın.
Ridcully

2
@emmby spinnerBrand.setSelection (-1); çalışmıyor
Sachin C

291

Yapabileceğiniz şey, SpinnerAdapterSpinner'ın seçilen hiçbir şey olmadan görüntülenmesi için başlangıçta bir 'Seçeneği Seç ...' görünümü sunan bir şeyle süslemektir .

İşte Android 2.3 ve 4.0 için test edilmiş bir çalışma örneği (uyumluluk kütüphanesinde hiçbir şey kullanmıyor, bu yüzden bir süre için iyi olmalı) Bir dekoratör olduğundan, mevcut kodu uyarlamak kolay olmalı ve CursorLoaders ile de iyi çalışmalıdır . ( cursorAdapterTabii sarılı üzerinde imleci değiştir ...)

Bu, görünümleri yeniden kullanmak için biraz daha zor hale getiren bir Android hatası var. (Bu nedenle , doğru setTagolduğundan emin olmak için veya başka bir şey kullanmanız gerekir convertView.) Spinner çoklu görünüm türlerini desteklemiyor

Kod notları: 2 kurucu

Bu, standart bir bilgi istemi kullanmanıza veya kendi 'seçilen hiçbir şeyi' ilk satır olarak veya her ikisini birden tanımlamanıza veya hiçbirini tanımlamanıza olanak tanır. (Not: Bazı temalar iletişim kutusu yerine bir Dönücü için bir Açılır menü gösterir. Açılır menü normalde istemi göstermez)

Bir istem gibi görünecek bir düzen tanımlarsınız, örneğin gri renkte ...

Başlangıçta hiçbir şey seçilmedi

Standart bir bilgi istemi kullanma (hiçbir şeyin seçili olmadığına dikkat edin):

Standart bir istemle

Veya bir bilgi istemi ve dinamik bir şeyle (hiçbir bilgi istemi olmayabilir):

Bilgi istemi ve hiçbir satır seçilmedi

Yukarıdaki örnekte kullanım

Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setPrompt("Select your favorite Planet!");

spinner.setAdapter(
      new NothingSelectedSpinnerAdapter(
            adapter,
            R.layout.contact_spinner_row_nothing_selected,
            // R.layout.contact_spinner_nothing_selected_dropdown, // Optional
            this));

contact_spinner_row_nothing_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    style="?android:attr/spinnerItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textSize="18sp"
    android:textColor="#808080"
    android:text="[Select a Planet...]" />

NothingSelectedSpinnerAdapter.java

import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;

/**
 * Decorator Adapter to allow a Spinner to show a 'Nothing Selected...' initially
 * displayed instead of the first choice in the Adapter.
 */
public class NothingSelectedSpinnerAdapter implements SpinnerAdapter, ListAdapter {

    protected static final int EXTRA = 1;
    protected SpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;

    /**
     * Use this constructor to have NO 'Select One...' item, instead use
     * the standard prompt or nothing at all.
     * @param spinnerAdapter wrapped Adapter.
     * @param nothingSelectedLayout layout for nothing selected, perhaps
     * you want text grayed out like a prompt...
     * @param context
     */
    public NothingSelectedSpinnerAdapter(
      SpinnerAdapter spinnerAdapter,
      int nothingSelectedLayout, Context context) {

        this(spinnerAdapter, nothingSelectedLayout, -1, context);
    }

    /**
     * Use this constructor to Define your 'Select One...' layout as the first
     * row in the returned choices.
     * If you do this, you probably don't want a prompt on your spinner or it'll
     * have two 'Select' rows.
     * @param spinnerAdapter wrapped Adapter. Should probably return false for isEnabled(0)
     * @param nothingSelectedLayout layout for nothing selected, perhaps you want
     * text grayed out like a prompt...
     * @param nothingSelectedDropdownLayout layout for your 'Select an Item...' in
     * the dropdown.
     * @param context
     */
    public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter,
            int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) {
        this.adapter = spinnerAdapter;
        this.context = context;
        this.nothingSelectedLayout = nothingSelectedLayout;
        this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
        layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public final View getView(int position, View convertView, ViewGroup parent) {
        // This provides the View for the Selected Item in the Spinner, not
        // the dropdown (unless dropdownView is not set).
        if (position == 0) {
            return getNothingSelectedView(parent);
        }
        return adapter.getView(position - EXTRA, null, parent); // Could re-use
                                                 // the convertView if possible.
    }

    /**
     * View to show in Spinner with Nothing Selected
     * Override this to do something dynamic... e.g. "37 Options Found"
     * @param parent
     * @return
     */
    protected View getNothingSelectedView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedLayout, parent, false);
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 -
        // Spinner does not support multiple view types
        if (position == 0) {
            return nothingSelectedDropdownLayout == -1 ?
              new View(context) :
              getNothingSelectedDropdownView(parent);
        }

        // Could re-use the convertView if possible, use setTag...
        return adapter.getDropDownView(position - EXTRA, null, parent);
    }

    /**
     * Override this to do something dynamic... For example, "Pick your favorite
     * of these 37".
     * @param parent
     * @return
     */
    protected View getNothingSelectedDropdownView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedDropdownLayout, parent, false);
    }

    @Override
    public int getCount() {
        int count = adapter.getCount();
        return count == 0 ? 0 : count + EXTRA;
    }

    @Override
    public Object getItem(int position) {
        return position == 0 ? null : adapter.getItem(position - EXTRA);
    }

    @Override
    public int getItemViewType(int position) {
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        return 1;
    }

    @Override
    public long getItemId(int position) {
        return position >= EXTRA ? adapter.getItemId(position - EXTRA) : position - EXTRA;
    }

    @Override
    public boolean hasStableIds() {
        return adapter.hasStableIds();
    }

    @Override
    public boolean isEmpty() {
        return adapter.isEmpty();
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        adapter.registerDataSetObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        adapter.unregisterDataSetObserver(observer);
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return position != 0; // Don't allow the 'nothing selected'
                                             // item to be picked.
    }

}

52
Bu, soruna zarif bir çözümdür. Kod tam olarak projeme kopyalanmış gibi çalışır. Yansıma gerektirmeyen +1.
Richard Le Mesurier

2
Bu harika bir çözüm. Herhangi bir öğe, bir öğe seçilmeden önce değil, her zaman getView () çağrısında başlığın nasıl geçersiz kılınacağını bilmek isterse, getNothingSelectedView'ı (veya başka bir özel görünümü) her zaman döndürmeniz yeterlidir. Açılır liste, bağdaştırıcınızdaki öğelerle doldurulmaya devam edecektir, ancak artık bir şey seçildikten SONRA başlığı da kontrol edebilirsiniz.
OldSchool4664

6
Bu, olmaması gereken bir problem için gerçekten zarif bir çözümdür (Iphone geliştirmeyi deneyin). Harika ve teşekkürler! Birisinin desenleri hatırladığına sevindim
user1700737

3
@prashantwosti, kod Lollipop ile çalışacak şekilde güncellendi. Özellikle getItemViewType () ve getViewTypeCount ().
aaronvargas

3
@aaronvargas bir kez spinner'dan bir öğe seçip geri alabilir ve "[Bir gezegen seç]" i seçebilir miyim?
modabeckham

130

Bunun Buttonyerine bir sona erdi . A bir Buttonolmasa da Spinner, davranışı özelleştirmek kolaydır.

Önce Adaptörü her zamanki gibi oluşturun:

String[] items = new String[] {"One", "Two", "Three"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_spinner_dropdown_item, items);

simple_spinner_dropdown_itemDüzen kimliği olarak kullandığımı unutmayın . Bu, uyarı iletişim kutusunu oluştururken daha iyi bir görünüm oluşturmanıza yardımcı olacaktır.

Benim Düğme için onClick işleyicisinde var:

public void onClick(View w) {
  new AlertDialog.Builder(this)
  .setTitle("the prompt")
  .setAdapter(adapter, new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {

      // TODO: user specific action

      dialog.dismiss();
    }
  }).create().show();
}

Ve bu kadar!


10
Bu cevaba katılıyorum. Ayrıca, bir Spinner'dan çok daha kolay bir düğme stili.
Romain Piel

@HRJ Ben önerilen şekilde uyguladım, ama daha önce seçilen öğe vurgulanmıyor (radyo düğmesi ortada greeen nokta ile vurgulanmalıdır anlamına gelir) .... Bunu OnClick () yönteminde nasıl elde edebilirim buton. Lütfen bana
HRJ

2
Bu düzene sahip düğme mükemmel <Düğme android: id = "@ + kimlik / şehir" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: layout_margin = "5dp" android: gravity = "sol" android: background = "@ android: çekilebilir / btn_dropdown" android: metin = "@ string / city_prompt" />
kml_ckr

Daha sonra, düğmenin metnini, bir çeviricide olduğu gibi seçimi yansıtacak şekilde nasıl güncellersiniz?
shim

3
sorun çözümü: SetAdapter yerine SetSingleChoiceItems kullanın
Grzegorz Dev

67

İlk olarak, sınıfın promptniteliğiyle ilgileniyor olabilirsiniz Spinner. Aşağıdaki resme bakın, "Bir Gezegen Seçin" ile XML'de ayarlanabilen bilgi istemidir android:prompt="".

resim açıklamasını buraya girin

İçeride Spinneriki adaptörü koruyabileceğiniz alt sınıf önerecektim . "Birini Seç" seçeneğine sahip bir adaptör ve diğer gerçek adaptör (gerçek seçeneklerle), ardından OnClickListenerseçenekler iletişim kutusu gösterilmeden önce adaptörleri değiştirmek için. Ancak, bu fikri uygulamaya çalıştıktan sonra OnClick, widget'ın kendisi için olayları alamayacağınız sonucuna varıyorum .

Dönücüyü farklı bir görünümde sarabilir, görünümdeki tıklamalara müdahale edebilir ve ardından CustomSpinnerbağdaştırıcınızı değiştirmenizi söyleyebilirsiniz , ancak korkunç bir hack gibi görünüyor.

Gerçekten "Birini Seç" i göstermeniz mi gerekiyor?


36
Bu sadece "Birini Seçin" i gösterme gereği değil, aynı zamanda eğirme değerinin isteğe bağlı olarak boş bırakılabileceği durumu da ele alır.
greg7gkb

5
Ayrıca, bu seçenekle, Dünya herhangi bir şey seçilmeden önce Spinner'da seçim olarak gösterilir, benim uygulama için kullanıcı henüz bir şey seçmediklerini söyleyebilirim
seçmediklerini dylan murphy 17:30

2
bu soruya gerçekten cevap vermiyor. insanlar, bu örnekte gezegenler listesindeki ilk öğe yerine varsayılan olarak "Birini Seç" i döndürücüye sahip olmanın bir yolunu arıyorlar
JMRboosties

58

Bu kod test edildi ve Android 4.4'te çalışıyor

resim açıklamasını buraya girin

Spinner spinner = (Spinner) activity.findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, android.R.layout.simple_spinner_dropdown_item) {

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {

                View v = super.getView(position, convertView, parent);
                if (position == getCount()) {
                    ((TextView)v.findViewById(android.R.id.text1)).setText("");
                    ((TextView)v.findViewById(android.R.id.text1)).setHint(getItem(getCount())); //"Hint to be displayed"
                }

                return v;
            }       

            @Override
            public int getCount() {
                return super.getCount()-1; // you dont display last item. It is used as hint.
            }

        };

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        adapter.add("Daily");
        adapter.add("Two Days");
        adapter.add("Weekly");
        adapter.add("Monthly");
        adapter.add("Three Months");
        adapter.add("HINT_TEXT_HERE"); //This is the text that will be displayed as hint.


        spinner.setAdapter(adapter);
        spinner.setSelection(adapter.getCount()); //set the hint the default selection so it appears on launch.
        spinner.setOnItemSelectedListener(this);

getItem(getCount())benim için altı çizili kırmızı mı? Yöntem seti çözümlenemiyor
Zapnologica

Bir şüphe var, bu iş parçacığında birçok çözüm gördüm ... ama neden herkes son ipucu ekliyor. İlk satıra ipucu eklemek yanlış mı?
akashPatra

'SetOnItemSelectedListener (this);' ayarlayamıyorum; çünkü kullanıyorum 'uygular NavigationView.OnNavigationItemSelectedListener', 'setOnItemSelectedListener (this)' i kaldırabilir miyim; herhangi bir sorun olmadan?
CGR

@akashpatra En son ipuçlarını eklemelerinin nedeni, spinner için ArrayAdapter'ın değerlerini çalışma zamanında farklı kaynaklardan alabilmesidir.
17:43

bu gerçekten bana yardımcı oldu
sunil

31

Bu çözümü buldum:

String[] items = new String[] {"Select One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
        items[0] = "One";
        selectedItem = items[position];
    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
    }
});

Sadece [0] dizisini "Birini Seç" ile değiştirin ve onItemSelected öğesinde "One" olarak yeniden adlandırın.

Şık bir çözüm değil, ama işe yarıyor: D


5
Bu benim için işe yaramadı. "Bir" öğesini seçtikten sonra hala "Birini Seç" yazıyor.
Leo Landau

Bu alışkanlık neden onItemSelected arabirimi her zaman ilk kez arayacaktır.
Vaibhav Kadam

20

Spinner'da ipucu ayarlamak için varsayılan bir API yoktur. Eklemek için, güvenlik yansıması uygulamasının olmadığı küçük bir geçici çözüme ihtiyacımız var

List<Object> objects = new ArrayList<Object>();
objects.add(firstItem);
objects.add(secondItem);
// add hint as last item
objects.add(hint);

HintAdapter adapter = new HintAdapter(context, objects, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

Spinner spinnerFilmType = (Spinner) findViewById(R.id.spinner);
spinner.setAdapter(adapter);

// show hint
spinner.setSelection(adapter.getCount());

Adaptör kaynağı:

public class HintAdapter
        extends ArrayAdapter<Objects> {

    public HintAdapter(Context theContext, List<Object> objects) {
        super(theContext, android.R.id.text1, android.R.id.text1, objects);
    }

    public HintAdapter(Context theContext, List<Object> objects, int theLayoutResId) {
        super(theContext, theLayoutResId, android.R.id.text1, objects);
    }

    @Override
    public int getCount() {
        // don't display last item. It is used as hint.
        int count = super.getCount();
        return count > 0 ? count - 1 : count;
    }
}

Orjinal kaynak


R.id.text1 nedir? herhangi bir düzen veya görünüm var mı? Cevabınızı lütfen ortaya
Anand Savjani

O olmalıandroid.R.id.text1
Yakiv Mospan

Bir şüphe var, bu iş parçacığında birçok çözüm gördüm ... ama neden herkes son ipucu ekliyor. İlk satıra ipucu eklemek yanlış mı?
akashPatra

@akashpatra Tam hatırlamıyorum, ancak ilk öğe listesi olarak yapmaya çalıştığımda bir sorun vardı gibi görünüyor. Her neyse her zaman deneyebilir ve burada yorum yapabilirsiniz, buradaki tüm sihir getCountyöntem etrafında
Yakiv Mospan

@YakivMospan Bunu kullandığımda, muhtemelen ProGuard kullanırken Yansıma nedeniyle bir NPE alıyorum. Bunu nasıl düzeltebileceğinizi biliyor musunuz?
Alan

17

Burada birçok cevap var ama kimsenin basit bir çözüm önermediğine şaşırdım: Spinner'ın üstüne bir TextView yerleştirin. TextView'da Spinner'ı gösteren ve spinner.performClick () öğesini çağıran TextView üzerinde bir tıklama dinleyicisi ayarlayın.


9

Boş bir seçim ile spinner için de aynı problemi yaşadım ve daha iyi bir çözüm buldum. Bu basit koda bir göz atın.

Spinner lCreditOrDebit = (Spinner)lCardPayView.findViewById(R.id.CARD_TYPE);
spinneradapter lAdapter = 
  new spinneradapter(
    BillPayScreen.this, 
    ndroid.R.layout.simple_spinner_item,getResources().getStringArray(R.array.creditordebit));
lAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
lCreditOrDebit.setAdapter(lAdapter);

Burada spinneradapter arrayadapter için küçük bir özelleştirmedir. Şöyle görünüyor:

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

public class spinneradapter extends ArrayAdapter<String>{
    private Context m_cContext;
    public spinneradapter(Context context,int textViewResourceId, String[] objects) {
        super(context, textViewResourceId, objects);
        this.m_cContext = context;
    }

    boolean firsttime = true;
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(firsttime){
            firsttime = false;
            //Just return some empty view
            return new ImageView(m_cContext);
        }
        //Let the array adapter take care of it this time.
        return super.getView(position, convertView, parent);
    }
}

6
Bu yaklaşımla ilgili sorun, liste açıldığında hala listedeki ilk öğeyi seçmesidir. Zaten seçili olduğu için seçmek için dokunamazsınız - seçilen hiç olmamış gibi davranır.
jwadsack

7

Metin Görünümü olarak değiştirebilir ve bunu kullanabilirsiniz:

android:style="@android:style/Widget.DeviceDefault.Light.Spinner"

ve sonra android:textözelliği tanımlayın .


Yalnızca API 14 ve üstü için çalışır.
Giulio Piancastelli

6

XML dosyası:

<Spinner android:id="@+id/locationSpinner"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:prompt="@string/select_location" />

Aktivite:

private Spinner featuresSelection;
private ArrayAdapter<CharSequence> featuresAdapter;
private List<CharSequence> featuresList;

onCreate:

featuresList = new ArrayList<CharSequence>();
featuresAdapter = new ArrayAdapter<CharSequence>(this,
  android.R.layout.simple_spinner_item, featuresList);
featuresAdapter.setDropDownViewResource(
  android.R.layout.simple_spinner_dropdown_item);
featuresSelection = ((Spinner) yourActivity.this
  .findViewById(R.id.locationSpinner));
featuresSelection.setAdapter(featuresAdapter);
featuresSelection.setOnItemSelectedListener(
  new MyOnItemSelectedListener());

Bazı fonksiyonlar (adaptöre programlı olarak bir şeyler ekleyin)>

featuresAdapter.add("some string");

Şimdi boş bir döndürücünüz var ve boşsa iletişim kutusunu açmamak için kod yazabilirsiniz. Veya geri basabilirler. Ancak çalışma zamanı sırasında bir işlevle veya başka bir listeyle doldurursunuz.


Ayrıca varsayılan olarak true değerine ayarlanması gerektiği için DataSetChanged () 'yi bildirmeye gerek yoktur.
trgraglia

4

Aşağıdaki gibi denedim. Bir düğme alın ve tıklama etkinliğini ona verin. Düğme arka planını değiştirerek, bir spinner gibi görünüyor.

Global değişkenler olarak bildirir uyarıyatı ve varsayılan değer ..

AlertDialog d;
static int default_value = 0;
final Button btn = (Button) findViewById(R.id.button1);
btn .setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v)
{
    //c.show();
    final CharSequence str[] = {"Android","Black Berry","Iphone"};
        AlertDialog.Builder builder =
          new AlertDialog.Builder(TestGalleryActivity.this).setSingleChoiceItems(
            str, default_value,new  DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int position)
            {
                Toast.makeText(TestGalleryActivity.this,
                               "" + position,
                               Toast.LENGTH_SHORT).show();
                default_value = position;
                btn.setText(str[position]);
                if(d.isShowing())
                    d.dismiss();
            }
        }).setTitle("Select Any");
        d = builder.create();
        d.show();
    }
});

4

Bu benim yolum:

List<String> list = new ArrayList<String>();
list.add("string1");
list.add("string2");
list.add("string3");
list.add("[Select one]");
final int listsize = list.size() - 1;
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list) {
 @Override
public int getCount() {
    return(listsize); // Truncate the list
}
};
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(dataAdapter);

mySpinner.setSelection(listsize); // Hidden item to appear in the spinner

bu,
iplikçiyi

3

Listenin en üstüne bir öğe eklemek için genel amaçlı bir çözüm için iosched uygulamasına bir göz atın. Özellikle bir CursorAdapter kullanıyorsanız, TracksAdapter.java bu tanımı bir "setHasAllItem" yöntemi ve ilişkili kodu üstteki ek öğeyle başa çıkmak için yönetmek için sağlamak üzere genişleten .

Özel bağdaştırıcıyı kullanarak metni "Birini Seçin" veya bu üst öğenin söylemesini istediğiniz herhangi bir şekilde ayarlayabilirsiniz.


3

Benim main.xml bir spinner var ve kimliği @+id/spinner1

Bu benim OnCreate işlevinde yazdığım şeydir:

spinner1 = (Spinner)this.findViewById(R.id.spinner1);
final String[] groupes = new String[] {"A", "B", "C", "D", "E", "F", "G", "H"};
ArrayAdapter<CharSequence> featuresAdapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, new ArrayList<CharSequence>());
featuresAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(featuresAdapter);
for (String s : groupes) featuresAdapter.add(s);

spinner1.setOnItemSelectedListener(new OnItemSelectedListener() {
     public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
         // Here go your instructions when the user chose something
         Toast.makeText(getBaseContext(), groupes[position], 0).show();
     }
     public void onNothingSelected(AdapterView<?> arg0) { }
});

Sınıfta herhangi bir uygulamaya ihtiyaç duymaz.


3

Bunun için birçok iyi çözüm buldum. Çoğu, bağdaştırıcının sonuna bir öğe ekleyerek çalışır ve son öğeyi açılır listede görüntülemez. Benim için en büyük sorun, aşağı açılır listenin listenin altından başlayacağıydı. Bu yüzden kullanıcı, ilk kez yerine (ilk olarak gösterilecek çok sayıda öğe olması durumunda), eğiriciye ilk kez dokunduktan sonra son öğeleri görür.

Bu yüzden ipucu öğesini listenin başına koyuyorum. ve açılır listeden ilk öğeyi gizleyin.

private void loadSpinner(){

    HintArrayAdapter hintAdapter = new HintArrayAdapter<String>(context, 0);

    hintAdapter.add("Hint to be displayed");
    hintAdapter.add("Item 1");
    hintAdapter.add("Item 2");
            .
            .
    hintAdapter.add("Item 30");

    spinner1.setAdapter(hintAdapter);

    //spinner1.setSelection(0); //display hint. Actually you can ignore it, because the default is already 0
    //spinner1.setSelection(0, false); //use this if don't want to onItemClick called for the hint

    spinner1.setOnItemSelectedListener(yourListener);
}

private class HintArrayAdapter<T> extends ArrayAdapter<T> {

    Context mContext;

    public HintArrayAdapter(Context context, int resource) {
        super(context, resource);
        this.mContext = context
    }

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
        TextView texview = (TextView) view.findViewById(android.R.id.text1);

        if(position == 0) {
            texview.setText("");
            texview.setHint(getItem(position).toString()); //"Hint to be displayed"
        } else {
            texview.setText(getItem(position).toString());
        }

        return view;
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view;

        if(position == 0){
            view = inflater.inflate(R.layout.spinner_hint_list_item_layout, parent, false); // Hide first row
        } else {
            view = inflater.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
            TextView texview = (TextView) view.findViewById(android.R.id.text1);
            texview.setText(getItem(position).toString());
        } 

        return view;
    }
}

ilk ipucu satırını gizlemek için 0 konumundayken getDropDownView () işlevinde aşağıdaki düzeni ayarlayın.

R.layout.spinner_hint_list_item_layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

</LinearLayout>

3

Ayrıca, varsayılanı göstermek için basit bir hile vardır:

Listenize varsayılan bir değer ekleyebilir ve ardından tüm koleksiyonunuzu list.addAll(yourCollection);

Burada örnek uygulanabilir kod:

List<FuelName> fuelList = new ArrayList<FuelName>();
                    fuelList.add(new FuelName(0,"Select One"));
                    fuelList.addAll(response.body());
                    ArrayAdapter adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, fuelList);
                    //fuelName.setPrompt("Select Fuel");
                    fuelName.setAdapter(adapter);

Umarım karmaşıklığınızı geri kazanır. Mutlu kodlama!


2

Ben en kolay yolu dizin 0 "birini seçin" diyerek kukla bir öğe oluşturmak olduğunu düşünüyorum ve sonra kaydettikten sonra seçim 0 olmadığını kontrol edin.


4
Öğe listesini görüntülemeye ne dersiniz? Üstte "birini seç" konumunu görmek ister misiniz? Bu sadece tasarruf meselesi değil.
Krzysztof Wolny

Wolny Spinner varsayılan olarak öğeyi 0 konumunda görüntüler
rds

2

Bu benim bir düğme döndürücü için son örneğim "all-in"

In activity_my_form.xml

    <Button
        android:id="@+id/btnSpinnerPlanets"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="left|center_vertical"
        android:singleLine="true"
        android:text="@string/selectAPlanet"
        android:textSize="10sp"
        android:background="@android:drawable/btn_dropdown">
    </Button>

In strings.xml

<string name="selectAPlanet">Select planet&#8230;</string>

<string-array name="planets__entries">
    <item>The Sun with a name very long so long long long long longThe Sun with a name very long so long long long long longThe Sun with a name very long so long long long long long</item>
    <item>Mercury</item>
    <item>Venus</item>
    <item>Earth</item>
    <item>Mars</item>
    <item>Jupiter</item>
    <item>Saturn</item>
    <item>Uranus</item>
    <item>Neptune</item>
</string-array>

In MyFormActivity.java

public class MyFormActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String[] items = view.getResources().getStringArray(R.array.planets__entries);
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items);
                new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(adapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((Button) findViewById(R.id.btnSpinnerPlanets)).setText(items[which]);
                        dialog.dismiss();
                    }
                }).create().show();
            }
        });     

    }

}   

Sonunda bir yazı tipi boyutu yapılandırılabilir hiçbir ilk öğe seçilebilir düğme spinner elde !!! HRJ sayesinde


1

Uzanan zaman SpinnerAdapter, iki geçersiz Viewüreten yöntemleri getView(int, View, ViewGroup)ve getDropDownView(int, View, ViewGroup). Birincisi, Vieweklenmiş olanı Spinnerkendisine tedarik eder; ikincisi Viewaçılır listede (adından da anlaşılacağı gibi) sağlar. getView(...)Bir öğe seçilene kadar TextViewbir bilgi istemi görüntüleyecek şekilde geçersiz kılabilirsiniz ; daha sonra, bir öğenin seçildiğini algıladığınızda, TextViewbuna karşılık gelen bir öğeyi görüntüleyecek şekilde değiştirirsiniz .

public class PromptingAdapter extends SpinnerAdapter {

    //... various code ...

    private boolean selectionmade = false;

    //call this method from the OnItemSelectedListener for your Spinner
    public setSelectionState(boolean b) {
        selectionmade = b;
    }

    @Override
    public View getView(int position, View recycle, ViewGroup container) {
        if(selectionmade) {
            //your existing code to supply a View for the Spinner
            //you could even put "return getDropDownView(position, recycle, container);"
        }
        else {
            View output;
            if(recycle instanceof TextView) {
                 output = recycle;
            }
            else {
                 output = new TextView();
                 //and layout stuff
            }
            output.setText(R.string.please_select_one);
            //put a string "please_select_one" in res/values/strings.xml
            return output;
        }
    }

//...
}

1
Bu yöntemde bir kusur keşfettim: Spinner otomatik olarak hemen bir öğe seçer. Kısa süre içinde bir yol bulacağım.
Andrew Wyld

Çok erken konuştum. Ancak ben vazgeçmedim. Eğiticiye göre Spinner( Toastbir öğeyi seçtiğinizden SONRA gösterdiği gibi) bu OUGHT'un çalışmak için olduğuna dikkat edin: developer.android.com/resources/tutorials/views/…
Andrew Wyld

1

Xamarin kullananlar için, yukarıdaki aaronvargas'ın cevabına C # eşdeğeridir.

using Android.Content;
using Android.Database;
using Android.Views;
using Android.Widget;
using Java.Lang;

namespace MyNamespace.Droid
{ 
  public class NothingSelectedSpinnerAdapter : BaseAdapter, ISpinnerAdapter, IListAdapter
  {
    protected static readonly int EXTRA = 1;
    protected ISpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;

    public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) : this(spinnerAdapter, nothingSelectedLayout, -1, context)
    {
    }

    public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context)
    {
      this.adapter = spinnerAdapter;
      this.context = context;
      this.nothingSelectedLayout = nothingSelectedLayout;
      this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
      layoutInflater = LayoutInflater.From(context);
    }

    protected View GetNothingSelectedView(ViewGroup parent)
    {
      return layoutInflater.Inflate(nothingSelectedLayout, parent, false);
    }

    protected View GetNothingSelectedDropdownView(ViewGroup parent)
    {
      return layoutInflater.Inflate(nothingSelectedDropdownLayout, parent, false);
    }

    public override Object GetItem(int position)
    {
      return position == 0 ? null : adapter.GetItem(position - EXTRA);
    }

    public override long GetItemId(int position)
    {
      return position >= EXTRA ? adapter.GetItemId(position - EXTRA) : position - EXTRA;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
      // This provides the View for the Selected Item in the Spinner, not
      // the dropdown (unless dropdownView is not set).
      if (position == 0)
      {
        return GetNothingSelectedView(parent);
      }

      // Could re-use the convertView if possible.
      return this.adapter.GetView(position - EXTRA, null, parent);
    }

    public override int Count
    {
      get
      {
        int count = this.adapter.Count;
        return count == 0 ? 0 : count + EXTRA;
      }
    }

    public override View GetDropDownView(int position, View convertView, ViewGroup parent)
    {
      // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 -
      // Spinner does not support multiple view types
      if (position == 0)
      {
        return nothingSelectedDropdownLayout == -1 ?
          new View(context) :
          GetNothingSelectedDropdownView(parent);
      }

      // Could re-use the convertView if possible, use setTag...
      return adapter.GetDropDownView(position - EXTRA, null, parent);
    }

    public override int GetItemViewType(int position)
    {
      return 0;
    }

    public override int ViewTypeCount => 1;

    public override bool HasStableIds => this.adapter.HasStableIds;

    public override bool IsEmpty => this.adapter.IsEmpty;

    public override void RegisterDataSetObserver(DataSetObserver observer)
    {
      adapter.RegisterDataSetObserver(observer);
    }

    public override void UnregisterDataSetObserver(DataSetObserver observer)
    {
      adapter.UnregisterDataSetObserver(observer);
    }

    public override bool AreAllItemsEnabled()
    {
      return false;
    }

    public override bool IsEnabled(int position)
    {
      return position > 0;
    }
  }
}

1

Ben de aşağıdaki kodu kullanarak bu sorunu çözdü. Diyelim ki bir öğe listeniz var.

ArrayList<Item> itemsArrayList = new ArrayList<Item>();
Item item1 = new Item();
item1.setId(1);
item1.setData("First Element");
Item item2 = new Item();
item2.setId(2);
Item2.setData("Second Element");
itemsArrayList.add(item1);
itemsArrayList.add(item2);

Şimdi iplikçiyi dizgiye vermeliyiz çünkü iplikçinin nesneyi anlayamaması. Böylece, bunun gibi dize öğeleriyle yeni bir dizi listesi oluşturacağız ->

ArrayList<String> itemStringArrayList = new ArrayList<String>();
for(Item item : itemsArrayList) {
    itemStringArrayList.add(item.getData());
}

Şimdi itemStringArrayListiki dize öğesi içeren dizi listemiz var . Ve "Öğe Seç" metnini ilk öğe olarak göstermeliyiz. Yani yeni bir dize eklemeliyiz itemStringArrayList.

itemStringArrayList.add("Select Item");

Şimdi bir dizi listemiz var itemsArrayListve açılır menüde iki öğe göstermek istiyoruz. Ama buradaki durum ... Hiçbir şey seçmezsekSelect Item , etkinleştirilmeyecek ilk öğe olarak görünmelidir.

Böylece bu işlevi böyle uygulayabiliriz. Dizi listesi öğelerini android döndürücüye yüklemeniz gerekiyorsa. Bu yüzden bazı adaptörler kullanmanız gerekecek. İşte burada kullanacağım ArrayAdapter. Özelleştirme adaptörünü de kullanabiliriz.

ArrayAdapter<String> itemsArrayAdapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.spinner_item, itemsArrayList){
        @Override
        public boolean isEnabled(int position) {
            if(position == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        @Override
        public View getDropDownView(int position, View convertView,
                                    ViewGroup parent) {
            View view = super.getDropDownView(position, convertView, parent);
            TextView tv = (TextView) view;
            if(position == 0){
                // Set the hint text color gray
                tv.setTextColor(Color.GRAY);
            }
            else {
                tv.setTextColor(Color.BLACK);
            }
            return view;
        }
    };

itemsArrayAdapter.setDropDownViewResource(R.layout.spinner_item);
your_spinner_name.setAdapter(itemsArrayAdapter);

İşte bu kodda. biz özelleştirilmiş spinner düzeni kullanıyoruz yani R.layout.spinner_item. Basit bir metin görünümü

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textStyle="italic"
    android:fontFamily="sans-serif-medium"
    />

Değer değiştiricideki ilk metni devre dışı bırakmamız gerekir. Yani 0 konumu için metni devre dışı bırakıyoruz. Ve renk de getDropDownView yöntemini geçersiz kılarak ayarlayabilirsiniz. Bu şekilde beklenen döndürücüyü alacağız.


0

Sadece üç seçeneğiniz varsa, RadioButtons ile bir RadioGroup kullanırım, ilk önce hepsini işaretlemeyebilirsiniz.


0

Daha önce gönderilen cevapların hiçbiri bu sorunu çözmek istediğim şekilde işe yaramadı. Bana göre ideal çözüm, değer değiştirici ilk kez görüntülendiğinde “Birini Seçin” (ya da başlangıç ​​metni ne olursa olsun). Kullanıcı döndürücüye dokunduğunda, ilk metin görüntülenen açılır menünün bir parçası olmamalıdır.

Özel durumumu daha da karmaşıklaştırmak için, değer değiştirici verilerim LoaderManager geri çağrıları aracılığıyla yüklenen bir imleçten geliyor.

Önemli deneylerden sonra aşağıdaki çözümü buldum:

public class MyFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor>{

private static final String SPINNER_INIT_VALUE = "Select A Widget";
private Spinner mSpinner;
private int mSpinnerPosition;
private boolean mSpinnerDropDownShowing = false;
private View mSpinnerDropDown;

private MyCursorAdapter mCursorAdapter;

...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
...

mCursorAdapter = new MyCursorAdapter(getActivity());

mSpinner = (Spinner) rootView.findViewById(R.id.theSpinner);
mSpinner.setOnTouchListener(mSpinnerTouchListener);
mSpinner.setAdapter(mCursorAdapter);

...
}

//Capture the touch events to toggle the spinner's dropdown visibility
private OnTouchListener mSpinnerTouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if(mSpinnerDropDown != null && mSpinnerDropDownShowing == false){
            mSpinnerDropDownShowing = true;
            mSpinnerDropDown.setVisibility(View.VISIBLE);
        }
        return false;
    }
};

//Capture the click event on the spinner drop down items
protected OnClickListener spinnerItemClick = new OnClickListener(){

    @Override
    public void onClick(View view) {
        String widget = ((TextView) view.findViewById(android.R.id.text1)).getText().toString();

        if(!widget.equals(SPINNER_INIT_VALUE)){
            if(mCursorAdapter != null){
                Cursor cursor = mCursorAdapter.getCursor();
                if(cursor.moveToFirst()){
                    while(!cursor.isAfterLast()){
                        if(widget.equals(cursor.getString(WidgetQuery.WIDGET_NAME))){

                            ...

                            //Set the spinner to the correct item
                            mSpinnerPosition = cursor.getPosition() + 1;
                            mSpinner.setSelection(mSpinnerPosition);
                            break;
                        }
                        cursor.moveToNext();
                    }
                }
            }
        }

        //Hide the drop down. Not the most elegent solution but it is the only way I could hide/dismiss the drop down
        mSpinnerDropDown = view.getRootView();
        mSpinnerDropDownShowing = false;
        mSpinnerDropDown.setVisibility(View.GONE);
    }
};

private class MyCursorAdapter extends CursorAdapter {

    private final int DISPLACEMENT = 1;
    private final int DEFAULT_ITEM_ID = Integer.MAX_VALUE;

    private Activity mActivity;

    public MyCursorAdapter(Activity activity) {
            super(activity, null, false);
            mActivity = activity;
    }

    //When loading the regular views, inject the defualt item
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(position == 0){
            if(convertView == null){
                convertView = mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
            }
            return getDefaultItem(convertView);
        }
        return super.getView(position - DISPLACEMENT, convertView, parent);
    }

    //When loading the drop down views, set the onClickListener for each view
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent){
        View view = super.getDropDownView(position, convertView, parent);
        view.setOnClickListener(spinnerItemClick);
        return view;
    }

    //The special default item that is being injected
    private View getDefaultItem(View convertView){
        TextView text = (TextView) convertView.findViewById(android.R.id.text1);
        text.setText(SPINNER_INIT_VALUE);
        return convertView;
    }

    @Override
    public long getItemId(int position) {
        if (position == 0) {
            return DEFAULT_ITEM_ID;
        }
        return super.getItemId(position - DISPLACEMENT);
    }

    @Override
    public boolean isEnabled(int position) {
        return position == 0 ? true : super.isEnabled(position - DISPLACEMENT);
    }

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount() + DISPLACEMENT;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return super.getViewTypeCount();
        }

        return super.getItemViewType(position - DISPLACEMENT);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor){

        if(cursor.isAfterLast()){
            return;
        }

        TextView text = (TextView) view.findViewById(android.R.id.text1);
        String WidgetName = cursor.getString(WidgetQuery.WIDGET_NAME);
        text.setText(WidgetName);
    }
}
}

0

Bunu bir Spinner yerine bir düğme kullanarak hallederim. GitHub üzerinde örnek proje var.

Projede, gerçekten aynı göründüklerini göstermek için Spinner ve düğmeyi görüntülüyorum. Düğme dışında ilk metni istediğiniz gibi ayarlayabilirsiniz.

Etkinlik şöyle görünür:

package com.stevebergamini.spinnerbutton;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Spinner;

public class MainActivity extends Activity {

    Spinner spinner1;
    Button button1;
    AlertDialog ad;
    String[] countries;

    int selected = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        spinner1 = (Spinner) findViewById(R.id.spinner1);
        button1 = (Button) findViewById(R.id.button1);

        countries = getResources().getStringArray(R.array.country_names);

        //  You can also use an adapter for the allert dialog if you'd like
        //  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, countries);        

        ad = new AlertDialog.Builder(MainActivity.this).setSingleChoiceItems(countries, selected,  
                new  DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            button1.setText(countries[which]);
                            selected = which;
                            ad.dismiss();

                        }}).setTitle(R.string.select_country).create(); 


        button1.setOnClickListener( new OnClickListener(){

            @Override
            public void onClick(View v) {
                ad.getListView().setSelection(selected);
                ad.show();              
            }});

    }

}

NOT: Evet, bunun uygulanan Temaya bağlı olduğunu ve Theme.Holo kullanılırsa görünümün biraz farklı olacağını anlıyorum. Ancak, Theme.Black gibi eski temalardan birini kullanıyorsanız, gitmekte fayda var.


0

öğeleriniz veritabanı imlecinden doldurulduğunda bu sorunla karşı karşıyaysanız ,

Bu SO cevabında bulduğum en basit çözüm :

imleç bağdaştırıcısı sorgunuzda UNION kullanın ve id = -1 ile ek öğeyi sorguya gerçekten DB'ye eklemeden ekleyin:

gibi bir şey:

db.rawQuery ("iWorkerId öğesini _id olarak seç, nvLastName adından UNION SELECT -1 _id olarak, '' ad olarak", null);

seçilen öğe -1 ise, varsayılan değerdir. Aksi takdirde tablodan bir kayıt olur.


0

Banal bir çözüm gibi görünse de, genellikle döndürücünün önüne bir TextView koyarım. Bütün Xml buna benziyor. (hey millet, beni vurma, bazılarınızın bu tür bir evliliği sevmediğini biliyorum):

<FrameLayout
    android:id="@+id/selectTypesLinear"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <Spinner
        android:id="@+id/spinnerExercises"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:entries="@array/exercise_spinner_entries"
        android:prompt="@string/exercise_spinner_prompt"
     />                         
    <TextView
        android:id="@+id/spinnerSelectText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hey! Select this guy!"
        android:gravity="center"
        android:background="#FF000000" />


</FrameLayout>

Sonra bir Öğe seçildiğinde TextView gizlemek. Açıkçası TextView'ın arka plan rengi Spinner ile aynı olmalıdır. Android 4.0'da çalışır. Eski sürümleri bilmiyorum.

Evet. Spinner başlangıçta setOnItemSelectedListener öğesini çağırdığı için, metin görünümünün gizlenmesi biraz zor olabilir, ancak şu şekilde yapılabilir:

    Boolean controlTouched;

    exerciseSpinner.setOnTouchListener(new OnTouchListener() {


        @Override
        public boolean onTouch(View v, MotionEvent event) {
            controlTouched = true; // I touched it but but not yet selected an Item.
            return false;
        }

    });
    exerciseSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1,
                int arg2, long arg3) {
            if (controlTouched) { // Are you sure that I touched it with my fingers and not someone else  ?
                spinnerSelText.setVisibility(View.GONE);
            }
        }

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

    });

0

benim için böyle bir şey çalıştı. tümünde değil, yalnızca BAZI seçeneklerinde metni değiştiren iyileştirmeye sahiptir.

İlk önce spinner'ın isimlerini alıp özel bir görünümle arrayadapter oluşturuyorum, ancak şimdi önemli değil, anahtar getView'i geçersiz kılıyor ve içinde değiştirmeniz gereken değerleri değiştirin. Benim durumumda sadece birincisiydi, gerisi orijinali terk ediyorum

public void rellenarSpinnerCompeticiones(){
        spinnerArrayCompeticiones = new ArrayList<String>();
        for(Competicion c: ((Controlador)getApplication()).getCompeticiones()){
            spinnerArrayCompeticiones.add(c.getNombre());
        }
        //ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,R.layout.spinner_item_competicion,spinnerArrayCompeticiones);
        ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, R.layout.spinner_item_competicion, spinnerArrayCompeticiones){
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                final View v = vi.inflate(R.layout.spinner_item_competicion, null);
                final TextView t = (TextView)v.findViewById(R.id.tvCompeticion);
                if(spinnerCompeticion.getSelectedItemPosition()>0){
                    t.setText(spinnerArrayCompeticiones.get(spinnerCompeticion.getSelectedItemPosition()));
                }else{
                    t.setText("Competiciones");
                }
                return v;
            }
        };
        spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerCompeticion.setAdapter(spinnerArrayAdapter);
    }

0

işte basit bir tane

    private boolean isFirst = true;
private void setAdapter() {
    final ArrayList<String> spinnerArray = new ArrayList<String>();     
    spinnerArray.add("Select your option");
    spinnerArray.add("Option 1");
    spinnerArray.add("Option 2");
    spin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            TextView tv = (TextView)selectedItemView;
            String res = tv.getText().toString().trim();
            if (res.equals("Option 1")) {
            //do Something
        } else if (res.equals("Option 2")) {
            //do Something else
        }
        }

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

    });

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.my_spinner_style,spinnerArray) {
         public View getView(int position, View convertView, ViewGroup parent) {
             View v = super.getView(position, convertView, parent);
             int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics());                  
             ((TextView) v).setTypeface(tf2);
             ((TextView) v).getLayoutParams().height = height;
             ((TextView) v).setGravity(Gravity.CENTER);
             ((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, 19);
             ((TextView) v).setTextColor(Color.WHITE);
             return v;
         }

         public View getDropDownView(int position, View convertView,
                 ViewGroup parent) {
             if (isFirst) {
                 isFirst = false;
                 spinnerArray.remove(0);
             }
             View v = super.getDropDownView(position, convertView, parent);                  
             ((TextView) v).setTextColor(Color.argb(255, 70, 70, 70));
             ((TextView) v).setTypeface(tf2);
             ((TextView) v).setGravity(Gravity.CENTER);
             return v;
         }
     };
     spin.setAdapter(adapter);
}

0

Yukarıdaki cevaplardan birine başvurun: https://stackoverflow.com/a/23005376/1312796

Küçük bir hatayı düzeltmek için kodumu ekledim. Hiçbir veri alınamadığı .. Nasıl istemi metni göstermek için ..!

İşte benim numaram ... Benimle iyi çalışıyor. !

Spinner'ınızı Relative_layoutand'a koymaya çalışın ve bir Textview'i spinner'ınızla hizalayın ve spinner'ın adaptörü yüklendiğinde veya boş olduğunda Textview (SHOW / HIDE) görünürlüğü ile oynayın.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="20dp"
android:background="#ededed"
android:orientation="vertical">



    <TextView
        android:id="@+id/txt_prompt_from"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:textColor="@color/gray"
        android:textSize="16sp"
        android:layout_alignStart="@+id/sp_from"
        android:text="From"
        android:visibility="gone"/>

    <Spinner
        android:id="@+id/sp_from"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        />

İşte kod:

  txt__from = (TextView) rootView.findViewById(R.id.txt_prompt_from);

spinner adaptör yüklendikten sonra boş ve önce bu yöntemi çağırın.

setPromptTextViewVisibility (); //True or fales 

public void setPromptTextViewVisibility (boolean visible )
{
    if (visible)
    {
        txt_from.setVisibility(View.VISIBLE);
    }
    else
    {
        txt_from.setVisibility(View.INVISIBLE);
    }

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