Il est possible d'utiliser des éléments de liste extensibles avec le nouveau RecyclerView? Vous aimez ExpandableListView?
Il est possible d'utiliser des éléments de liste extensibles avec le nouveau RecyclerView? Vous aimez ExpandableListView?
Réponses:
C'est simple à faire avec les LayoutManagers de stock, tout dépend de la façon dont vous gérez votre adaptateur.
Lorsque vous souhaitez développer une section, vous ajoutez simplement 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, vous supprimez simplement les éléments pertinents et appelez notifyItemRangeRemoved (). Pour toute modification de données notifiée 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 disparaissant. La suppression est l'inverse. Tout ce que vous avez à faire en plus de l'adaptateur est de styliser vos vues pour transmettre la structure logique à l'utilisateur.
Mise à jour: Ryan Brooks a maintenant écrit un article sur la façon de procéder.
Obtenez l'exemple d'implémentation de code à partir d' ici
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();
}
}
ExpandableListView
", car le contenu développé dans ce cas est une liste elle-même avec des éléments provenant de l'adaptateur. Il s'agit d'une solution dégénérée avec un seul élément autorisé en tant qu'enfant dans le groupe.
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.
Quelqu'un s'est plaint du fait que la solution mentionnée ci-dessus n'est pas utilisable avec une vue de liste en tant que contenu extensible. Mais il existe une solution simple: créez une vue de liste et remplissez cette vue de liste manuellement avec vos lignes .
Solution pour les paresseux: il existe une solution simple si vous ne voulez pas trop changer votre code. Utilisez simplement votre adaptateur manuellement pour créer des vues et les ajouter au fichier 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'assistance: 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 résumé: https://gist.github.com/MichaelFlisar/738dfa03a1579cc7338a
recyclerview
et vous pouvez développer / masquer cette vue imbriquée et utiliser toutes les optimisations durecyclerview
Vous pouvez utiliser ExpandableLayout qui ressemble à une CheckBox d'animation de développement / réduction fluide, vous pouvez donc l'utiliser comme CheckBox dans ListView et RecyclerView.
Ceci est l'exemple de code pour ce qui est mentionné par @TonicArtos pour ajouter et supprimer des éléments et pour l'animer tout en faisant, ceci est tiré de RecyclerView Animations et de l' exemple GitHub
1) Ajoutez un auditeur dans votre onCreateViewHolder () pour vous inscrire à onClick
2) Créez votre OnClickListener personnalisé 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 votre 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 n'est pas dans la même activité que Recycler View , transmettez l'instance de recyclerView à l'adaptateur lors de la création
5) itemList est un ArrayList de type mObject qui aide à maintenir les états de l'élément (Ouvrir / Fermer), le nom, le type d'élément (subItems / mainItem) et définir le thème en fonction des valeurs
public class mObject{
private String label;
private int type;
private boolean checked;
}