/* * */ package syncthing.android.ui.common; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; /** * Helper to animate collapse and expand animation */ public class ExpandCollapseHelper { /** * This method expandes the view that was clicked. * * @param expandingLayout layout to expand * @param cardView cardView * @param recyclerView recyclerView */ public static void animateCollapsing(final View expandingLayout, final ExpandableView cardView, final RecyclerView recyclerView, boolean wobble) { final int origHeight = expandingLayout.getHeight(); ValueAnimator animator = createHeightAnimator(expandingLayout, origHeight, 0); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(final Animator animator) { expandingLayout.setVisibility(View.GONE); //reset height else recycled views never show ViewGroup.LayoutParams layoutParams = expandingLayout.getLayoutParams(); layoutParams.height = origHeight; expandingLayout.setLayoutParams(layoutParams); cardView.getExpandable().setExpanded(false); //notifyAdapter(recyclerView, recyclerView.getLayoutManager().getPosition((View)cardView)); // Card card = cardView.getCard(); // if (card.getOnCollapseAnimatorEndListener()!=null) // card.getOnCollapseAnimatorEndListener().onCollapseEnd(card); } }); if (wobble) { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(animator, createWobbleAnimator(cardView.getView())); animatorSet.start(); } else { animator.start(); } } /** * This method collapse the view that was clicked. * * @param expandingLayout layout to collapse * @param cardView cardView * @param recyclerView recyclerView */ public static void animateExpanding(final View expandingLayout, final ExpandableView cardView, final RecyclerView recyclerView, boolean wobble) { /* Update the layout so the extra content becomes visible.*/ expandingLayout.setVisibility(View.VISIBLE); View parent = (View) expandingLayout.getParent(); final int widthSpec = View.MeasureSpec.makeMeasureSpec( parent.getMeasuredWidth() - parent.getPaddingLeft() - parent.getPaddingRight(), View.MeasureSpec.AT_MOST); final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); expandingLayout.measure(widthSpec, heightSpec); ValueAnimator animator = createHeightAnimator(expandingLayout, 0, expandingLayout.getMeasuredHeight()); if (recyclerView != null) { animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { final int listViewHeight = recyclerView.getHeight(); final int listViewBottomPadding = recyclerView.getPaddingBottom(); final View v = findDirectChild(expandingLayout, recyclerView); @Override public void onAnimationUpdate(final ValueAnimator valueAnimator) { if (recyclerView.getLayoutManager().canScrollVertically()) { final int bottom = v.getBottom(); if (bottom > listViewHeight) { final int top = v.getTop(); if (top > 0) { //recyclerView.scrollBy(0,Math.min(bottom - listViewHeight + listViewBottomPadding, top)); recyclerView.smoothScrollBy(0,Math.min(bottom - listViewHeight + listViewBottomPadding + 4, top)); } } } } }); } animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); cardView.getExpandable().setExpanded(true); //notifyAdapter(recyclerView,recyclerView.getLayoutManager().getPosition((View)cardView)); // Card card = cardView.getCard(); // if (card.getOnExpandAnimatorEndListener()!=null) // card.getOnExpandAnimatorEndListener().onExpandEnd(card); } }); if (wobble) { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(animator, createWobbleAnimator((View)cardView)); animatorSet.start(); } else { animator.start(); } } private static View findDirectChild(final View view, final RecyclerView recyclerView) { View result = view; View parent = (View) result.getParent(); while (parent != recyclerView) { result = parent; parent = (View) result.getParent(); } return result; } public static ValueAnimator createHeightAnimator(final View view, final int start, final int end) { ValueAnimator animator = ValueAnimator.ofInt(start, end); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(final ValueAnimator valueAnimator) { int value = (Integer) valueAnimator.getAnimatedValue(); ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); layoutParams.height = value; view.setLayoutParams(layoutParams); } }); return animator; } public static Animator createWobbleAnimator(final View view) { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "rotationX", 0f, 30f); objectAnimator.setDuration(100); objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(view, "rotationX", 30f, 0f); objectAnimator.setDuration(100); objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); AnimatorSet set = new AnimatorSet(); set.playSequentially(objectAnimator, objectAnimator2); return set; } /** * This method notifies the adapter after setting expand value inside cards * * @param recyclerView */ public static void notifyAdapter(RecyclerView recyclerView, int position){ if (recyclerView instanceof CardRecyclerView) { CardRecyclerView cardRecyclerView = (CardRecyclerView) recyclerView; if (cardRecyclerView.getAdapter()!=null){ cardRecyclerView.getAdapter().notifyItemChanged(position); } } } }