Bagaimana cara membuat Spinner Android dengan teks awal "Select One"?

569

Saya ingin menggunakan Spinner yang awalnya (ketika pengguna belum membuat pilihan) menampilkan teks "Select One". Ketika pengguna mengklik pemintal, daftar item ditampilkan dan pengguna memilih salah satu opsi. Setelah pengguna membuat pilihan, item yang dipilih ditampilkan di Spinner alih-alih "Pilih Satu".

Saya memiliki kode berikut untuk membuat Spinner:

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

Dengan kode ini, awalnya item "Satu" ditampilkan. Saya hanya bisa menambahkan item baru "Pilih Satu" ke item, tetapi kemudian "Pilih Satu" juga akan ditampilkan dalam daftar dropdown sebagai item pertama, yang bukan yang saya inginkan.

Bagaimana saya bisa memperbaiki masalah ini?

Pieter Kuijpers
sumber
6
Solusi sempurna terletak pada pertanyaan ini: stackoverflow.com/questions/9863378/… Cukup timpa metode getDropDownView ().
Sourab Sharma
Sudahkah Anda mencoba mengatur elemen pertama adaptor Anda ke "Select One"?
IgorGanapolsky
[Di sini solusi bagus lainnya!] [1] [1]: stackoverflow.com/questions/9863378/…
AirtonCarneiro
pemintal yang dapat digunakan kembali: github.com/henrychuangtw/ReuseSpinner
HenryChuang

Jawaban:

255

Inilah solusi umum yang mengesampingkan Spinnertampilan. Mengganti setAdapter()untuk mengatur posisi awal ke -1, dan proksi yang disediakan SpinnerAdapteruntuk menampilkan string prompt untuk posisi kurang dari 0.

Ini telah diuji pada Android 1.5 hingga 4.2, tetapi pembeli berhati-hatilah! Karena solusi ini mengandalkan refleksi untuk memanggil pribadi AdapterView.setNextSelectedPositionInt()dan AdapterView.setSelectedPositionInt(), itu tidak dijamin untuk bekerja di pembaruan OS di masa depan. Tampaknya itu memang akan terjadi, tetapi tidak berarti dijamin.

Biasanya saya tidak akan memaafkan sesuatu seperti ini, tetapi pertanyaan ini telah ditanyakan cukup banyak dan sepertinya permintaan yang cukup masuk akal yang saya pikir saya akan memposting solusi saya.

