Search code examples
android-recyclerviewxamarin.androidpagersnaphelper

How to move the snap position from center to left of RecycleView using SnapHelper?


I have an RecycleView that contains ImageViews and my question is how can i move the snap to be on the left side of the RecycleView instead of the center?

When i move the ImageViews they get snapped in the center and I can move them to the left or right inside that "snap window" by overriding the CalculateDistanceToFinalSnap method. I think I would now need to move that "snap window" to the left side of the RecycleView but I don't know how, or maybe there is another way, please help.

Here is a image of my problem, maybe it will help you to understand more clearly: image


Solution

  • I have achieved this function ,we juse need to create a class and extent class LinearSnapHelper and override method CalculateDistanceToFinalSnap and FindSnapView. You can check out the full demo here .

    The main code is as follows:

     public class StartSnapHelper: LinearSnapHelper
     {
        private OrientationHelper mVerticalHelper, mHorizontalHelper;
    
        public StartSnapHelper()
        {
        }
    
        public override void AttachToRecyclerView(RecyclerView recyclerView)
        {
            base.AttachToRecyclerView(recyclerView);
        }
    
        public override int[] CalculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView)
        {
            //return base.CalculateDistanceToFinalSnap(layoutManager, targetView);
            int[] outer = new int[2];
    
            if (layoutManager.CanScrollHorizontally())
            {
                outer[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
            } else {
                outer[0] = 0;
            }
    
        if (layoutManager.CanScrollVertically()) {
                outer[1] = distanceToStart(targetView, getVerticalHelper(layoutManager));
        } else {
                outer[1] = 0;
        }
        return outer;
        }
    
        private int distanceToStart(View targetView, OrientationHelper helper)
        {
            return helper.GetDecoratedStart(targetView) - helper.StartAfterPadding;
        }
    
        public override View FindSnapView(RecyclerView.LayoutManager layoutManager)
        {
            if (layoutManager is LinearLayoutManager) {
    
                if (layoutManager.CanScrollHorizontally())
                {
                    return getStartView(layoutManager, getHorizontalHelper(layoutManager));
                }
                else
                {
                    return getStartView(layoutManager, getVerticalHelper(layoutManager));
                }
            }
    
            return base.FindSnapView(layoutManager);
        }
    
        private View getStartView(RecyclerView.LayoutManager layoutManager,
                              OrientationHelper helper)
        {
    
            if (layoutManager is LinearLayoutManager) {
                int firstChild = ((LinearLayoutManager)layoutManager).FindFirstVisibleItemPosition();
    
                bool isLastItem = ((LinearLayoutManager)layoutManager)
                        .FindLastCompletelyVisibleItemPosition()
                        == layoutManager.ItemCount - 1;
    
                if (firstChild == RecyclerView.NoPosition || isLastItem)
                {
                    return null;
                }
    
                View child = layoutManager.FindViewByPosition(firstChild);
    
                if (helper.GetDecoratedEnd(child) >= helper.GetDecoratedMeasurement(child) / 2
                        && helper.GetDecoratedEnd(child) > 0)
                {
                    return child;
                }
                else
                {
                    if (((LinearLayoutManager)layoutManager).FindLastCompletelyVisibleItemPosition()
                            == layoutManager.ItemCount - 1)
                    {
                        return null;
                    }
                    else
                    {
                        return layoutManager.FindViewByPosition(firstChild + 1);
                    }
                }
            }
            return base.FindSnapView(layoutManager);
        }
    
    
        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;
        }
    }
    

    And use like this:

      SnapHelper snapHelperStart = new StartSnapHelper();
      snapHelperStart.AttachToRecyclerView(recyclerView);