web-dev-qa-db-fra.com

Liste extensible avec RecyclerView?

Il est possible d'utiliser des éléments de liste extensibles avec le nouveau RecyclerView? Comme ExpandableListView?

91
Dariusz Rusin

Ceci est simple à faire avec les responsables de la mise en page en stock, tout dépend de la façon dont vous gérez votre adaptateur.

Lorsque vous souhaitez développer une section, vous devez simplement ajouter de nouveaux éléments à votre adaptateur après l'en-tête. N'oubliez pas d'appeler notifyItemRangeInserted lorsque vous faites cela. Pour réduire une section, supprimez simplement les éléments pertinents et appelez notifyItemRangeRemoved (). Pour toutes les modifications de données notifiées de manière appropriée, la vue du recycleur animera les vues. Lors de l'ajout d'éléments, une zone à remplir avec les nouveaux éléments est créée, les nouveaux éléments s'estompant progressivement. La suppression est l'inverse. Tout ce que vous devez faire en plus de l'adaptateur, c'est de styliser vos vues pour transmettre la structure logique à l'utilisateur.

Mise à jour: Ryan Brooks a écrit un article sur la procédure à suivre.

118
Tonic Artos

Obtenez l'exemple de code d'implémentation de here

Définir ValueAnimator dans onClick of ViewHolder

@Override
public void onClick(final View view) {
    if (mOriginalHeight == 0) {
        mOriginalHeight = view.getHeight();
    }
    ValueAnimator valueAnimator;
    if (!mIsViewExpanded) {
        mIsViewExpanded = true;
        valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
    } else {
        mIsViewExpanded = false;
        valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
    }
    valueAnimator.setDuration(300);
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer value = (Integer) animation.getAnimatedValue();
            view.getLayoutParams().height = value.intValue();
            view.requestLayout();
        }
    });
    valueAnimator.start();

}

Voici le code final

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private TextView mFriendName;
    private int mOriginalHeight = 0;
    private boolean mIsViewExpanded = false;


    public ViewHolder(RelativeLayout v) {
        super(v);
        mFriendName = (TextView) v.findViewById(R.id.friendName);
        v.setOnClickListener(this);
    }

    @Override
    public void onClick(final View view) {
        if (mOriginalHeight == 0) {
            mOriginalHeight = view.getHeight();
        }
        ValueAnimator valueAnimator;
        if (!mIsViewExpanded) {
            mIsViewExpanded = true;
            valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
        } else {
            mIsViewExpanded = false;
            valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
        }
        valueAnimator.setDuration(300);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                view.getLayoutParams().height = value.intValue();
                view.requestLayout();
            }
        });
        valueAnimator.start();

    }
}
7
Kavin Varnan

https://github.com/gabrielemariotti/cardslib

Cette bibliothèque a une implémentation d'une liste extensible avec une vue de recyclage (reportez-vous à l'application de démonstration sous "CardViewNative" -> "Liste, Grille et RecyclerView" -> "Cartes extensibles"). Il a également beaucoup d'autres combinaisons intéressantes de cartes/listes.

3
Xinzz

Vous pouvez utiliser ExpandableLayout comme une checkBox d'animation lisse pour développer/réduire, de sorte que vous puissiez l'utiliser comme CheckBox dans ListView et RecyclerView.

https://github.com/KyoSherlock/ExpandableLayout

0
user2914737

Quelqu'un s'est plaint de ce que la solution mentionnée ci-dessus ne peut pas être utilisée avec une liste comme contenu extensible. Mais il existe une solution simple: créez une liste et remplissez-la manuellement avec vos lignes .

Solution pour les paresseux: Il existe une solution simple si vous ne voulez pas trop modifier votre code. Utilisez simplement manuellement votre adaptateur pour créer des vues et les ajouter à la variable LinearLayout.

Voici l'exemple:

