Comment cacher un article dans un Spinner Android

je cherche un moyen de cacher un élément dans un widget Android spinner. Cela vous permettra de simuler un spinner sans aucun item sélectionné, et garantit que le callback onItemSelected() est toujours appelé pour chaque item sélectionné (si l'item caché est l'item "courant"). Normalement, il y a toujours un élément dans le spinner qui ne génère pas de callback, à savoir le courant.

il y a un certain code sur stackoverflow pour désactiver (gris out) articles, mais pas comment cacher des objets complètement comme s'ils n'existaient pas.

après beaucoup d'expérimentation, j'ai trouvé une solution quelque peu pirate qui fonctionne sur diverses anciennes et nouvelles plates-formes Android. Il a quelques inconvénients cosmétiques mineurs qui sont difficiles à remarquer. J'aimerais quand même entendre parler d'une solution plus officielle, autre que "ne fais pas ça avec un tourniquet".

cela cache toujours le premier élément dans la broche, mais pourrait assez facilement être étendu pour cacher un arbitraire élément ou de plusieurs éléments. Ajoutez un article fictif contenant une chaîne vide au début de votre liste d'articles spinner. Vous pouvez paramétrer la sélection de spinner actuelle à l'item 0 avant que la boîte de dialogue spinner s'ouvre, ce qui simulera un spinner non sélectionné.

Spinner exemple de configuration avec ArrayAdapter méthode de remplacement:

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);
91
demandé sur Georgie 2012-03-25 23:44:50

7 réponses

pour cacher un élément arbitraire ou plus d'un élément, je pense que vous pouvez implémenter votre propre adaptateur et définir l'index (ou la liste des tableaux) de l'index que vous voulez cacher.

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 articles.

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) espoir qui aide.

42
répondu Aebsubis 2013-03-01 16:52:49

il est plus facile de cacher 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 spinner, puis vérifier si la sélection a été modifiée à 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
répondu Romich 2014-02-02 20:23:10

pour cacher n'importe quel élément dans la descente de spinner vous devez passer la position de l'élément qui doit hided basé sur des critères requis. J'ai réalisé cela dans un cas d'utilisation de cacher l'élément qui est sélectionné à partir de 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;
}}

et le réglage de l'adaptateur est quelque chose comme ceci

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

        }
    });
2
répondu Jiju Induchoodan 2017-01-27 10:01:23

juste pour l'intérêt, j'ai fait une solution pour utiliser "Prompt" comme un indice. Ce code est fait pour Xamarin.Android , mais il pourrait être parfaitement porté en Java en 10 minutes. Utilisez-le comme un simple ArrayAdapter sans ajouter d'éléments indexés à 0 ou à count au tableau des sources. Il a également placé SpinnerGeolocation.SelectedItemId à -1 lorsque rien n'est choisi ( hint est l'article courant).

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
répondu K.D. 2014-05-24 16:27:59

je pense qu'il sera préférable de mettre la validation sur la liste des tableaux plutôt que sur Spinner car une fois l'élément filtré, il sera sûr d'ajouter dans Spinner

0
répondu Akhilesh 2013-02-27 12:54:38

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;

       }
    });
0
répondu Abdul Vajid 2014-08-16 13:24:01

une autre approche qui a fonctionné le mieux pour moi est de retourner un nouvel objet de vue vierge. C'est considérablement une approche propre car vous ne jouez pas avec les éléments de tableau.

créez votre classe d'Adaptateur Extension 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
répondu jeet.chanchawat 2017-01-17 12:54:49