RecyclerView - 动画更改网格布局管理器列

时间:2016-01-29 10:51:20

标签: android android-recyclerview

我想动画RecyclerView GridLayoutManager的更改动画。我默认显示一个包含3列的网格中的项目列表,用户可以选择显示更多或更少的列。

我希望views中的RecyclerView移动/扩展到新的位置,但我不知道如何做到这一点。

最终我想要的是什么

  • 允许通过展开/收缩触摸手势来缩放网格=>我知道该怎么做
  • LayoutManager
  • 的更改设置动画

有谁知道我如何为LayoutManager的变化添加动画?

3 个答案:

答案 0 :(得分:12)

这里的灵感来源是Google相册应用,股票索尼图库应用

基本上有两种方法可供选择:

  1. 使用setSpanCount(int)

  2. 修改GridLayoutManager的spancount
  3. 您设置了一个非常高的跨度计数(~100),使用SpanSizeLookUp可以动态更改每个项目的spanSize。

    • 我使用了Musenkishi提供的Gist,为this answer提供动画制作动画来更改网格布局更改的动画
    • 我在实现相同的sample GitHub project中使用了这种方法。
    • 注意事项:
      • 我目前使用点击监听器继续修改跨度大小查找。可以将其更改为ItemGestureListener以捕获缩放缩放事件并相应地更改。
      • 您需要确定一种选择跨度计数的方法,以便一行中的所有项目占据整个屏幕宽度(因此您看不到任何空白区域)
      • 您使用延迟的可运行帖子调用notifyItemRangeChanged,因为您无法从bindView / createView等中调用notifyChanged方法。
      • 更改跨度大小后,您需要notifyItemRangeChanged具有适当的范围,以便屏幕上当前显示的所有项目都相应地移动。我使用过(底部的代码)
  4. 这不是一个完整的解决方案,而是一个2小时的解决方案。你可以明显改善提到的所有要点:)。 我希望不断更新样本,因为这种观点一直让我着迷。 不要将此视为最终解决方案,而只是实现此方法的特定方式。如果您使用的是StaggerredLayoutManager,则可以轻松避免项之间的空格。

    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;
      }
    

答案 1 :(得分:2)

我处理与你相同的问题,到目前为止我还没有找到一个好的解决方案。

GridLayoutManager中列号的简单更改似乎很奇怪,所以现在我使用动画淡出/整个布局。像这样:

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);
}

如果您将淡出/动画与缩放每个可见项组合在一起,那么对于GridLayoutManager的更改,它将是一个不错的动画。

答案 2 :(得分:1)

你可以用“手势探测器”做到这一点 请参阅示例教程http://wiki.workassis.com/pinch-zoom-in-recycler-view/在本教程中,我们将从图库中获取图像,并在回收器视图中以网格布局显示它们。您将能够在捏合手势上更改布局。以下是不同布局的屏幕截图。

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;
                }
            });