Cara menyembunyikan satu item di Android Spinner

101

Saya mencari cara untuk menyembunyikan satu item di widget spinner Android. Ini akan memungkinkan Anda untuk menyimulasikan spinner tanpa item yang dipilih, dan memastikan bahwa callback onItemSelected () selalu dipanggil untuk setiap item yang dipilih (jika item yang disembunyikan adalah yang "saat ini"). Biasanya selalu ada satu item di spinner yang tidak menghasilkan callback, yaitu item saat ini.

Ada beberapa kode di stackoverflow tentang cara menonaktifkan item (berwarna abu-abu), tetapi bukan cara menyembunyikan item sepenuhnya seolah-olah tidak ada.

Setelah banyak bereksperimen, saya menemukan solusi yang agak hack-ish yang berfungsi pada berbagai platform Android lama dan baru. Ini memiliki beberapa kekurangan kosmetik kecil yang sulit untuk diperhatikan. Saya masih ingin mendengar solusi yang lebih resmi, selain "jangan lakukan itu dengan pemintal".

Ini selalu menyembunyikan item pertama di spinner, tetapi dapat dengan mudah diperpanjang untuk menyembunyikan item arbitrer atau lebih dari satu item. Tambahkan item dummy yang berisi string kosong di awal daftar item spinner Anda. Anda mungkin ingin menyetel pilihan spinner saat ini ke item 0 sebelum dialog spinner terbuka, ini akan menyimulasikan spinner yang tidak dipilih.

Contoh penyiapan spinner dengan penggantian metode ArrayAdapter:

List<String> list = new ArrayList<String>();
list.add("");   //  Initial dummy entry
list.add("string1");
list.add("string2");
list.add("string3");

// Populate the spinner using a customized ArrayAdapter that hides the first (dummy) entry
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list) {
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent)
    {
        View v = null;

        // If this is the initial dummy entry, make it hidden
        if (position == 0) {
            TextView tv = new TextView(getContext());
            tv.setHeight(0);
            tv.setVisibility(View.GONE);
            v = tv;
        }
        else {
            // Pass convertView as null to prevent reuse of special case views
            v = super.getDropDownView(position, null, parent);
        }

        // Hide scroll bar because it appears sometimes unnecessarily, this does not prevent scrolling 
        parent.setVerticalScrollBarEnabled(false);
        return v;
    }
};

dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(dataAdapter);
Georgie
sumber
apa yang Anda temukan di interwebs lainnya? apa yang sudah kamu coba sejauh ini?
dldnh
Maaf lah, saya tidak tahu bagaimana melakukannya.
Louisth
Solusi bagus! Tapi saya pikir tv.setVisibility(View.GONE);garis itu tidak perlu. Mengomentarinya sepertinya tidak membuat perbedaan (visual) apa pun, setidaknya di Android 4.4.2 / KitKit (di LG / Google Nexus 4).
Matthias
Jawaban dalam pertanyaan ini bekerja dengan baik ..
Rat-a-tat-a-tat Ratatouille
Ini mungkin bukan peningkatan, tetapi saya menggunakan setTag(1)textView di posisi 0, lalu digunakan convertView.getTag() != nulluntuk menentukan apakah tampilan yang digunakan kembali adalah tampilan 0 ketinggian yang dibuat untuk posisi 0 atau tampilan normal yang digunakan untuk item spinner lainnya. Ini agar saya super.getDropDownView(position, convertView, parent)terkadang dapat menggunakan alih-alih selalu membuat tampilan baru.
Daniel Handojo

Jawaban:

49

Untuk menyembunyikan item sewenang-wenang atau lebih dari satu item, saya pikir Anda dapat menerapkan adaptor Anda sendiri dan mengatur indeks (atau daftar indeks array) yang ingin Anda sembunyikan.

public class CustomAdapter extends ArrayAdapter<String> {

     private int hidingItemIndex;

     public CustomAdapter(Context context, int textViewResourceId, String[] objects, int hidingItemIndex) {
         super(context, textViewResourceId, objects);
         this.hidingItemIndex = hidingItemIndex;
     }

     @Override
     public View getDropDownView(int position, View convertView, ViewGroup parent) {
         View v = null;
         if (position == hidingItemIndex) {
             TextView tv = new TextView(getContext());
             tv.setVisibility(View.GONE);
             v = tv;
         } else {
             v = super.getDropDownView(position, null, parent);
         }
         return v;
     }
 }

Dan gunakan adaptor kustom Anda saat Anda membuat daftar item.

List<String> list = new ArrayList<String>();
list.add("");   //  Initial dummy entry
list.add("string1");
list.add("string2");
list.add("string3");

