RecyclerView - animation of changing columns of the grid layout manager

I want to animate the change in my RecyclerView GridLayoutManager . By default, I display a list of elements in a grid with three columns, and the user can choose to show more or less columns.

I would like the views in RecyclerView move / scale to their new positions, but I have no idea how to do this.

What i want at the end

  • allow me to scale the grid using touch gestures expand / contract => I know how to do this
  • LayoutManager change of LayoutManager

Does anyone know how I can animate a change to a LayoutManager ?

+6
source share
3 answers

The inspiration here will be the Google Photos app, Sony Gallery's stock app

Basically you can use 2 approaches:

  • You are modifying spancount from GridLayoutManager using setSpanCount (int)

  • You set a very high counter (~ 100) using SpanSizeLookUp to change the value of the spanSize parameter for each fly item.

    • I used the Gist provided by Musenkishi for this answer to give the animator the ability to change the changes to the mesh settings.
    • I used this approach in a sample GitHub project implementing the same thing.
    • Cautions:
      • Currently, I used a click listener to change the appearance of the range. This could be changed to ItemGestureListener to capture scaling and change events accordingly.
      • You need to determine how to select the range calculation so that all the elements in the row occupy the entire width of the screen (and therefore you do not see empty space)
      • You call notifyItemRangeChanged with a delayed delayed message, since you cannot call notifyChanged methods from bindView / createView, etc.
      • After resizing the range, you need to notifyItemRangeChanged with the appropriate range so that all the items displayed on the screen are currently shifted accordingly. I used (code below)

This is not a complete solution, but a solution for this is 2 hours. Obviously, you can improve all the points mentioned :). I hope to continue updating the sample, as such views have always fascinated me. Do not consider this as a final decision, but simply a special way to achieve this approach. If you were to use the StaggerredLayoutManager, you could easily avoid spaces between elements.

 public int calculateRange() { int start = ((GridLayoutManager) grv.getLayoutManager()).findFirstVisibleItemPosition(); int end = ((GridLayoutManager) grv.getLayoutManager()).findLastVisibleItemPosition(); if (start < 0) start = 0; if (end < 0) end = getItemCount(); return end - start; } 
+11
source

I am dealing with the same problem as you, and so far I have not found a good solution.

Just changing the column number in the GridLayoutManager seems strange, so at the moment I'm using animation to fade out / the whole layout. Something like that:

 private void animateRecyclerLayoutChange(final int layoutSpanCount) { Animation fadeOut = new AlphaAnimation(1, 0); fadeOut.setInterpolator(new DecelerateInterpolator()); fadeOut.setDuration(400); fadeOut.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { productsRecyclerLayoutManager.setSpanCount(layoutSpanCount); productsRecyclerLayoutManager.requestLayout(); Animation fadeIn = new AlphaAnimation(0, 1); fadeIn.setInterpolator(new AccelerateInterpolator()); fadeIn.setDuration(400); productsRecycler.startAnimation(fadeIn); } }); productsRecycler.startAnimation(fadeOut); } 

If you combine burnout / animation with the scaling of each visible element, this will be a decent animation for the changes of the GridLayoutManager.

+1
source

You can do this with a "gesture detector" see the sample tutorial here http://wiki.workassis.com/pinch-zoom-in-recycler-view/ In this tutorial, we will extract images from a gallery and display them in a layout grids in recycler view. You can change the layout to a pinch gesture. Below are screenshots of different layouts.

 mScaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener() { @Override public boolean onScale(ScaleGestureDetector detector) { if (detector.getCurrentSpan() > 200 && detector.getTimeDelta() > 200) { if (detector.getCurrentSpan() - detector.getPreviousSpan() < -1) { if (mCurrentLayoutManager == mGridLayoutManager1) { mCurrentLayoutManager = mGridLayoutManager2; mRvPhotos.setLayoutManager(mGridLayoutManager2); return true; } else if (mCurrentLayoutManager == mGridLayoutManager2) { mCurrentLayoutManager = mGridLayoutManager3; mRvPhotos.setLayoutManager(mGridLayoutManager3); return true; } } else if(detector.getCurrentSpan() - detector.getPreviousSpan() > 1) { if (mCurrentLayoutManager == mGridLayoutManager3) { mCurrentLayoutManager = mGridLayoutManager2; mRvPhotos.setLayoutManager(mGridLayoutManager2); return true; } else if (mCurrentLayoutManager == mGridLayoutManager2) { mCurrentLayoutManager = mGridLayoutManager1; mRvPhotos.setLayoutManager(mGridLayoutManager1); return true; } } } return false; } }); 
+1
source

All Articles