Android RecyclerView défilement lisse pour voir qui anime leur hauteur

J’ai un RecyclerView avec des vues enfant extensibles. Lorsque l’utilisateur clique sur ViewGroup enfant, il gonfle un nombre de vues animant la hauteur du ViewGroup de 0 à la hauteur mesurée du groupe de visualisation, comme le gif suivant:

Exemple

Le problème est le suivant: j’appelle smoothScrollToPosition sur recyclerView, cela permet de faire défiler en douceur la position de la vue, mais il prend en compte la hauteur de vue actuelle, qui n’est pas encore étendue, dans le gif ci-dessus, je touche la vue en dessous de la vue de recyclage, qui ne défilent pas à la position car la vue est déjà visible, mais lorsque je touche à nouveau (en appelant à nouveau le smoothscrolltoposition), il fait défiler la vue à la position correcte, car la vue est déjà développée.

Existe-t-il une approche permettant de faire défiler la vue en haut de l’écran ou simplement de faire défiler pour rendre le contenu visible?

Pour les références: C’est la méthode appelée pour gonfler les vues:

collapsible_content.removeAllViews(); for(int i = 0; i < 5; i++) { View link_view = getLayoutInflater().inflate(R.layout.list_item_timeline_step_link, collapsible_content, false); TextView text = (TextView) link_view.findViewById(R.id.step_link_text); text.setText("Test"); collapsible_content.addView(link_view); } 

Et voici ma méthode pour développer:

 public void toggle() { collapsible_content.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); Animation a; if (mExpanded) { a = new ExpandAnimation(collapsible_content.getLayoutParams().height, 0); } else { a = new ExpandAnimation(collapsible_content.getLayoutParams().height, getMeasuredHeight()); } a.setDuration(mAnimationDuration); collapsible_content.startAnimation(a); mExpanded = !mExpanded; } 

Et l’animation:

 private class ExpandAnimation extends Animation { private final int mStartHeight; private final int mDeltaHeight; public ExpandAnimation(int startHeight, int endHeight) { mStartHeight = startHeight; mDeltaHeight = endHeight - startHeight; } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final int newHeight = (int) (mStartHeight + mDeltaHeight * interpolatedTime); collapsible_content getLayoutParams().height = newHeight; if (newHeight <= 0) { collapsible_content setVisibility(View.GONE); } else { collapsible_content setVisibility(View.VISIBLE); } collapsible_content requestLayout(); } @Override public boolean willChangeBounds() { return true; } } 

Ma solution consistait à vérifier en permanence la vue du bas dans la méthode applyTransformation et à la comparer à la hauteur RecyclerView. Si le fond devenait supérieur à la hauteur de la RV, je fais défiler les valeurs de diff:

 final int bottom = collapsible_content.getBottom(); final int listViewHeight = mRecyclerView.getHeight(); if (bottom > listViewHeight) { final int top = collapsible_content.getTop(); if (top > 0) { mRecyclerView.smoothScrollBy(0, Math.min(bottom - listViewHeight + mRecyclerView.getPaddingBottom(), top)); } } 

L’astuce consistait à utiliser Math.min pour obtenir la vue de dessus, afin qu’elle ne défile pas, la vue de dessus ne devenant pas visible.

Solution basée sur ListViewAnimations

Ajoutez un animationlistener et lancez le défilement de la vue recyclée une fois l’animation en développement terminée.