int hidingItemIndex = 0;

CustomAdapter dataAdapter = new CustomAdapter(this, android.R.layout.simple_spinner_item, list, hidingItemIndex);

dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(dataAdapter);

(Saya belum menguji kodenya) harapan yang membantu.

Aebsubis
sumber
1
Ini bukanlah solusi. Pembaruan atas pertanyaan memberikan kode yang benar.
dldnh
13
Tanpa tv.setHeight (0), TextView masih terlihat.
v4r
hai, saya telah menggunakan kode ini untuk menyembunyikan item pertama di pemintal saya, ini berfungsi dengan baik, pemintal saya akan menampilkan item kedua, tetapi ketika saya mengklik item kedua, teks pada item itu akan disetel ke pemintal saya, i tidak ingin menampilkan teks apa pun di spinner saya ketika saya mengklik item itu, tolong pandu saya?
Achin
1
Luar biasa :) Solusi sederhana :)
Chaitanya
1
Bekerja seperti pesona ..!
Krupa Kakkad
20

Lebih mudah menyembunyikan item di akhir daftar dengan memotong daftar.

Tetapi Anda harus memilihnya terlebih dahulu agar muncul di spinner, lalu periksa apakah pilihan telah diubah ke salah satu item yang ditampilkan.

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
Romich
sumber
3
Saya sedang mencari selama setengah jam mencoba menemukan pendekatan yang bersih, dan sejauh ini pendekatan yang terbaik. Potong saja daftarnya, tetapi item tersebut benar-benar ada. Luar biasa.
KSdev
1
Ini sepertinya tidak berfungsi di Lollipop, tes [Pilih satu] tidak muncul pada awalnya di Spinner. Kode yang sama pada versi Android yang lebih lama tampaknya melakukan apa yang kita semua inginkan.
Jonathan Caryl
1
Teks spinner diubah menjadi 'String3' saat orientasi berubah bahkan spinner tidak tersentuh. @Romich
Yksh
dapatkah seseorang melihat ke dalam pertanyaan saya ?
Moeez
5

Untuk menyembunyikan item apa pun di dropdown spinner, Anda harus meneruskan posisi item yang perlu disembunyikan berdasarkan kriteria yang diperlukan. Saya telah mencapai ini dalam kasus penggunaan menyembunyikan item yang dipilih dari dropdown

public class CustomAdapter extends ArrayAdapter<String> {

private List<String> dates;
private int hideItemPostion;

public CustomAdapter (Context context, int resource, List<String> dates) {
    super(context, resource,dates);
    this.dates=dates;
}
public void setItemToHide(int itemToHide)
{
    this.hideItemPostion =itemToHide;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
    View v = null;
    if (position == hideItemPostion) {
        TextView tv = new TextView(getContext());
        tv.setVisibility(View.GONE);
        tv.setHeight(0);
        v = tv;
        v.setVisibility(View.GONE);
    }
    else
        v = super.getDropDownView(position, null, parent);
    return v;
}}

Dan pengaturan adaptor adalah seperti ini

final CustomAdapter dataAdapter = new CustomAdapter(this,R.layout.spinner_item,dates);
    dataAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
    spinner.setAdapter(dataAdapter);
    dataAdapter.setItemToHide(0);

Saat memilih beberapa item dari dropdown juga posisinya perlu diubah

 spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, final int i, long l) {
        dataAdapter.notifyDataSetChanged();
            mEPGDateSelector.setSelection(i);
            dataAdapter.setItemToHide(i);}

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

        }
    });
Jiju Induchoodan
sumber
1

Hanya untuk kepentingan, saya membuat solusi untuk menggunakan "Prompt" sebagai petunjuk. Kode ini dibuat untuk Xamarin.Android, tetapi dapat dengan sempurna diporting ke Java dalam 10 menit. Gunakan seperti sederhana ArrayAdaptertanpa menambahkan item yang diindeks 0 atau diindeks hitungan ke larik sumber. Ini juga disetel SpinnerGeolocation.SelectedItemIdke -1 ketika tidak ada yang dipilih ( hintadalah item saat ini).

public class ArrayAdapterWithHint<T>: ArrayAdapter<T>
{
    protected bool HintIsSet = false;
    protected int HintResource = 0;

    public ArrayAdapterWithHint(Context context, int textViewResourceId,
                   T[] objects)
        : base(context, textViewResourceId, objects)
    {
    }
    public ArrayAdapterWithHint(Context context, int hintResource,
                   int textViewResourceId, T[] objects)
        : base(context, textViewResourceId, objects)
    {
        HintResource = hintResource;
    }
    public ArrayAdapterWithHint(Context context, int textViewResourceId,
             IList<T> objects)
        : base(context, textViewResourceId, objects)
    {
    }
    public ArrayAdapterWithHint(Context context, int hintResource,
                    int textViewResourceId, IList<T> objects)
        : base(context, textViewResourceId, objects)
    {
        HintResource = hintResource;
    }

