SnapHelper

4121 ワード

一、SnapHelperを理解する
実はSnapHelperはRecyclerViewの開拓です.
SnapHelperの実現原理はRecyclerViewを傍受することである.OnFlingListenerのonFlingインタフェース.LinearSnapHelperは抽象クラスSnapHelperの具体的な実装である.
LinearSnapHelperにより、RecyclerViewは、どのようにスライドしても最終的にページの真ん中に留まるようなViewPagerのような機能を実現することができます.
二、効果を実現する
1.LinearSnapHelperを持参して実現
ページを自動的に中央に配置できます.
LinearSnapHelper  mLinearSnapHelper=new LinearSnapHelper();

mLinearSnapHelper.attachToRecyclerView(mRecyclerView);

2.カスタムSnapHelper実装
たとえば、左揃えです.
SnapHelperは抽象クラスであり、実装する必要がある3つの方法を直接継承します.
  • このメソッドは、ドラッグまたはスライドが終了するとコールバックされ、out=int[2]、out[0]x軸、out[1]y軸を返します.この値は、修正が必要な位置のオフセット量
  • です.
    public abstract int[] calculateDistanceToFinalSnap(@NonNull LayoutManager layoutManager, @NonNull View targetView);
    
  • 上の方法にはtargetViewがあるでしょう.この方法で返される
  • です.
    public abstract View findSnapView(LayoutManager layoutManager);
    
  • Flingに使用され、速度に応じてスライドするposition
  • を返します.
    public abstract int findTargetSnapPosition(LayoutManager layoutManager, int velocityX, int velocityY);
    

    SnapHelperを直接継承するのではなく、彼の実装クラスLinearsnapHelperを継承します.
    
    public  class  MySnapHelper  extends  LinearSnapHelper   {
    
      privateOrientationHelper mHorizontalHelper;
    
      @Nullable
    
      @Override
    
      public  int[]  calculateDistanceToFinalSnap (RecyclerView.LayoutManager layoutManager, View targetView) {
    
        int[] out =newint[2];
    
        if(layoutManager.canScrollHorizontally()) {
    
          out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
    
        }else{
    
          out[0] =0;
    
        }return out;
    
      }
    
      private  int  distanceToStart(View targetView, OrientationHelper helper) {
    
        return  helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
    
      }
    
      @Nullable
    
      @Override  public  View  findSnapView(RecyclerView.LayoutManager layoutManager) {
    
        return   findStartView(layoutManager, getHorizontalHelper(layoutManager));
    
      }
    
      private  View  findStartView(RecyclerView.LayoutManager layoutManager,OrientationHelper helper) {
    
        if(layoutManagerinstanceofLinearLayoutManager) {
    
          intfirstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
    
          intlastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
    
          if(firstChild == RecyclerView.NO_POSITION) {
    
            return  null;
    
          }  if(lastChild == layoutManager.getItemCount() -1) {
    
                return  layoutManager.findViewByPosition(lastChild);
    
             }
    
         View child = layoutManager.findViewByPosition(firstChild);
    
         if(helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) /2&& helper.getDecoratedEnd(child) >0) {
    
            return  child;
    
          }  else{
    
              return  layoutManager.findViewByPosition(firstChild +1);
    
          }
    
        }
         return  super.findSnapView(layoutManager);
    
      }
    
      private   OrientationHelpergetHorizontalHelper(
    
      @NonNull
    
      RecyclerView.LayoutManager layoutManager) {
    
        if(mHorizontalHelper ==null) {
    
          mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
    
        }  return  mHorizontalHelper;
    
      }
    
    }
    

    ここではいくつか注意すべき点がありますが、
    11~24行目:横方向左揃えのみを考慮するのでout[0]の値を処理すればdistanceToStart()メソッドは修正されたオフセット量を返す.
    41~43行目:最後のページをめくったときに最後のItemが完全に表示されない問題を解決するためです(信じないで、注釈してみてください).
    if(lastChild == layoutManager.getItemCount() -1) {
      returnlayoutManager.findViewByPosition(lastChild);           
    }
    

    第47~52行:このとき左揃え表示が必要な項目を得る
    if(helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) /2
        && helper.getDecoratedEnd(child) >0) {              
          return  child;
    }  else{
        return  la youtManager.findViewByPosition(firstChild +1);
    }
    

    最後に私たち自身のSnapHelperを使えば、簡単にできます.
    MySnapHelper mMySnapHelper=new MySnapHelper();
    
    mMySnapHelper.attachToRecyclerView(mRecyclerView);
    
    

    実装済みライブラリ:https://github.com/rubensousa/RecyclerViewSnap
    参考記事:http://blog.csdn.net/whitley_gong/article/details/52421215