/**
 * 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);
        }
    }
}
emmby
sumber
7
@emmby Apakah Anda tahu cara menghapus pilihan setelah pengguna mengaturnya? Saya mencoba refactoring dua panggilan () panggilan ke metode clearSelection (), tetapi tidak benar-benar berfungsi. Meskipun daftar sembulan menunjukkan item yang sebelumnya dipilih sebagai tidak dipilih, widget pemintal masih menunjukkannya sebagai yang dipilih, dan jika pengguna memilih item yang sama lagi, onItemSelected () tidak dipanggil.
Qwertie
3
Bisakah beberapa orang menjelaskan cara menggunakan kelas di atas?
Bishan
4
Solusi ini tidak 100% sempurna di Android 4.2 (Cyanogenmod 10.1), menggunakan entri Android:. Ketinggian TextView yang digembungkan lebih kecil dari ketinggian sumber daya mana pun yang mengembang Adaptor default. Jadi, ketika Anda benar-benar memilih opsi, tingginya bertambah, ~ 10px di Galaxy S saya, yang tidak dapat diterima. Saya sudah mencoba beberapa hal (gravitasi, bantalan, margin, dll.) Dan tidak ada yang bekerja dengan andal di seluruh perangkat, jadi saya akan memilih solusi yang berbeda.
Maragues
3
@ Davidvidoria Anda harus menggunakan kelas NoDefaultSpinner di file tata letak Anda. Salin sumber dari atas ke proyek Anda, misalnya ke paket com.example.customviews. Sekarang di tata letak Anda xml, alih-alih <Spinner ...> gunakan <com.example.customviews.NoDefaultSpinner ...> Sisa kode dapat tetap sama. Jangan lupa untuk menambahkan atribut android: prompt ke tampilan <com.example.customviews.NoDefaultSpinner> di tata letak Anda.
Ridcully
2
@emmby spinnerBrand.setSelection (-1); tidak bekerja
Sachin C
291

Yang dapat Anda lakukan adalah menghiasnya SpinnerAdapterdengan tampilan yang menampilkan 'Pilih Opsi ...' pada awalnya agar Spinner dapat ditampilkan tanpa ada yang dipilih.

Berikut ini adalah contoh kerja yang diuji untuk Android 2.3, dan 4.0 (tidak menggunakan apa pun di perpustakaan kompatibilitas, jadi itu harus baik untuk sementara). Karena ini adalah dekorator, seharusnya mudah untuk memperbaiki kode yang ada dan berfungsi baik dengan CursorLoaders juga. (Tukar kursor pada bungkus cursorAdaptertentu saja ...)

Ada bug Android yang membuat ini sedikit lebih sulit untuk menggunakan kembali tampilan. (Jadi, Anda harus menggunakan setTagatau sesuatu yang lain untuk memastikan Anda convertViewbenar.) Spinner tidak mendukung beberapa jenis tampilan

Catatan kode: 2 konstruktor

Ini memungkinkan Anda untuk menggunakan prompt standar atau menentukan sendiri 'tidak ada yang dipilih' sebagai baris pertama, atau keduanya, atau tidak sama sekali. (Catatan: Beberapa tema menunjukkan DropDown untuk Spinner alih-alih dialog. Dropdown biasanya tidak menampilkan prompt)

Anda menetapkan tata letak untuk 'terlihat' seperti prompt, misalnya, berwarna abu-abu ...

Tidak ada yang dipilih awal

Menggunakan prompt standar (perhatikan bahwa tidak ada yang dipilih):

Dengan prompt standar

Atau dengan prompt dan sesuatu yang dinamis (bisa saja tidak memiliki prompt juga):

Prompt dan tidak ada baris yang dipilih

Penggunaan dalam contoh di atas

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

}
aaronvargas
sumber
52
Ini adalah solusi elegan untuk masalah ini. Kode berfungsi persis seperti salin 'tidak dicicipi ke proyek saya. +1 tanpa refleksi diperlukan.
Richard Le Mesurier
2
Ini solusi hebat. Jika ada yang ingin tahu cara mengganti judul tidak hanya sebelum item dipilih, tetapi setiap saat, dalam panggilan getView (), kembalikan getNothingSelectedView (atau tampilan kustom lainnya) setiap saat. Daftar dropdown masih akan diisi dengan item dari adaptor Anda, tetapi sekarang Anda dapat mengontrol judul SETELAH sesuatu juga dipilih.
OldSchool4664
6
Ini adalah solusi yang sangat elegan untuk masalah yang seharusnya tidak ada (coba pengembangan iPhone). Hebat dan terima kasih! Senang bahwa seseorang mengingat pola, dll.
user1700737
3
@prashantwosti, kode diperbarui untuk bekerja dengan Lollipop. Khususnya getItemViewType () dan getViewTypeCount ().
aaronvargas
3
@ aaronvargas pernah memilih item dari pemintal, bisakah saya membatalkan dan memilih "[Select a planet]"?
modabeckham
130

Saya akhirnya menggunakan sebagai Buttongantinya. Meskipun a Buttonbukan a Spinner, perilaku tersebut mudah disesuaikan.

Pertama buat Adaptor seperti biasa:

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

Perhatikan bahwa saya menggunakan simple_spinner_dropdown_itemid tata letak. Ini akan membantu menciptakan tampilan yang lebih baik saat membuat dialog peringatan.

Di pengendali onClick untuk Tombol saya, saya punya:

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

Dan itu dia!

HRJ
sumber
10
Saya setuju dengan jawaban itu. Selain itu, tombol yang jauh lebih mudah untuk ditata daripada Spinner.
Romain Piel
@ HRJ Saya telah menerapkan cara yang disarankan, tetapi item yang dipilih sebelumnya tidak disorot (berarti tombol radio harus disorot dengan greeen dot di tengah) .... Bagaimana saya dapat memperolehnya dengan metode OnClick () dari tombol. Tolong bantu saya HRJ .....
Avadhani Y
2
Tombol dengan tata letak ini sempurna <Tombol android: id = "@ + id / city" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: layout_margin = "5dp" android: gravity = "left" android: background = "@ android: drawable / btn_dropdown" android: text = "@ string / city_prompt" />
kml_ckr
Bagaimana kemudian Anda memperbarui teks tombol untuk mencerminkan pilihan, seperti yang terjadi pada pemintal?
shim
3
solusi masalah: alih-alih SetAdapter gunakan SetSingleChoiceItems
Grzegorz Dev
67

Pertama, Anda mungkin tertarik pada promptatribut Spinnerkelas. Lihat gambar di bawah, "Pilih Planet" adalah prompt yang dapat diatur dalam XML dengan android:prompt="".

masukkan deskripsi gambar di sini

Saya akan menyarankan subclassing Spinner, di mana Anda dapat mempertahankan dua adapter secara internal. Satu adaptor yang memiliki opsi "Pilih Satu", dan adaptor nyata lainnya (dengan opsi aktual), lalu gunakan OnClickListeneruntuk mengganti adaptor sebelum dialog pilihan ditampilkan. Namun, setelah mencoba menerapkan gagasan itu, saya sampai pada kesimpulan Anda tidak dapat menerima OnClickacara untuk widget itu sendiri.

Anda bisa membungkus pemintal dalam tampilan yang berbeda, memotong klik pada tampilan, dan kemudian memberitahu Anda CustomSpinneruntuk mengganti adaptor, tetapi tampaknya seperti peretasan yang mengerikan.

Apakah Anda benar-benar perlu menunjukkan "Select One"?

Casey
sumber
36
Ini bukan hanya masalah perlunya menunjukkan "Select One", tetapi juga membahas kasus di mana nilai spinner secara opsional dibiarkan kosong.
greg7gkb
5
juga, dengan opsi ini, Earth ditampilkan sebagai pilihan pada Spinner sebelum sesuatu dipilih, untuk aplikasi saya, saya lebih suka pengguna dapat memberi tahu mereka belum memilih apa pun
dylan murphy
2
ini tidak benar-benar menjawab pertanyaan. orang mencari cara untuk memiliki pemintal itu sendiri dengan pertunjukan default "Select One" daripada item pertama dalam daftar planet, dalam contoh ini
JMRboosties
58

Kode ini telah diuji dan berfungsi di Android 4.4

masukkan deskripsi gambar di sini

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);
Manos
sumber
getItem(getCount())Apakah yang digarisbawahi merah untuk saya? Tidak dapat menyelesaikan metode setHint
Zapnologica
Saya ragu, melihat banyak solusi di utas ini..tapi mengapa semua orang menambahkan petunjuk ke yang terakhir. Apakah salah menambahkan petunjuk di baris pertama?
akashPatra
Saya tidak dapat menetapkan 'setOnItemSelectedListener (ini);' karena saya menggunakan 'mengimplementasikan NavigationView.OnNavigationItemSelectedListener', dapatkah saya menghapus 'setOnItemSelectedListener (this);' tanpa masalah?
CGR
@akashpatra Alasan mereka menambahkan petunjuk ke yang terakhir adalah karena ArrayAdapter untuk spinner mungkin mendapatkan nilainya dari sumber yang berbeda saat dijalankan.
VinKrish
ini sangat membantu saya
sunil
31

Saya menemukan solusi ini:

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

Ubah saja array [0] dengan "Select One" dan kemudian di onItemSelected, ganti namanya menjadi "One".

Bukan solusi yang berkelas, tetapi berhasil: D

Marco da Gualdo
sumber
5
Ini tidak berhasil untuk saya. Setelah memilih item "One" masih tertulis "Select One".
Leo Landau
Pekerjaan ini tidak akan menyebabkan antarmuka OnItemSelected akan memanggil untuk pertama kalinya selalu.
Vaibhav Kadam
20

Tidak ada API default untuk memberi petunjuk pada Spinner. Untuk menambahkannya kita perlu solusi kecil tanpa implementasi refleksi keselamatan

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

Sumber adaptor:

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

Sumber asli

Yakiv Mospan
sumber
apa itu R.id.text1? apakah ada tata letak atau tampilan? tolong
uraikan
Seharusnyaandroid.R.id.text1
Yakiv Mospan
Saya ragu, melihat banyak solusi di utas ini..tapi mengapa semua orang menambahkan petunjuk ke yang terakhir. Apakah salah menambahkan petunjuk di baris pertama?
akashPatra
@akashpatra Saya tidak ingat persis, tetapi sepertinya ada beberapa masalah ketika saya mencoba menjadikannya sebagai daftar item pertama. Pokoknya Anda selalu dapat mencobanya dan berkomentar di sini, semua keajaiban di sini ada di sekitar getCountmetode
Yakiv Mospan
@YakivMospan Saya mendapatkan NPE saat saya menggunakan ini, mungkin karena Refleksi saat menggunakan ProGuard. Apakah Anda tahu cara memperbaikinya?
Alan
17

Banyak jawaban di sini tapi saya terkejut tidak ada yang menyarankan solusi sederhana: Tempatkan TextView di atas Spinner. Atur pendengar klik pada TextView yang menyembunyikan TextView memperlihatkan Spinner, dan panggil spinner.performClick ().

mjancola
sumber
9

Saya mendapat masalah yang sama untuk pemintal, dengan pilihan kosong, dan saya menemukan solusi yang lebih baik. Lihatlah kode sederhana ini.

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

Di sini spinneradapter adalah penyesuaian kecil untuk arrayadapter. Ini terlihat seperti ini:

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);
    }
}
Rajasekhar
sumber
6
Masalah dengan pendekatan ini adalah bahwa ia masih memilih item pertama dalam daftar ketika daftar muncul. Karena itu sudah dipilih, Anda tidak dapat menyentuhnya untuk memilih - ini bertindak seolah-olah tidak ada yang dipilih terjadi.
jwadsack
7

Anda dapat mengubahnya ke Tampilan Teks dan gunakan ini:

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

dan kemudian mendefinisikan android:textproperti.

Christian Vielma
sumber
Hanya berfungsi untuk API 14 ke atas.
Giulio Piancastelli
6

File XML:

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

Aktivitas:

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

Beberapa fungsi (tambahkan beberapa hal ke adaptor secara terprogram)>

featuresAdapter.add("some string");

Sekarang Anda memiliki pemintal kosong dan Anda dapat menulis kode untuk tidak membuka dialog jika kosong. Atau mereka dapat menekan kembali. Tetapi Anda juga mengisinya dengan fungsi atau daftar lain selama waktu berjalan.

trgraglia
sumber
Juga tidak perlu notifyDataSetChanged () karena harus disetel ke true secara default.
trgraglia
4

Saya sudah mencoba seperti berikut ini. Ambil tombol dan berikan event klik untuk itu. Dengan mengubah latar belakang tombol, tampaknya menjadi pemintal.

Deklarasikan sebagai variabel global alertdialog dan nilai default ..

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();
    }
});
Ramesh Akula
sumber
4

Ini cara saya:

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
Cabezas
sumber
ini membuka pemintal di posisi bawah
SpyZip
3

Lihatlah aplikasi iosched untuk solusi tujuan umum untuk menambahkan elemen ke bagian atas daftar. Khususnya, jika Anda menggunakan CursorAdapter, lihat TracksAdapter.java yang memperluas definisi itu untuk menyediakan metode "setHasAllItem" dan kode terkait untuk mengelola jumlah daftar untuk menangani item tambahan di atas.

Dengan menggunakan adaptor khusus, Anda dapat mengatur teks menjadi "Select One" atau apa pun yang ingin Anda sampaikan.

Olahraga
sumber
3

Saya memiliki spinner di main.xml saya dan id-nya @+id/spinner1

inilah yang saya tulis di fungsi OnCreate saya:

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

Tidak perlu implementasi di kelas.

Cyril
sumber
3

Saya menemukan banyak solusi bagus untuk ini. sebagian besar bekerja dengan menambahkan item ke ujung adaptor, dan tidak menampilkan item terakhir dalam daftar drop-down. Masalah besar bagi saya adalah daftar drop-down pemintal akan mulai dari bagian bawah daftar. Jadi pengguna melihat item terakhir alih-alih item pertama (jika memiliki banyak item untuk ditampilkan), setelah menyentuh pemintal untuk pertama kalinya.

Jadi saya meletakkan item petunjuk di awal daftar. dan sembunyikan item pertama dalam daftar drop-down.

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

atur tata letak di bawah ini di @Override getDropDownView () saat posisinya 0, untuk menyembunyikan baris petunjuk pertama.

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>
Alireza Sobhani
sumber
3

Selain itu, Ada trik sederhana untuk menampilkan default:

Anda dapat menambahkan nilai default di daftar Anda dan kemudian menambahkan semua koleksi Anda menggunakan list.addAll(yourCollection);

Contoh kode yang bisa diterapkan di sini:

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

Semoga ini memulihkan kompleksitas Anda. Selamat coding!

Majedur Rahaman
sumber
2

Saya pikir cara termudah adalah membuat item dummy pada indeks 0 mengatakan "pilih satu" dan kemudian menghemat mungkin memeriksa bahwa pemilihannya bukan 0.

Tobias
sumber
4
Bagaimana dengan melihat daftar item? Anda ingin melihat posisi "pilih satu" di atas? Bukan hanya masalah menabung.
Krzysztof Wolny
@KrzysztofWolny Spinner secara default menampilkan item di posisi 0
rds
2

Jadi ini adalah contoh terakhir saya "all-in" untuk pemintal tombol

Di 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>

Di 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>

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

    }

}   

Akhirnya saya memperoleh ukuran font yang dapat dikonfigurasi, tidak ada item pertama yang dapat dipilih pemintal tombol !!! Terima kasih kepada HRJ

liar
sumber
1

Saat memanjang SpinnerAdapter, Anda mengganti dua Viewmetode penghasil, getView(int, View, ViewGroup)dan getDropDownView(int, View, ViewGroup). Yang pertama memasok yang Viewdimasukkan ke dalam Spinnerdirinya sendiri; yang kedua memasok Viewdalam daftar drop-down (seperti namanya). Anda dapat mengesampingkan getView(...)sehingga, sampai suatu item telah dipilih, itu akan menampilkan TextViewprompt yang berisi; kemudian, ketika Anda mendeteksi item telah dipilih, Anda mengubahnya untuk menampilkan yang TextViewsesuai dengan itu.

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

//...
}
Andrew Wyld
sumber
1
Saya telah menemukan kelemahan dalam metode ini: Spinner secara otomatis memilih item dengan segera. Saya akan menemukan cara mengitari ini segera.
Andrew Wyld
Saya berbicara terlalu cepat. Namun saya belum menyerah. Perhatikan bahwa sesuai dengan Spinnertutorial (yang seharusnya menampilkan ToastSETELAH Anda telah memilih item) OUGHT ini berfungsi: developer.android.com/resources/tutorials/views/…
Andrew Wyld
1

Bagi mereka yang menggunakan Xamarin, berikut adalah C # yang setara dengan jawaban aaronvargas di atas.

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;
    }
  }
}
MPavlak
sumber
1

Saya juga memecahkan masalah ini dengan menggunakan kode berikut. Misalkan Anda memiliki daftar barang misalnya

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

Sekarang kita harus menyediakan string ke spinner karena spinner tidak dapat memahami objek. Jadi kita akan membuat daftar array baru dengan item string seperti ini ->

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

Sekarang kami memiliki itemStringArrayListdaftar array dengan dua item string. Dan kita harus menunjukkan teks "Pilih Item" sebagai item pertama. Jadi kita harus memasukkan string baru ke dalam itemStringArrayList.

itemStringArrayList.add("Select Item");

Sekarang kami memiliki daftar array itemsArrayListdan kami ingin menunjukkan dua elemen di drop down. Tetapi kondisinya di sini adalah ... Jika kita tidak memilih apa pun maka Select Itemakan muncul elemen pertama yang tidak akan diaktifkan.

Jadi kita bisa mengimplementasikan fungsi ini seperti ini. Jika Anda perlu memuat item daftar array ke spinner Android. Jadi, Anda harus menggunakan beberapa adaptor. Jadi di sini saya akan menggunakan ArrayAdapter. Kita dapat menggunakan adaptor penyesuaian juga.

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

Di sini, di kode ini. kami menggunakan tata letak pemintal yang disesuaikan R.layout.spinner_item. Ini tampilan teks sederhana

<?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"
    />

Kita perlu menonaktifkan teks pertama di pemintal. Jadi untuk posisi 0 kita menonaktifkan teks. Dan warna juga bisa kita atur dengan mengabaikan metode getDropDownView. Jadi dengan cara ini kita akan mendapatkan pemintal yang diharapkan.

Shravan Jain
sumber
0

Saya hanya akan menggunakan RadioGroup dengan RadioButtons jika Anda hanya memiliki tiga pilihan, Anda dapat membuat semuanya tidak dicentang pada awalnya.

stephane k.
sumber
0

Tidak satu pun dari jawaban yang dikirimkan sebelumnya benar-benar berfungsi seperti yang saya inginkan untuk menyelesaikan masalah ini. Bagi saya solusi ideal akan memberikan "Select One" (atau teks awal apa pun) saat spinner pertama kali ditampilkan. Ketika pengguna mengetuk spinner, teks awal tidak boleh menjadi bagian dari drop down yang ditampilkan.

Untuk semakin memperumit situasi khusus saya, data spinner saya datang membentuk kursor yang dimuat melalui callback LoaderManager.

Setelah bereksperimen cukup lama saya menemukan solusi berikut:

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);
    }
}
}
Jed
sumber
0

Saya menangani ini dengan menggunakan tombol, bukan Spinner. Saya memiliki proyek sampel di GitHub.

Dalam proyek ini, saya menampilkan Spinner dan tombol untuk menunjukkan bahwa mereka memang terlihat identik. Kecuali tombol, Anda dapat mengatur teks awal ke apa pun yang Anda inginkan.

Seperti apa kegiatannya:

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

    }

}

CATATAN: Ya, saya menyadari bahwa ini tergantung pada Tema yang diterapkan dan tampilannya akan sedikit berbeda jika menggunakan Theme.Holo. Namun, jika Anda menggunakan salah satu tema lawas seperti Theme.Black, Anda siap melakukannya.

SBerg413
sumber
0

jika Anda menghadapi masalah ini saat item Anda terisi dari kursor basis data ,

solusi paling sederhana yang saya temukan dalam jawaban SO ini :

gunakan UNION di permintaan adaptor kursor Anda dan tambahkan item tambahan dengan id = -1 ke hasil permintaan, tanpa benar-benar menambahkannya ke DB:

sesuatu seperti:

db.rawQuery ("SELECT iWorkerId as _id, nvLastName as name from Worker w UNION SELECT -1 as _id, '' as name", null);

jika item yang dipilih adalah -1, maka itu adalah nilai default. Kalau tidak, ini catatan dari tabel.

dvrm
sumber
0

Tampaknya solusi biasa tapi saya biasanya meletakkan TextView di depan pemintal. Seluruh Xml terlihat seperti ini. (hai teman-teman, jangan tembak saya, saya tahu bahwa beberapa dari Anda tidak menyukai pernikahan semacam ini):

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

Lalu saya menyembunyikan TextView ketika Item dipilih. Jelas warna latar belakang TextView harus sama dengan Spinner. Bekerja di Android 4.0. Tidak tahu di versi yang lebih lama.

Iya. Karena Spinner memanggil setOnItemSelectedListener di awal, menyembunyikan tampilan teks bisa sedikit rumit, tetapi dapat dilakukan dengan cara ini:

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

    });
Claudio Ferraro
sumber
0

bagi saya itu bekerja seperti ini. memiliki peningkatan yang hanya mengubah teks dalam opsi BEBERAPA, tidak semuanya.

Pertama saya mengambil nama-nama pemintal dan membuat arrayadapter dengan tampilan kustomisasi, tetapi tidak masalah sekarang, kuncinya adalah menimpa getView, dan di dalam mengubah nilai-nilai yang perlu Anda ubah. Dalam kasus saya hanya yang pertama, sisanya saya tinggalkan yang asli

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);
    }
Rako
sumber
0

ini yang sederhana

    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);
}
Sayka
sumber
0

Lihat salah satu jawaban di atas: https://stackoverflow.com/a/23005376/1312796

Saya menambahkan kode saya untuk memperbaiki bug kecil. Di mana tidak ada data yang diambil .. Bagaimana menampilkan teks prompt ..!

Ini Trik saya ... Ini berfungsi dengan baik untuk saya. !

Cobalah untuk meletakkan pemintal Anda di Relative_layout dan menyelaraskan Textview dengan pemintal Anda dan bermain dengan visibilitas Textview (SHOW / HIDE) setiap kali adaptor pemintal dimuat atau kosong..Seperti ini:

<?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"
        />

Ini kodenya:

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

panggil metode ini setelah dan sebelum adaptor pemintal dimuat dan kosong.

setPromptTextViewVisibility (); //True or fales 

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

}
Ibrahim AbdelGawad
sumber