web-dev-qa-db-fra.com

Android: Pour définir un élément comme sélectionné lorsque ListView s'ouvre?

Une activité a un bouton et une liste .. .. Initialement, seul le bouton est visible. Lorsque vous appuyez sur le bouton, ListView s’affiche. Une fois affiché, est-il possible pour moi de montrer un élément particulier comme sélectionné/focalisé?

Un cas d'utilisation pourrait être que supposons qu'il s'agisse d'une liste de paramètres de langue et que lorsque la liste s'ouvre, la langue actuellement sélectionnée doit être affichée en surbrillance.

Si je connais l'index de l'élément, comment le définir pour qu'il soit concentré sur l'affichage?

15
kiki

En bref, ListView :: setSelection (int position) est ce dont vous avez besoin. Toutefois, selon que l'appareil est en mode tactile ou non, il peut avoir ou non un effet visuel (surbrillance en arrière-plan). Pour plus de détails, consultez Problème de sélection de ListView Android

15
onlygo

Je publie ma solution, car Google ne connaît toujours pas la réponse.

getListView().setItemChecked(selectedGroupIndex, true);
39
Piotr L.

Si vous utilisez une Adapter pour votre ListView, ajoutez ce code à votre adaptateur:

public class MyAdapter extends ArrayAdapter<MyClass> {
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater inflator = (LayoutInflater) getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflator.inflate(R.layout.my_adapter, null);
        } else {
            rowView = (View) convertView;
        }

        //...

        // set selected item
        LinearLayout ActiveItem = (LinearLayout) rowView;
        if (position == selectedItem){
            ActiveItem.setBackgroundResource(R.drawable.background_dark_blue);

            // for focus on it
            int top = (ActiveItem == null) ? 0 : ActiveItem.getTop();
            ((ListView) parent).setSelectionFromTop(position, top);
        }
        else{
            ActiveItem.setBackgroundResource(R.drawable.border02);
        }    
    }

    private int selectedItem;

    public void setSelectedItem(int position) {
        selectedItem = position;
    }    
}

Dans votre Activity:

myAdapter.setSelectedItem(1);
11
Bobs

J'utilise un adaptateur et je ne souhaite pas définir de couleurs d'arrière-plan personnalisées, mais j'utilise Android: state_selected in drawable xml. SetSelection n'a pas fonctionné pour moi, mais c'est peut-être aussi parce que j'avais besoin de SetNotifyDataChanged, ce qui montre que l'état sélectionné n'est pas persistant.

J'ai également constaté que l'état sélectionné pour un élément dans un ListView n'est pas persistant, car SetNotifyDataChanged entraîne la mise à jour de la présentation ListView, qui les efface tous. Définir l'élément sur Sélectionné dans GetView de l'adaptateur est trop tôt. 

Finalement, j'ai défini l'état Selected pour la vue de l'élément sélectionné après la modification de la présentation de la liste, c'est-à-dire lorsque l'événement LayoutChange est déclenché (en Java, il est probablement lié à OnLayoutChangeListener du ListView). 

Pour que ce soit vraiment facile, je stocke la vue de l'élément sélectionné en tant que SelectedItemView de l'adaptateur . Dans le gestionnaire d'événements LayoutChange de ListView, je viens de définir le paramètre SelectedItemView de l'adaptateur sur true.

Voici le code de mon activité dans lequel je configure l'adaptateur pour ListView et que je m'abonne également à LayoutChange (ou, en Java, associe un OnLayoutChangeListener)

        ringTonesListView.Adapter = ringTonesListAdapter;
        ringTonesListView.LayoutChange += (s, layoutChangeArgs) => {
            //At this stage the layout has been updated and the Selected can be set to true for the view of the selected item. This will result in Android:state_selected logic to be applied as desired and styling can be completely done per layout in Resources.
            ringTonesListAdapter.SelectedItemView.Selected = true;
        };

Voici mon code pour l'adaptateur:

public class RingTonesListAdapter : BaseAdapter<RingToneItem>
{
    List<RingTone> Items { get; set; }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View view = convertView;

        // re-use an existing view, if one is available
        // otherwise create a new one
        if (view == null)
        {
            view = Context.LayoutInflater.Inflate(Resource.Layout.AlertSoundItem, parent, false);
            view.Click += SelectRingTone;
        }

        RingTone ringTone = this[position];
        if (ringTone.Selected)
        {
            //==> Important
            //Store this view since it's the view for the Selected Item
            SelectedItemView = view;
            //Setting view.Selected to true here doesn't help either, since Selected will be cleared after.
        }

        return view;
    }

    private void SelectRingTone(object sender, EventArgs args)
    {
        View view = (View)sender;
        string title = view.FindViewById<TextView>(Resource.Id.ringToneTitle).Text;
        RingToneItem ringToneItem = Items.First(rt => rt.Title == title);
        if (!ringToneItem.Selected)
        {
            //The RingTone was not selected and is selected now
            //Deselect Old and Select new
            foreach (RingToneItem oldItem in Items.Where(rt => rt.Selected))
            {
                oldItem.Selected = false;
            }

            // Select New RingTone
            ringToneItem.Selected = true;
            //Update the ListView. 
            //This will result in removal of Selected state for all Items when the ListView updates it's layout
            NotifyDataSetChanged();
        }

        //Now play the test sound
        NotifierService.TestSound(Context, ringToneItem);
    }

    public View SelectedItemView { get; set; }
}
0
Dacker