if (mIsExpanded)
{
    // llExpandable... is the expandable nested LinearLayout
    llExpandable.removeAllViews();
    final ArrayAdapter<?> adapter = ... // create your adapter as if you would use it for a ListView
    for (int i = 0; i < adapter.getCount(); i++)
    {
        View item = adapter.getView(i, null, null);
        // if you want the item to be selectable as if it would be in a default ListView, then you can add following code as well:
        item.setBackgroundResource(Functions.getThemeReference(context, Android.R.attr.selectableItemBackground));
        item.setTag(i);
        item.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // item would be retrieved with: 
                // adapter.getItem((Integer)v.getTag())
            }
        });
        llExpandable.addView(item);
    }
    ExpandUtils.expand(llExpandable, null, 500);
}
else
{
    ExpandUtils.collapse(llExpandable, null, 500);
}

fonctions d'aide: getThemeReference

public static int getThemeReference(Context context, int attribute)
{
    TypedValue typeValue = new TypedValue();
    context.getTheme().resolveAttribute(attribute, typeValue, false);
    if (typeValue.type == TypedValue.TYPE_REFERENCE)
    {
        int ref = typeValue.data;
        return ref;
    }
    else
    {
        return -1;
    }
}

classe d'assistance: ExpandUtils

Kavin Varnan postet déjà comment animer une mise en page ... Mais si vous voulez utiliser ma classe, n'hésitez pas à le faire, j'ai posté un Gist: https://Gist.github.com/MichaelFlisar/738dfa03a1579cc7338a

0
prom85

Vous pouvez simplement changer votre code pour obtenir une lisibilité maximale. Vous devez donc utiliser la méthode notifyItemChanged() à la place de l'animateur de valeurs. Vérifiez ma réponse pour cela. Vous pouvez gagner beaucoup de temps en le faisant.

utilisez simplement notifyItemChanged () `là où il est nécessaire de réduire et d’agrandir les vues.

N'utilisez pas de bibliothèque ni de code complexe pour cela.

voir this

0
Kiran Benny Joseph

Ceci est l'exemple de code pour ce qui est mentionné par @ TonicArtos pour ajouter et supprimer des éléments et pour l'animer en même temps, ceci est pris de RecyclerView Animations et exemple GitHub

1) Ajoutez un écouteur dans votre onCreateViewHolder () pour vous inscrire à onClick

2) Créez votre personnalisation OnClickListener dans votre adaptateur.

private View.OnClickListener mItemListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        TextView tv = (TextView) v.findViewById(R.id.tvItems);
        String selected = tv.getText().toString();
        boolean checked = itemsList.get(recyclerView.getChildAdapterPosition(v)).isChecked();

        switch (selected){
            case "Item1":
                if(checked){
                    deleteItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
                }else {
                    addItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
                }
                break;
            case "Item2":
                if(checked){
                    deleteItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
                }else {
                    addItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
                }
                break;                 
            default:
                //In my case I have checkList in subItems,
                //checkItem(v);
                break;
        }
    }
};

3) Ajoutez vos addItem () et deleteItem ()

private void addItem(View view){
    int position = recyclerView.getChildLayoutPosition(view);
    if (position != RecyclerView.NO_POSITION){
        navDrawItems.add(position+1,new mObject());
        navDrawItems.add(position+2,new mObject());
        notifyItemRangeInserted(position+1,2);
    }
}


private void deleteItem(View view) {
    int position = recyclerView.getChildLayoutPosition(view);
    if (position != RecyclerView.NO_POSITION) {
        navDrawItems.remove(position+2);
        navDrawItems.remove(position+1);
        notifyItemRangeRemoved(position+1,2);
    }
}

4) Si votre RecyclerViewAdapter ne se trouve pas dans la même activité que la vue Recycler , transmettez l’instance de recyclerView à l’adaptateur lors de la création

5) itemList est un ArrayList de type mObject qui permet de conserver les états de item (Open/Close), nom, type d'élément (subItems/mainItem) et définition du thème en fonction des valeurs

public class mObject{
    private String label;
    private int type;
    private boolean checked;
} 
0
Ujju