Java 回收器视图-滚动时调整项目视图的大小(用于类似旋转木马的效果)

Java 回收器视图-滚动时调整项目视图的大小(用于类似旋转木马的效果),java,android,performance,android-layout,android-recyclerview,Java,Android,Performance,Android Layout,Android Recyclerview,我需要创建一个垂直的回收视图,在这个视图中,屏幕中央的项目视图应该调整大小,以便在滚动时具有类似缩放的效果 我尝试过但没有成功的事情: 添加滚动侦听器并按位置在项目视图中循环,测量居中位置,然后更新居中视图的布局参数 RecyclerView不允许在滚动时计算项目的位置或更新视图。如果在onScrolled 当滚动状态为“空闲”或“正在结算”时,在onScrollStateChanged中更改居中项目视图的LayoutParams 仅在滚动已完成/即将完成后更新视图,而不是在执行项目滚动期

我需要创建一个垂直的回收视图,在这个视图中,屏幕中央的项目视图应该调整大小,以便在滚动时具有类似缩放的效果

我尝试过但没有成功的事情:

  • 添加滚动侦听器并按位置在项目视图中循环,测量居中位置,然后更新居中视图的布局参数

    • RecyclerView
      不允许在滚动时计算项目的位置或更新视图。如果在
      onScrolled
  • 当滚动状态为“空闲”或“正在结算”时,在
    onScrollStateChanged
    中更改居中项目视图的
    LayoutParams

    • 仅在滚动已完成/即将完成后更新视图,而不是在执行项目滚动期间更新视图
  • 剩下的最后一个选项是实现自己的自定义
    LayoutManager
    ,它将扩展默认的
    LayoutManager

    • 据我所知,实现自定义
      Layoutmanager
      需要处理更多复杂的计算
  • 任何其他解决方案或想法都将受到赞赏。我发现,它在水平方向上做了完全相同的事情。Answer提供了扩展
    LinearLayoutManager
    的工作解决方案。我对它做了一点修改,以适应垂直列表,它可以工作。如果在执行中有任何错误,请在评论中告诉我。干杯

    自定义布局管理器:

    public class CenterZoomLayoutManager extends LinearLayoutManager {
    
        private final float mShrinkAmount = 0.15f;
        private final float mShrinkDistance = 0.9f;
    
        public CenterZoomLayoutManager(Context context) {
            super(context);
        }
    
        public CenterZoomLayoutManager(Context context, int orientation, boolean reverseLayout) {
            super(context, orientation, reverseLayout);
        }
    
    
        @Override
        public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
            int orientation = getOrientation();
            if (orientation == VERTICAL) {
                int scrolled = super.scrollVerticallyBy(dy, recycler, state);
                float midpoint = getHeight() / 2.f;
                float d0 = 0.f;
                float d1 = mShrinkDistance * midpoint;
                float s0 = 1.f;
                float s1 = 1.f - mShrinkAmount;
                for (int i = 0; i < getChildCount(); i++) {
                    View child = getChildAt(i);
                    float childMidpoint =
                            (getDecoratedBottom(child) + getDecoratedTop(child)) / 2.f;
                    float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
                    float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
                    child.setScaleX(scale);
                    child.setScaleY(scale);
                }
                return scrolled;
            } else {
                return 0;
            }
        }
    
        @Override
        public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
            int orientation = getOrientation();
            if (orientation == HORIZONTAL) {
                int scrolled = super.scrollHorizontallyBy(dx, recycler, state);
    
                float midpoint = getWidth() / 2.f;
                float d0 = 0.f;
                float d1 = mShrinkDistance * midpoint;
                float s0 = 1.f;
                float s1 = 1.f - mShrinkAmount;
                for (int i = 0; i < getChildCount(); i++) {
                    View child = getChildAt(i);
                    float childMidpoint =
                            (getDecoratedRight(child) + getDecoratedLeft(child)) / 2.f;
                    float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
                    float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
                    child.setScaleX(scale);
                    child.setScaleY(scale);
                }
                return scrolled;
            } else {
                return 0;
            }
    
        }
    }
    
    公共类CenterZoomLayoutManager扩展了LinearLayoutManager{
    私人最终浮动mShrinkAmount=0.15f;
    专用最终浮点数mShrinkDistance=0.9f;
    公共中心ZoomLayoutManager(上下文){
    超级(上下文);
    }
    公共中心ZoomLayoutManager(上下文上下文、int方向、布尔反转){
    超级(上下文、方向、反转);
    }
    @凌驾
    public int scrollVerticallyBy(int-dy,RecyclerView.recyclerRecycler,RecyclerView.State){
    int-orientation=getOrientation();
    如果(方向==垂直){
    int scrolled=super.scrollVerticallyBy(dy,recycler,state);
    浮点中点=getHeight()/2.f;
    浮点数d0=0.f;
    浮点d1=mShrinkDistance*中点;
    浮点数s0=1.f;
    浮动s1=1.f—mShrinkAmount;
    对于(int i=0;i
    水平方向:

    垂直方向:


    你知道如何使它循环吗??我有10个项目的水平回收视图。我想无限滚动它。i、 e位置1将在所有项目完成后再次出现。@RonakThakkar我认为这样的技巧会起作用:@Krupal,你有没有想过如何在下一个可滚动项目中包含窥视?@KrupalShah,谢谢你的解决方案,但这似乎对不同的移动屏幕大小不起作用。我已经用不同的屏幕尺寸测试过了,在一些设备上,左右项目看起来很完美,而在一些设备上则不完美。“我在这里说的是水平列表。”穆罕默德·法罕说,“它似乎对我有用。”。你可以自己修改。嘿@Krupal Shah,你能帮我修改一下吗