Je cherche un moyen de cacher un élément dans un widget spinner Android. Cela vous permet de simuler un spinner sans éléments sélectionnés et garantit que le rappel onItemSelected () est toujours appelé pour chaque élément sélectionné (si l’élément masqué est le “actuel”). Normalement, il y a toujours un élément dans le compteur qui ne génère pas de rappel, à savoir celui en cours.
Il existe du code sur stackoverflow pour savoir comment désactiver (masquer) les éléments, mais pas comment les masquer complètement comme s’ils n’existaient pas.
Après beaucoup d’expérimentation, je suis arrivé avec une solution quelque peu piratée qui fonctionne sur diverses anciennes plates-formes Android. Il présente des inconvénients cosmétiques mineurs qui sont difficiles à remarquer. Je voudrais encore entendre parler d’une solution plus officielle, autre que “ne fais pas ça avec un fileur”.
Cela cache toujours le premier élément du spinner, mais peut facilement être étendu pour masquer un élément arbitraire ou plusieurs éléments. Ajoutez un élément factice contenant une chaîne vide au début de votre liste d’éléments Spinner. Vous voudrez peut-être définir la sélection de spinner actuelle à l’élément 0 avant que la boîte de dialog spinner s’ouvre, cela simulera un spinner non sélectionné.
Exemple d’installation Spinner avec la méthode ArrayAdapter substituer:
List list = new ArrayList(); list.add(""); // Initial dummy entry list.add("ssortingng1"); list.add("ssortingng2"); list.add("ssortingng3"); // Populate the spinner using a customized ArrayAdapter that hides the first (dummy) entry ArrayAdapter dataAdapter = new ArrayAdapter(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);
Pour masquer un élément arbitraire ou plusieurs éléments, je pense que vous pouvez implémenter votre propre adaptateur et définir l’index (ou la liste de tableaux) de l’index que vous souhaitez masquer.
public class CustomAdapter extends ArrayAdapter { private int hidingItemIndex; public CustomAdapter(Context context, int textViewResourceId, Ssortingng[] 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; } }
Et utilisez votre adaptateur personnalisé lorsque vous créez la liste des éléments.
List list = new ArrayList (); list.add(""); // Initial dummy entry list.add("ssortingng1"); list.add("ssortingng2"); list.add("ssortingng3"); 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);
(Je n’ai pas testé le code) j’espère que ça aide.
Il est plus facile de masquer un élément à la fin de la liste en tronquant la liste.
Mais vous devez d’abord le sélectionner pour qu’il apparaisse dans le compteur, puis vérifier si la sélection a été modifiée pour l’un des éléments affichés.
List list = new ArrayList (); list.add("ssortingng1"); list.add("ssortingng2"); list.add("ssortingng3"); list.add("[Select one]"); final int listsize = list.size() - 1; ArrayAdapter dataAdapter = new ArrayAdapter (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
Pour masquer un élément du menu déroulant, vous devez transmettre la position de l’élément à masquer en fonction des critères requirejs. Je l’ai réalisé dans un cas d’utilisation de cacher l’article qui est sélectionné dans la liste déroulante
public class CustomAdapter extends ArrayAdapter { private List dates; private int hideItemPostion; public CustomAdapter (Context context, int resource, List 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; }}
Et régler l’adaptateur est quelque chose comme ça
final CustomAdapter dataAdapter = new CustomAdapter(this,R.layout.spinner_item,dates); dataAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item); spinner.setAdapter(dataAdapter); dataAdapter.setItemToHide(0);
Lors de la sélection de certains éléments de la liste déroulante, la position doit également être modifiée
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) { } });
Juste par intérêt, j’ai fait une solution pour utiliser “Invite” comme indice. Ce code est fait pour Xamarin.Android
, mais il pourrait être parfaitement porté sur Java en 10 minutes. Utilisez-le comme un ArrayAdapter
simple sans append d’éléments indexés ou indexés à 0 au tableau source. Il définit également SpinnerGeolocation.SelectedItemId
à -1 lorsque rien n’est choisi (le hint
est l’élément en cours).
public class ArrayAdapterWithHint: ArrayAdapter { 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 objects) : base(context, textViewResourceId, objects) { } public ArrayAdapterWithHint(Context context, int hintResource, int textViewResourceId, IList 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 && !ssortingng.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; } } }
Je pense qu’il vaudra mieux mettre la validation sur la liste de tableaux plutôt que sur Spinner car une fois que l’élément est filtré, il sera sûr de l’append à Spinner
J’ai trouvé cette solution qui a résolu mon problème.
final Spinner mySpinner = (Spinner)findViewById(R.id.spinner_sortingptype); final ArrayAdapter adapter = new ArrayAdapter (this,R.layout.spinner_item, R.id.weekofday, sortingptype_initial); final ArrayAdapter adapter_temp = new ArrayAdapter (this,R.layout.spinner_item, R.id.weekofday, sortingptype_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; } });
Une autre approche qui a le mieux fonctionné pour moi est de renvoyer un nouvel object de vue vide. C’est une approche très nette car vous ne jouez pas avec des éléments de tableau.
Créez votre classe d’adaptateur étendant ArrayAdapter
dans ta méthode
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; }