Android Studio第十八期 - Snaphelper

临文乍了了,彻卷兀若无。这篇文章主要讲述Android Studio第十八期 - Snaphelper相关的知识,希望能为你提供帮助。
        代码已经整理好,效果如下图:

        GravitySnapHelper:

/*   *  Copyright  (C)  2016  The  android  Open  Source  Project   *  Copyright  (C)  2016  Rúben  Sousa   *   *  Licensed  under  the  Apache  License,  Version  2.0  (the  "License");   *  you  may  not  use  this  file  except  in  compliance  with  the  License.   *  You  may  obtain  a  copy  of  the  License  at   *   *            http://www.apache.org/licenses/LICENSE-2.0   *   *  Unless  required  by  applicable  law  or  agreed  to  in  writing,  software   *  distributed  under  the  License  is  distributed  on  an  "AS  IS"  BASIS,   *  WITHOUT  WARRANTIES  OR  CONDITIONS  OF  ANY  KIND,  either  express  or  implied.   *  See  the  License  for  the  specific  languag`e  governing  permissions  and   *  limitations  under  the  License.   */package  com.haiersmart.sfnation.widget; import  android.support.annotation.NonNull; import  android.support.annotation.Nullable; import  android.support.v7.widget.LinearLayoutManager; import  android.support.v7.widget.LinearSnapHelper; import  android.support.v7.widget.OrientationHelper; import  android.support.v7.widget.RecyclerView; import  android.view.Gravity; import  android.view.View; import  com.haiersmart.sfnation.R; public  class  GravitySnapHelper  extends  LinearSnapHelper  {        private  OrientationHelper  mVerticalHelper;         private  OrientationHelper  mHorizontalHelper;         private  int  mGravity;         private  boolean  mIsRtlHorizontal;         private  boolean  mSnapLastItemEnabled;         SnapListener  mSnapListener;         boolean  mSnapping;         private  RecyclerView.OnScrollListener  mScrollListener  =  new  RecyclerView.OnScrollListener()  {                 @Override                 public  void  onScrollStateChanged(RecyclerView  recyclerView,  int  newState)  {                         super.onScrollStateChanged(recyclerView,  newState);                         if  (newState  ==  RecyclerView.SCROLL_STATE_SETTLING)  {                                 mSnapping  =  false;                         }                         if  (newState  ==  RecyclerView.SCROLL_STATE_IDLE  & &   mSnapping  & &   mSnapListener  !=  null)  {                                 int  position  =  getSnappedPosition(recyclerView);                                 if  (position  !=  RecyclerView.NO_POSITION)  {                                         mSnapListener.onSnap(position);                                 }                                 mSnapping  =  false;                         }                 }         };         public  GravitySnapHelper(int  gravity)  {                 this(gravity,  false,  null);         }        public  GravitySnapHelper(int  gravity,  boolean  enableSnapLastItem)  {                 this(gravity,  enableSnapLastItem,  null);         }        public  GravitySnapHelper(int  gravity,  boolean  enableSnapLastItem,  SnapListener  snapListener)  {                 if  (gravity  !=  Gravity.START  & &   gravity  !=  Gravity.END                                 & &   gravity  !=  Gravity.BOTTOM  & &   gravity  !=  Gravity.TOP)  {                         throw  new  IllegalArgumentException("Invalid  gravity  value.  Use  START  "  +                                         "|  END  |  BOTTOM  |  TOP  constants");                 }                 mSnapListener  =  snapListener;                 mGravity  =  gravity;                 mSnapLastItemEnabled  =  enableSnapLastItem;         }        @Override         public  void  attachToRecyclerView(@Nullable  RecyclerView  recyclerView)                         throws  IllegalStateException  {                 if  (recyclerView  !=  null)  {                         if  (mGravity  ==  Gravity.START  ||  mGravity  ==  Gravity.END)  {                                 mIsRtlHorizontal                                                 =  recyclerView.getContext().getResources().getBoolean(R.bool.is_rtl);                         }                         if  (mSnapListener  !=  null)  {                                 recyclerView.addOnScrollListener(mScrollListener);                         }                 }                 super.attachToRecyclerView(recyclerView);         }        @Override         public  int[]  calculateDistanceToFinalSnap(@NonNull  RecyclerView.LayoutManager  layoutManager,                                                                                             @NonNull  View  targetView)  {                 int[]  out  =  new  int[2];                 if  (layoutManager.canScrollHorizontally())  {                         if  (mGravity  ==  Gravity.START)  {                                 out[0]  =  distanceToStart(targetView,  getHorizontalHelper(layoutManager),  false);                         }  else  {  //  END                                 out[0]  =  distanceToEnd(targetView,  getHorizontalHelper(layoutManager),  false);                         }                 }  else  {                         out[0]  =  0;                 }                if  (layoutManager.canScrollVertically())  {                         if  (mGravity  ==  Gravity.TOP)  {                                 out[1]  =  distanceToStart(targetView,  getVerticalHelper(layoutManager),  false);                         }  else  {  //  BOTTOM                                 out[1]  =  distanceToEnd(targetView,  getVerticalHelper(layoutManager),  false);                         }                 }  else  {                         out[1]  =  0;                 }                return  out;         }        @Override         public  View  findSnapView(RecyclerView.LayoutManager  layoutManager)  {                 View  snapView  =  null;                 if  (layoutManager  instanceof  LinearLayoutManager)  {                         switch  (mGravity)  {                                 case  Gravity.START:                                         snapView  =  findStartView(layoutManager,  getHorizontalHelper(layoutManager));                                         break;                                 case  Gravity.END:                                         snapView  =  findEndView(layoutManager,  getHorizontalHelper(layoutManager));                                         break;                                 case  Gravity.TOP:                                         snapView  =  findStartView(layoutManager,  getVerticalHelper(layoutManager));                                         break;                                 case  Gravity.BOTTOM:                                         snapView  =  findEndView(layoutManager,  getVerticalHelper(layoutManager));                                         break;                         }                 }                mSnapping  =  snapView  !=  null;                 return  snapView;         }        /**           *  Enable  snapping  of  the  last  item  that‘s  snappable.           *  The  default  value  is  false,  because  you  can‘t  see  the  last  item  completely           *  if  this  is  enabled.           *           *  @param  snap  true  if  you  want  to  enable  snapping  of  the  last  snappable  item           */         public  void  enableLastItemSnap(boolean  snap)  {                 mSnapLastItemEnabled  =  snap;         }        private  int  distanceToStart(View  targetView,  OrientationHelper  helper,  boolean  fromEnd)  {                 if  (mIsRtlHorizontal  & &   !fromEnd)  {                         return  distanceToEnd(targetView,  helper,  true);                 }                return  helper.getDecoratedStart(targetView)  -  helper.getStartAfterPadding();         }        private  int  distanceToEnd(View  targetView,  OrientationHelper  helper,  boolean  fromStart)  {                 if  (mIsRtlHorizontal  & &   !fromStart)  {                         return  distanceToStart(targetView,  helper,  true);                 }                return  helper.getDecoratedEnd(targetView)  -  helper.getEndAfterPadding();         }        /**           *  Returns  the  first  view  that  we  should  snap  to.           *           *  @param  layoutManager  the  recyclerview‘s  layout  manager           *  @param  helper                orientation  helper  to  calculate  view  sizes           *  @return  the  first  view  in  the  LayoutManager  to  snap  to           */         private  View  findStartView(RecyclerView.LayoutManager  layoutManager,                                                               OrientationHelper  helper)  {                if  (layoutManager  instanceof  LinearLayoutManager)  {                         int  firstChild  =  ((LinearLayoutManager)  layoutManager).findFirstVisibleItemPosition();                         if  (firstChild  ==  RecyclerView.NO_POSITION)  {                                 return  null;                         }                        View  child  =  layoutManager.findViewByPosition(firstChild);                         float  visibleWidth;                         //  We  should  return  the  child  if  it‘s  visible  width                         //  is  greater  than  0.5  of  it‘s  total  width.                         //  In  a  RTL  configuration,  we  need  to  check  the  start  point  and  in  LTR  the  end  point                         if  (mIsRtlHorizontal)  {                                 visibleWidth  =  (float)  (helper.getTotalSpace()  -  helper.getDecoratedStart(child))                                                 /  helper.getDecoratedMeasurement(child);                         }  else  {                                 visibleWidth  =  (float)  helper.getDecoratedEnd(child)                                                 /  helper.getDecoratedMeasurement(child);                         }                        //  If  we‘re  at  the  end  of  the  list,  we  shouldn‘t  snap                         //  to  avoid  having  the  last  item  not  completely  visible.                         boolean  endOfList  =  ((LinearLayoutManager)  layoutManager)                                         .findLastCompletelyVisibleItemPosition()                                         ==  layoutManager.getItemCount()  -  1;                         if  (visibleWidth  >   0.5f  & &   !endOfList)  {                                 return  child;                         }  else  if  (mSnapLastItemEnabled  & &   endOfList)  {                                 return  child;                         }  else  if  (endOfList)  {                                 return  null;                         }  else  {                                 //  If  the  child  wasn‘t  returned,  we  need  to  return                                 //  the  next  view  close  to  the  start.                                 return  layoutManager.findViewByPosition(firstChild  +  1);                         }                 }                return  null;         }        private  View  findEndView(RecyclerView.LayoutManager  layoutManager,                                                           OrientationHelper  helper)  {                if  (layoutManager  instanceof  LinearLayoutManager)  {                         int  lastChild  =  ((LinearLayoutManager)  layoutManager).findLastVisibleItemPosition();                         if  (lastChild  ==  RecyclerView.NO_POSITION)  {                                 return  null;                         }                        View  child  =  layoutManager.findViewByPosition(lastChild);                         float  visibleWidth;                         if  (mIsRtlHorizontal)  {                                 visibleWidth  =  (float)  helper.getDecoratedEnd(child)                                                 /  helper.getDecoratedMeasurement(child);                         }  else  {                                 visibleWidth  =  (float)  (helper.getTotalSpace()  -  helper.getDecoratedStart(child))                                                 /  helper.getDecoratedMeasurement(child);                         }                        //  If  we‘re  at  the  start  of  the  list,  we  shouldn‘t  snap                         //  to  avoid  having  the  first  item  not  completely  visible.                         boolean  startOfList  =  ((LinearLayoutManager)  layoutManager)                                         .findFirstCompletelyVisibleItemPosition()  ==  0;                         if  (visibleWidth  >   0.5f  & &   !startOfList)  {                                 return  child;                         }  else  if  (mSnapLastItemEnabled  & &   startOfList)  {                                 return  child;                         }  else  if  (startOfList)  {                                 return  null;                         }  else  {                                 //  If  the  child  wasn‘t  returned,  we  need  to  return  the  previous  view                                 return  layoutManager.findViewByPosition(lastChild  -  1);                         }                 }                 return  null;         }        int  getSnappedPosition(RecyclerView  recyclerView)  {                 RecyclerView.LayoutManager  layoutManager  =  recyclerView.getLayoutManager();                 if  (layoutManager  instanceof  LinearLayoutManager)  {                         if  (mGravity  ==  Gravity.START  ||  mGravity  ==  Gravity.TOP)  {                                 return  ((LinearLayoutManager)  layoutManager).findFirstCompletelyVisibleItemPosition();                         }  else  if  (mGravity  ==  Gravity.END  ||  mGravity  ==  Gravity.BOTTOM)  {                                 return  ((LinearLayoutManager)  layoutManager).findLastCompletelyVisibleItemPosition();                         }                 }                return  RecyclerView.NO_POSITION;         }        private  OrientationHelper  getVerticalHelper(RecyclerView.LayoutManager  layoutManager)  {                 if  (mVerticalHelper  ==  null)  {                         mVerticalHelper  =  OrientationHelper.createVerticalHelper(layoutManager);                 }                 return  mVerticalHelper;         }        private  OrientationHelper  getHorizontalHelper(RecyclerView.LayoutManager  layoutManager)  {                 if  (mHorizontalHelper  ==  null)  {                         mHorizontalHelper  =  OrientationHelper.createHorizontalHelper(layoutManager);                 }                 return  mHorizontalHelper;         }        public  interface  SnapListener  {                 void  onSnap(int  position);         }}

    build.gradle
compile  ‘com.android.support:design:25.0.0‘ compile  ‘com.android.support:appcompat-v7:25.0.0‘ compile  ‘com.android.support:recyclerview-v7:25.0.0‘ compile  ‘com.android.support:cardview-v7:25.0.0‘

        方法调用:
recycler_view1.setLayoutManager(new  LinearLayoutManager(getActivity(),  LinearLayoutManager.VERTICAL,  false)); SnapHelper  snapHelperStart  =  new  GravitySnapHelper(Gravity.TOP); snapHelperStart.attachToRecyclerView(recycler_view1);

       
Android Studio第十八期 - Snaphelper

文章图片

        地址:
https://github.com/geeklx/MyApplication/tree/master/p015_recycleview_gundong_vertical


【Android Studio第十八期 - Snaphelper】本文出自 “梁肖技术中心” 博客,请务必保留此出处http://liangxiao.blog.51cto.com/3626612/1871713

    推荐阅读