    public override View GetDropDownView(int position, View convertView,
                ViewGroup parent)
    {
        if (HintIsSet)
            return base.GetDropDownView(position + 1,
                               convertView, parent);
        return base.GetDropDownView(position, convertView, parent);
    }

    public override View GetView(int position, View convertView,
                      ViewGroup parent)
    {
        if (!HintIsSet && parent is Spinner && 
                    !string.IsNullOrWhiteSpace((parent as Spinner).Prompt))
        {
            Insert((parent as Spinner).Prompt, 0);
            HintIsSet = true;
            (parent as Spinner).SetSelection(base.Count - 1);
        }
        if (HintIsSet && position >= base.Count - 1)
        {
            View hintView = base.GetView(0, convertView, parent);
            if (hintView is TextView)
                (hintView as TextView).SetTextAppearance(
                                                     Context, HintResource);
            return hintView;
        }
        if (HintIsSet && position < base.Count - 1)
            return base.GetView(position + 1, convertView, parent);
        return base.GetView(position, convertView, parent);
    }

    public override long GetItemId(int position)
    {
        if (HintIsSet)
        {
            if (position >= base.Count - 1)
                return -1;
            return position;
        }
        return base.GetItemId(position);
    }

    public override int Count
    {
        get
        {
            return base.Count > 0 && HintIsSet ? base.Count - 1 : base.Count;
        }
    }
}
KD
sumber
dapatkah seseorang melihat ke dalam pertanyaan saya ?
Moeez
1

Saya menemukan solusi ini yang memecahkan masalah saya.

final Spinner mySpinner = (Spinner)findViewById(R.id.spinner_triptype);

   final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.spinner_item, R.id.weekofday, triptype_initial);

   final ArrayAdapter<String> adapter_temp = new ArrayAdapter<String>
(this,R.layout.spinner_item, R.id.weekofday, triptype_array);


   mySpinner.setAdapter(adapter);
    mySpinner.setOnTouchListener(new View.OnTouchListener() {
       @Override
       public boolean onTouch(View v, MotionEvent event) {
       // display your error popup here
        if(flag_spinner_isFirst){
           mySpinner.setAdapter(adapter_temp);
           flag_spinner_isFirst = false;
          }
           v.onTouchEvent(event);
           return true;

       }
    });
Abdul Vajid
sumber
0

Saya pikir akan lebih baik untuk menempatkan validasi di Array List daripada di Spinner karena setelah item disaring, akan aman untuk ditambahkan di Spinner

Akhilesh
sumber
0

Pendekatan lain yang paling berhasil bagi saya adalah mengembalikan objek tampilan kosong baru. Ini adalah pendekatan yang sangat bersih karena Anda tidak bermain-main dengan elemen array.

Buat ekstensi kelas adaptor Anda ArrayAdapter

di dalam metode Anda

public View getView(int position, View convertView, ViewGroup parent) {
    View row = getCustomView();
    if(position==0) // put the desired check here.
         {
            row  = new View(context);
         }
    }
    return row;
}
jeet.chanchawat
sumber
0

Ini adalah pertanyaan yang sangat lama tetapi saya telah menemukan cara yang bagus (dan mungkin) bersih untuk tidak menampilkan item pertama juga. Terinspirasi oleh jawaban @ Romich, saya telah menambahkan logika serupa untuk melewati item pertama.

Ini secara efektif menyembunyikan sejumlah item (1 secara default). Kode hanya melaporkan ukuran objek yang akan dirender menjadi lebih pendek dari yang sebenarnya dan juga mengubah indeks item yang akan dirender sehingga kami melewatkan jumlah item yang berubah-ubah.

Untuk mempermudah, saya telah mengecualikan solusi yang saat ini saya gunakan yang mendukung menyembunyikan daftar item acak, tetapi itu dapat dengan mudah dikelola dengan beberapa penyesuaian pada kode.

class ArrayAdapterCustom(context: Context, textViewResourceId: Int, vararg objects: String)
    : ArrayAdapter<String>(context, textViewResourceId, objects) {

    //Can skip first n items (skip 1 as default)
    var hideFirstItemsCount = 1

    override fun getCount(): Int {
        return super.getCount() - hideFirstItemsCount
    }

    override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
        return super.getDropDownView(position + hideFirstItemsCount, convertView, parent)
    }
}
Muhamed Avdić
sumber