8

スクロール中にズームのような効果を得るために画面中央のアイテムビューのサイズを変更する必要がある垂直リサイクルビューを作成する必要があります。Recyclerビュー - スクロール時にアイテムビューのサイズを変更する(カルーセルのような効果のために)

  1. は、スクロールリスナーを追加し、位置によってアイテムの景色をループし、中心viewLayoutParamsを更新中心位置を測定する:私が試してみましたが、うまくいきませんでした

    物事。

    • RecyclerViewは、スクロール中にアイテムの位置を計算したり、ビューを更新することはできません。このような操作は、スクロール状態がIDLE又はSETTLINGであるonScrollStateChangedにおける中心アイテムビューのLayoutParams変更onScrolled
  2. で実行される場合にはIllegalStateExceptionをスロー。

    • これは、スクロールが完了した/完了すると、アイテムのスクロール中ではなく、ビューが更新されるだけです。
  3. 最後のオプションはデフォルトLayoutManagerを延長する独自のカスタムLayoutManagerを実施している残りました。

    • 私が知る限り、カスタムLayoutmanagerの実装には、処理する必要があるさらに複雑な計算が含まれます。

任意の他のソリューションやアイデアが理解されるであろう。

答えて

24

私はthis answer on SOを見つけました。これはまったく同じことを水平に行いました。回答は、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; 
     } 

    } 
} 

enter image description here

垂直配向した:

enter image description here

+0

あなたはそれが周期的にするためにどのように、知っています?私は10の項目でhorizo​​ntal recyclerviewを持っています。私はそれを無限にスクロールしたい。つまり、すべての項目の完了後に位置1が再度表示されます。 –

+0

@RonakThakkar私はこれのようなトリックが動作すると思う:https://stackoverflow.com/a/45114415/3830694 –

関連する問題