एंड्रॉइड स्पिनर में एक आइटम को कैसे छिपाएं


101

मैं एंड्रॉइड स्पिनर विजेट में एक आइटम को छिपाने का तरीका ढूंढ रहा हूं। यह आपको किसी स्पिनर को चुने हुए आइटम के साथ अनुकरण करने की अनुमति देगा, और यह सुनिश्चित करता है कि onItemSelected () कॉलबैक को हमेशा चुने गए प्रत्येक आइटम के लिए कहा जाता है (यदि छिपा आइटम "वर्तमान" एक है)। आम तौर पर स्पिनर में हमेशा एक आइटम होता है जो कॉलबैक उत्पन्न नहीं करता है, अर्थात् वर्तमान एक।

कैसे (ग्रे आउट) आइटमों को अक्षम करने के लिए स्टैकओवरफ़्लो पर कुछ कोड है, लेकिन आइटम को पूरी तरह से छिपाने के लिए कैसे नहीं जैसे कि वे मौजूद नहीं हैं।

बहुत प्रयोग के बाद मैं कुछ हद तक हैक-ईश समाधान के साथ आया हूं जो विभिन्न पुराने और नए एंड्रॉइड प्लेटफार्मों पर काम करता है। इसमें कुछ मामूली कॉस्मेटिक कमियां हैं जिन्हें नोटिस करना मुश्किल है। मैं अभी भी एक अधिक आधिकारिक समाधान के बारे में सुनना चाहूंगा, "स्पिनर के साथ ऐसा न करें" के अलावा।

यह हमेशा स्पिनर में पहला आइटम छिपाता है, लेकिन एक आइटम या एक से अधिक आइटम को छिपाने के लिए काफी आसानी से बढ़ाया जा सकता है। स्पिनर आइटम की अपनी सूची की शुरुआत में एक खाली स्ट्रिंग युक्त डमी आइटम जोड़ें। स्पिनर संवाद खुलने से पहले आप वर्तमान स्पिनर चयन को आइटम 0 पर सेट करना चाह सकते हैं, यह एक अचयनित स्पिनर को अनुकरण करेगा।

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

आपने अन्य इंटरव्यू पर क्या पाया है? अब तक तुमने क्या प्रयास किये हैं?
dldnh

माफ करना, मैं नहीं जानता कि कैसे करना है।
लुसथ

अच्छा समाधान! लेकिन मुझे लगता है कि tv.setVisibility(View.GONE);लाइन अनावश्यक है। यह टिप्पणी करते हुए कम से कम Android 4.4.2 / KitKit (LG / Google Nexus 4 पर) पर कोई (दृश्य) अंतर नहीं लगता है।
मथायस

इस सवाल का जवाब अच्छी तरह से काम करता है ..
Rat-a-tat-a-tat-Ratatouille

यह एक सुधार नहीं हो सकता है, लेकिन मैंने setTag(1)स्थिति 0 पर textView पर उपयोग किया है, फिर convertView.getTag() != nullयह निर्धारित करने के लिए उपयोग किया जाता है कि पुन: उपयोग किया गया दृश्य स्थिति 0 के लिए बनाया गया 0 ऊंचाई दृश्य या अन्य स्पिनर आइटम के लिए उपयोग किया जाने वाला सामान्य दृश्य है। ऐसा था इसलिए मैं super.getDropDownView(position, convertView, parent)हमेशा एक नया दृश्य बनाने के बजाय कभी-कभी उपयोग कर सकता था ।
डैनियल हांडोजो

जवाबों:


49

एक मनमाना आइटम या एक से अधिक आइटम छिपाने के लिए मुझे लगता है कि आप अपने स्वयं के एडेप्टर को लागू कर सकते हैं और सूचकांक (या अनुक्रमित की सरणी सूची) सेट कर सकते हैं जिसे आप छिपाना चाहते हैं।

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

और आइटमों की सूची बनाते समय अपने कस्टम एडेप्टर का उपयोग करें।

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

(मैंने कोड का परीक्षण नहीं किया है) आशा है कि मदद करता है।


1
यह कोई हल नहीं है। प्रश्न का अद्यतन सही कोड प्रदान करता है।
dldnh

13
TV.setHeight (0) के बिना, TextView अभी भी दिखाई देता है।
v4r

नमस्ते, मैंने अपने स्पिनर में पहले आइटम को छिपाने के लिए इस कोड का उपयोग किया है, यह ठीक काम कर रहा है, मेरा स्पिनर मुझे दूसरा आइटम दिखाएगा, लेकिन जब मैंने क्लिक किया तो उस आइटम पर दूसरा आइटम मेरे स्पिनर को सेट हो जाएगा, i जब मैं उस आइटम पर क्लिक करता हूं, तो कृपया मेरे स्पिनर पर कोई पाठ न दिखाएं, कृपया मेरा मार्गदर्शन करें?
अचिन

