web-dev-qa-db-fra.com

Comment masquer un élément dans un spinner Android

Je cherche un moyen de masquer un élément dans un widget spinner Android. Cela vous permettrait de simuler un spinner sans aucun élément sélectionné et garantit que le rappel onItemSelected () est toujours appelé pour chaque élément sélectionné (si l'élément masqué est "actuel"). Normalement, il y a toujours un élément dans le compteur qui ne génère pas de rappel, à savoir l'actuel. 

Stackoverflow contient un code expliquant comment désactiver les éléments (grisé), mais pas comment les masquer complètement comme s'ils n'existaient pas.

Après de nombreuses expérimentations, je suis parvenu à une solution quelque peu astucieuse qui fonctionne sur diverses plates-formes Android anciennes et nouvelles. Il présente quelques inconvénients cosmétiques mineurs difficiles à remarquer. J'aimerais toujours entendre parler d'une solution plus officielle, à part "ne le faites pas avec une roulette". 

Cela masque toujours le premier élément de la roulette, mais peut être assez facilement é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 actuelle du spinner sur l'élément 0 avant que la boîte de dialogue ne s'ouvre, cela simulera un spinner non sélectionné.

Exemple de configuration de Spinner avec la méthode ArrayAdapter substituée:

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

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 d'index) à masquer.

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

Et utilisez votre adaptateur personnalisé lorsque vous créez la liste des éléments.

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

(Je n'ai pas testé le code) J'espère que cela vous aidera.

44
Aebsubis

Il est plus facile de masquer un élément à la fin de la liste en tronquant la liste.

Mais vous devez d'abord la sélectionner pour qu'elle apparaisse dans la roulette, puis vérifier si la sélection a été remplacée par l'un des éléments affichés.

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

Pour masquer un élément dans la liste déroulante de la liste déroulante, vous devez indiquer l'emplacement de l'élément à masquer en fonction des critères requis ..__

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

Et la configuration de 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 dans 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) {

        }
    });
4
Jiju Induchoodan

Juste pour votre intérêt, j'ai fait une solution pour utiliser "Prompt" comme un indice. Ce code est fait pour Xamarin.Android, mais il pourrait parfaitement être porté en Java en 10 minutes. Utilisez-le comme un simple ArrayAdapter sans ajouter d'éléments indexés 0 ou indexés au tableau source. Il définit également SpinnerGeolocation.SelectedItemId sur -1 lorsque rien n'est choisi (hint est l'élément actuel).

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.

J'ai trouvé cette solution qui a résolu mon problème. 

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

Je pense qu'il sera préférable de mettre la validation sur la liste de tableaux plutôt que sur Spinner, car une fois que l'élément est filtré, il sera prudent d'ajouter dans Spinner 

0
Akhilesh

C'est une question très ancienne, mais j'ai trouvé un moyen agréable (et probablement) propre de ne pas afficher les premiers éléments. Inspiré par la réponse de @ Romich, j'ai ajouté une logique similaire pour ignorer le (s) premier (s) élément (s).

Cela masque efficacement un nombre arbitraire d'éléments (1 par défaut). Le code indique uniquement que la taille des objets à rendre est plus courte que la valeur réelle et modifie également l'index des éléments à rendre afin que nous ignorions un nombre arbitraire d'éléments.

Pour garder les choses simples, j'ai exclu la solution que j'utilise actuellement qui prend en charge le masquage d'une liste d'éléments aléatoires, mais qui peut facilement être gérée par quelques ajustements au code.

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ć

Une autre approche qui fonctionne le mieux pour moi consiste à renvoyer un nouvel objet vue vide. C'est une approche nettement propre, car vous ne jouez pas avec des éléments de tableau.

Créez votre classe d'adaptateur étendant ArrayAdapter

dans votre 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;
}
0
jeet.chanchawat