wake-up-neo.com

So blenden Sie ein Element in einem Android-Spinner aus

Ich suche nach einer Möglichkeit, ein Element in einem Android-Spinner-Widget auszublenden. Auf diese Weise können Sie einen Spinner ohne ausgewählte Elemente simulieren und sicherstellen, dass der Callback onItemSelected () immer für jedes ausgewählte Element aufgerufen wird (wenn das ausgeblendete Element das "aktuelle" Element ist). Normalerweise gibt es immer einen Eintrag im Spinner, der keinen Rückruf generiert, nämlich den aktuellen. 

In stackoverflow gibt es etwas Code zum Deaktivieren (Ausblenden) von Elementen, nicht jedoch zum vollständigen Ausblenden von Elementen, als wären sie nicht vorhanden.

Nach langem Experimentieren habe ich eine etwas hackhafte Lösung gefunden, die auf verschiedenen alten und neuen Android-Plattformen funktioniert. Es hat einige kleinere kosmetische Nachteile, die schwer zu bemerken sind. Ich würde immer noch gerne von einer offizielleren Lösung hören, abgesehen von "Mach das nicht mit einem Spinner". 

Dadurch wird immer das erste Element im Spinner ausgeblendet, es kann jedoch relativ einfach erweitert werden, um ein beliebiges Element oder mehrere Elemente auszublenden. Fügen Sie ein Dummy-Element mit einer leeren Zeichenfolge am Anfang Ihrer Liste mit Spinner-Elementen hinzu. Möglicherweise möchten Sie die aktuelle Auswahl des Spinners auf Element 0 setzen, bevor das Dialogfeld "Spinner" geöffnet wird. Dies simuliert einen nicht ausgewählten Spinner.

Spinner-Setup-Beispiel mit ArrayAdapter-Methode überschreiben:

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

Um ein beliebiges Element oder mehrere Elemente auszublenden, denke ich, dass Sie Ihren eigenen Adapter implementieren und den Index (oder die Arrayliste der Indizes) festlegen können, den Sie ausblenden möchten.

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

Verwenden Sie Ihren benutzerdefinierten Adapter, wenn Sie die Liste der Elemente erstellen.

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

(Ich habe den Code nicht getestet) hoffe das hilft.

44
Aebsubis

Es ist einfacher, ein Element am Ende der Liste auszublenden, indem Sie die Liste abschneiden.

Sie müssen es jedoch zuerst auswählen, damit es im Spinner angezeigt wird, und dann prüfen, ob die Auswahl zu einem der angezeigten Elemente geändert wurde.

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

Um ein Element in der Spinner-Dropdownliste auszublenden, müssen Sie die Position des Elements, die aufgrund der erforderlichen Kriterien ausgeblendet werden muss, übergeben. Ich habe dies in einem Anwendungsfall erreicht, in dem das aus der Dropdownliste ausgewählte Element ausgeblendet wird

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

Und das Einstellen des Adapters ist so ähnlich

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

Bei der Auswahl einiger Elemente aus der Dropdown-Liste muss auch die Position geändert werden

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

        }
    });
4

Aus Interesse habe ich eine Lösung gefunden, um "Prompt" als Hinweis zu verwenden. Dieser Code wurde für Xamarin.Android erstellt, kann aber in 10 Minuten perfekt nach Java portiert werden. Verwenden Sie es wie eine einfache ArrayAdapter, ohne dem Quellarray 0-indizierte oder count-indizierte Elemente hinzuzufügen. Es setzt auch SpinnerGeolocation.SelectedItemId auf -1, wenn nichts ausgewählt wird (hint ist das aktuelle Element).

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
K.D.

Ich habe diese Lösung gefunden, die mein Problem gelöst hat. 

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;

       }
    });
1
Abdul Vajid

Ich denke, es ist besser, die Validierung in die Array-Liste als in den Spinner zu stellen, denn sobald das Element gefiltert ist, kann es sicher in Spinner hinzugefügt werden 

0
Akhilesh

Dies ist eine sehr alte Frage, aber ich habe eine nette (und wahrscheinlich) saubere Möglichkeit gefunden, die ersten Gegenstände ebenfalls nicht zu zeigen. Inspiriert von @ Romichs Antwort habe ich eine ähnliche Logik hinzugefügt, um die ersten Elemente zu überspringen.

Dadurch wird eine beliebige Anzahl von Elementen ausgeblendet (standardmäßig 1). Der Code gibt nur an, dass die Größe der zu rendernden Objekte kürzer ist als sie tatsächlich ist, und ändert auch den Index der zu rendernden Elemente, sodass eine beliebige Anzahl von Elementen übersprungen wird.

Um die Dinge einfach zu halten, habe ich eine Lösung ausgeschlossen, die das Ausblenden von Listen mit zufälligen Elementen unterstützt, die jedoch mit wenigen Änderungen am Code problemlos verwaltet werden kann.

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)
    }
}
0
Muhamed Avdić

Ein anderer Ansatz, der für mich am besten funktioniert hat, ist die Rückgabe eines neuen leeren Ansichtsobjekts. Dies ist ein ziemlich sauberer Ansatz, da Sie nicht mit Array-Elementen spielen.

Erstellen Sie Ihre Adapterklasse, die ArrayAdapter erweitert.

in deiner Methode

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
jeet.chanchawat