1
विस्मयकारी :) सरल समाधान :)
चैतन्य

1
एक जादू की तरह काम करता है..!
कृप कक्कड़

20

सूची को समाप्त करके सूची के अंत में किसी आइटम को छिपाना आसान है।

लेकिन आपको इसे पहले चुनना होगा इसलिए यह स्पिनर में दिखाई देता है, और फिर जांचें कि क्या चयन प्रदर्शित आइटम में से किसी एक में बदल दिया गया है।

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

3
मैं एक आधे घंटे की खोज कर रहा था ताकि एक साफ दृष्टिकोण मिल जाए, और यह अब तक का सबसे अच्छा तरीका है। बस सूची को छोटा करें, लेकिन वास्तव में आइटम मौजूद है। अति उत्कृष्ट।
केएसदेव

1
यह लॉलीपॉप में काम नहीं करता है, [एक का चयन करें] परीक्षण शुरुआत में स्पिनर में दिखाई नहीं देता है। पुराने एंड्रॉइड संस्करणों पर समान कोड वही करता है जो हम सभी चाहते हैं।
जोनाथन कैरल

1
स्पिनर पाठ को अभिविन्यास परिवर्तन पर 'स्ट्रिंग 3' में बदल दिया जाता है, यहां तक ​​कि स्पिनर भी अछूता नहीं है। @ रोमीच
यक्ष

किसी को भी मेरे सवाल में देख सकते हैं ?
मोइज

5

स्पिनर ड्रॉपडाउन में किसी भी आइटम को छिपाने के लिए आपको उस आइटम की स्थिति को पारित करने की आवश्यकता है जो आवश्यक मानदंडों के आधार पर चंगा करने की आवश्यकता है। मैंने इसे आइटम को छिपाने के एक उपयोग के मामले में हासिल किया है जो ड्रॉपडाउन से चुना गया है

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

और एडेप्टर सेट करना कुछ इस तरह है

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

ड्रॉपडाउन से कुछ वस्तुओं का चयन करने पर भी स्थिति को बदलना होगा

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

        }
    });

1

बस रुचि के लिए, मैंने संकेत के रूप में "प्रॉम्प्ट" का उपयोग करने के लिए एक समाधान बनाया। यह कोड के लिए बनाया गया है Xamarin.Android, लेकिन इसे 10 मिनट में जावा में पूरी तरह से पोर्ट किया जा सकता है। ArrayAdapterस्रोत सरणी में 0-अनुक्रमित या गिनती-अनुक्रमित आइटम को जोड़े बिना इसे एक साधारण की तरह उपयोग करें । यह भी SpinnerGeolocation.SelectedItemId-1 पर सेट होता है जब कुछ भी नहीं चुना जाता है ( hintवर्तमान आइटम है)।

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

किसी को भी मेरे सवाल में देख सकते हैं ?
मोइज

1

मुझे इसका हल मिल गया जिससे मेरी समस्या हल हो गई।

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;

       }
    });

0

मुझे लगता है कि स्पिनर के बजाय ऐरे लिस्ट पर सत्यापन करना बेहतर होगा क्योंकि एक बार आइटम फ़िल्टर हो जाने के बाद, स्पिनर में जोड़ना सुरक्षित होगा


0

एक और दृष्टिकोण जो मेरे लिए सबसे अच्छा काम करता है वह है एक नया रिक्त दृश्य ऑब्जेक्ट वापस करना। यह काफी साफ-सुथरा दृष्टिकोण है क्योंकि आप ऐरे तत्वों से नहीं खेल रहे हैं।

अपना एडेप्टर क्लास बढ़ाएँ बनाएँ ArrayAdapter

अपने तरीके के अंदर

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

0

यह बहुत पुराना सवाल है, लेकिन मैंने एक अच्छा (और शायद) साफ-सुथरा तरीका पाया है कि पहले आइटम भी न दिखाएं। @ रोमिच के जवाब से प्रेरित होकर मैंने पहले आइटम को छोड़ने के लिए इसी तरह के तर्क जोड़े हैं।

यह प्रभावी रूप से आइटमों की मनमानी संख्या को छिपाता है (1 डिफ़ॉल्ट रूप से)। कोड केवल वस्तुओं के आकार को रिपोर्ट करता है ताकि वह वास्तव में कम से कम हो और रेंडर किए जाने वाले आइटम के इंडेक्स को बदल सके ताकि हम वस्तुओं की संख्या को छोड़ दें।

चीजों को सरल रखने के लिए मैंने उस समाधान को छोड़ दिया है जिसका मैं वर्तमान में उपयोग कर रहा हूं जो यादृच्छिक वस्तुओं की सूची को छिपाने का समर्थन करता है, लेकिन यह आसानी से कोड के लिए कुछ tweaks द्वारा प्रबंधित किया जा सकता है।

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)
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.