web-dev-qa-db-fra.com

Comment ajouter des séparateurs / séparateurs de section à un ListView?

Je crée actuellement un menu pour mon application, en utilisant un DrawerLayout et une sous-classe ArrayAdapter pour réaliser quelque chose qui ressemble au menu du tiroir de Facebook.

Je n'ai actuellement aucun problème à créer la liste, mais maintenant qu'elle a l'air bien, je voudrais ajouter des séparateurs entre différents types d'options (c'est-à-dire des options liées à l'utilisateur et liées à l'application) et une barre de recherche en haut du menu.

Le code de ma sous-classe ArrayAdaptor actuelle est le suivant:

public class DrawerMenuAdapter extends ArrayAdapter<String>{
    private Context context;
    private String[] values;
    private int resId;

    public DrawerMenuAdapter(Context context, int textViewResourceId, String[] values) {
        super(context, textViewResourceId, values);
        this.context = context;
        this.values = values;
        this.resId = textViewResourceId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(this.resId, parent, false);

        TextView elementText = (TextView)rowView.findViewById(R.id.element_text);
        ImageView elementImage = (ImageView)rowView.findViewById(R.id.element_icon);
        String textValue = values[position];

        elementText.setText(textValue);

        //This switch adds the icons to the related elements
        switch (position){
            case 0:
                elementImage.setImageResource(R.drawable.search);
                break;
            case 1:
                elementImage.setImageResource(R.drawable.facebook_friends);
                break;
            case 2:
                elementImage.setImageResource(R.drawable.flirts_history);
                break;
            case 3:
                elementImage.setImageResource(R.drawable.premium);
                break;
            case 4:
                elementImage.setImageResource(R.drawable.settings);
                break;
            case 5:
                elementImage.setImageResource(R.drawable.share_app);
                break;
            case 6:
                elementImage.setImageResource(R.drawable.cgu);
                break;
        }


        return rowView;
    }
}

Je suppose que je dois remplacer la fonction qui remplit ListView en appelant la fonction getView, mais je ne trouve pas de quelle fonction il s'agit.

33
Jivay

Si vous voulez des sections simples dans votre ListView , jetez un œil à ce tutoriel:

http://cyrilmottier.com/2011/07/05/listview-tips-tricks-2-section-your-listview/

ou ce tutoriel:

http://bartinger.at/listview-with-sectionsseparators/

Le second n'est pas aussi détaillé, mais probablement plus facile à comprendre/plus simple.

L'idée de base est que vous faites en sorte que votre ListAdapter ait différents types de vues. Par exemple, deux vues différentes où une sorte est l'élément de liste réel affichant les informations, et l'autre type de vue étant le séparateur de section.

Du tutoriel:

ListViews et plus spécifiquement Les adaptateurs peuvent gérer plusieurs types de vues . Si vous jetez un œil à l'interface de l'adaptateur, vous remarquerez qu'elle contient deux méthodes spécifiques:

  • getViewTypeCount() qui renvoie le nombre de types de vues gérés par votre AdapterView. La plupart du temps, cette méthode renvoie 1 car tous les éléments de ListView sont similaires. Dans ce cas, en retournant 2, le ListView gérera deux types de vues: les vues d'élément standard et les vues de séparation
  • getItemViewType(int) doit renvoyer un entier entre 0 (inclus) et getViewTypeCount() (exclusif). Le nombre donné exprime le type de la vue à la position donnée. Par exemple, nous pouvons nous assurer que les valeurs renvoyées sont 0 pour les vues d'élément standard et 1 pour les séparateurs
38
Philipp Jahoda

J'ajoute une réponse ici car j'ai trouvé une autre façon d'y parvenir. Cela ressemble un peu aux liens publiés par @Phil.

J'ai d'abord défini un tableau de chaînes du menu que je veux afficher. J'ai écrit ce tableau dans un fichier de ressources XML pour plus de commodité.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array
            name="drawer_menu_options">
        <item>Username</item>
        <item>-sep-Flirter</item>
        <item>Recherche</item>
        <item>Amis Facebook</item>
        <item>Flirts</item>
        <item>Compte premium</item>
        <item>-sep-Menu</item>
        <item>Réglages</item>
        <item>Inviter des amis</item>
        <item>CGU</item>
    </string-array>
</resources>

Notez que j'ai deux éléments utilisant le préfixe -sep-. Ce seront nos séparateurs.

Vient ensuite le DrawerMenuAdapter que j'ai montré plus tôt, qui est toujours un ArrayAdapter, sur lequel j'ai ajouté quelques fonctionnalités:

public class DrawerMenuAdapter extends ArrayAdapter<String>{
    private Context context;
    private String[] values;
    private int resId;
    private int separatorId = 0;
    private int userbarId = 0;

    public DrawerMenuAdapter(Context context, int textViewResourceId, String[] values) {
        super(context, textViewResourceId, values);
        this.context = context;
        this.values = values;
        this.resId = textViewResourceId;
    }

    public void setSeparator(int resId){
        separatorId = resId;
    }

    public void setUserbarId(int resId){
        userbarId = resId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        View rowView;

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if(userbarId != 0 && values[position].equals("Username")){
            rowView = inflater.inflate(this.userbarId, parent, false);

        }else if(separatorId != 0 && values[position].startsWith("-sep-")){
            rowView = inflater.inflate(this.separatorId, parent, false);

        }else{
            rowView = inflater.inflate(this.resId, parent, false);
        }

        TextView elementText = (TextView)rowView.findViewById(R.id.element_text);
        String textValue = values[position];

        /* If the current line is a separator, just display a separator. Otherwise, set the
        matching picture
         */
        if(textValue.startsWith("-sep-")){
            elementText.setText(textValue.substring("-sep-".length()));

        }else{
            if(textValue.equals("Username")){
                elementText.setText(context.getSharedPreferences("LovRUserSettings", 0)
                        .getString("firstName", "Username"));
            }else{
                elementText.setText(textValue);
            }
            ImageView elementImage = (ImageView)rowView.findViewById(R.id.element_icon);
            switch (position){
                case 2:
                    elementImage.setImageResource(R.drawable.search);
                    break;
                case 3:
                    elementImage.setImageResource(R.drawable.facebook_friends);
                    break;
                case 4:
                    elementImage.setImageResource(R.drawable.flirts_history);
                    break;
                case 5:
                    elementImage.setImageResource(R.drawable.premium);
                    break;
                case 7:
                    elementImage.setImageResource(R.drawable.settings);
                    break;
                case 8:
                    elementImage.setImageResource(R.drawable.share_app);
                    break;
                case 9:
                    elementImage.setImageResource(R.drawable.cgu);
                    break;
            }
        }


        return rowView;
    }
}

Dans ce code, il y a un objet appelé userBar. Vous n'avez pas vraiment besoin de faire attention à cela, mais si vous êtes intéressé, c'est un autre élément de menu, en utilisant un fichier de mise en page spécifique au lieu de celui que j'utilise pour les éléments de menu réguliers. C'est un moyen de démontrer que vous pouvez ajouter n'importe quel type de mise en page spécifique n'importe où, simplement en lisant vos chaînes.

Le point principal ici est dans la façon dont le code recherche les séparateurs, les chaînes avec le -sep- préfixe. Une fois trouvé, le préfixe est supprimé et la mise en page correspondante est attribuée au séparateur.

C'est ce que j'ai trouvé. Après cela, vous devrez trouver votre propre moyen d'ajouter des écouteurs de clic. Les mines sont implantées dans le DrawerLayout.setOnCliclListener qui fait le travail exactement de la même manière que la documentation de Google le dit. Mais vous pouvez également utiliser setOnclickListenerà votre vue au fur et à mesure que vous les ajoutez, et utiliser un fichier XML dans lequel vous pouvez définir vos propres attributs onClick ...

J'espère que cela vous aidera =)

7
Jivay