PagerSnapHelper.java revision 849542dfdc5e83411c8b959251eb6f2a1556fc9d
1849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas/*
2849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * Copyright (C) 2016 The Android Open Source Project
3849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas *
4849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * Licensed under the Apache License, Version 2.0 (the "License");
5849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * you may not use this file except in compliance with the License.
6849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * You may obtain a copy of the License at
7849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas *
8849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas *      http://www.apache.org/licenses/LICENSE-2.0
9849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas *
10849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * Unless required by applicable law or agreed to in writing, software
11849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * distributed under the License is distributed on an "AS IS" BASIS,
12849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * See the License for the specific language governing permissions and
14849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * limitations under the License.
15849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas */
16849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
17849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikaspackage android.support.v7.widget;
18849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
19849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikasimport android.graphics.PointF;
20849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikasimport android.support.annotation.NonNull;
21849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikasimport android.support.annotation.Nullable;
22849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikasimport android.view.View;
23849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
24849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas/**
25849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * Implementation of the {@link SnapHelper} supporting pager style snapping in either vertical or
26849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas * horizontal orientation.
27849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas */
28849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikaspublic class PagerSnapHelper extends SnapHelper {
29849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    // Orientation helpers are lazily created per LayoutManager.
30849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Nullable
31849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    private OrientationHelper mVerticalHelper;
32849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Nullable
33849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    private OrientationHelper mHorizontalHelper;
34849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
35849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Nullable
36849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Override
37849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,
38849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            @NonNull View targetView) {
39849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        int[] out = new int[2];
40849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (layoutManager.canScrollHorizontally()) {
41849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            out[0] = distanceToCenter(layoutManager, targetView,
42849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                    getHorizontalHelper(layoutManager));
43849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        } else {
44849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            out[0] = 0;
45849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
46849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
47849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (layoutManager.canScrollVertically()) {
48849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            out[1] = distanceToCenter(layoutManager, targetView,
49849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                    getVerticalHelper(layoutManager));
50849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        } else {
51849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            out[1] = 0;
52849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
53849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return out;
54849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
55849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
56849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Nullable
57849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Override
58849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
59849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (layoutManager.canScrollVertically()) {
60849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            return findCenterView(layoutManager, getVerticalHelper(layoutManager));
61849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        } else if (layoutManager.canScrollHorizontally()) {
62849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            return findCenterView(layoutManager, getHorizontalHelper(layoutManager));
63849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
64849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return null;
65849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
66849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
67849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Override
68849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX,
69849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            int velocityY) {
70849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        final int itemCount = layoutManager.getItemCount();
71849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (itemCount == 0) {
72849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            return RecyclerView.NO_POSITION;
73849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
74849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
75849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        View mStartMostChildView = null;
76849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (layoutManager.canScrollVertically()) {
77849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            mStartMostChildView = findStartView(layoutManager, getVerticalHelper(layoutManager));
78849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        } else if (layoutManager.canScrollHorizontally()) {
79849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            mStartMostChildView = findStartView(layoutManager, getHorizontalHelper(layoutManager));
80849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
81849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
82849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (mStartMostChildView == null) {
83849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            return RecyclerView.NO_POSITION;
84849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
85849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        final int centerPosition = layoutManager.getPosition(mStartMostChildView);
86849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (centerPosition == RecyclerView.NO_POSITION) {
87849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            return RecyclerView.NO_POSITION;
88849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
89849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
90849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        final boolean forwardDirection;
91849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (layoutManager.canScrollHorizontally()) {
92849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            forwardDirection = velocityX > 0;
93849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        } else {
94849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            forwardDirection = velocityY > 0;
95849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
96849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        boolean reverseLayout = false;
97849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if ((layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
98849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            RecyclerView.SmoothScroller.ScrollVectorProvider vectorProvider =
99849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                    (RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager;
100849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            PointF vectorForEnd = vectorProvider.computeScrollVectorForPosition(itemCount - 1);
101849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            if (vectorForEnd != null) {
102849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                reverseLayout = vectorForEnd.x < 0 || vectorForEnd.y < 0;
103849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            }
104849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
105849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return reverseLayout
106849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                ? (forwardDirection ? centerPosition - 1 : centerPosition)
107849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                : (forwardDirection ? centerPosition + 1 : centerPosition);
108849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
109849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
110849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    private int distanceToCenter(@NonNull RecyclerView.LayoutManager layoutManager,
111849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            @NonNull View targetView, OrientationHelper helper) {
112849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        final int childCenter = helper.getDecoratedStart(targetView)
113849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                + (helper.getDecoratedMeasurement(targetView) / 2);
114849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        final int containerCenter;
115849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (layoutManager.getClipToPadding()) {
116849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            containerCenter = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;
117849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        } else {
118849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            containerCenter = helper.getEnd() / 2;
119849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
120849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return childCenter - containerCenter;
121849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
122849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
123849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    /**
124849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * Return the child view that is currently closest to the center of this parent.
125849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     *
126849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * @param layoutManager The {@link RecyclerView.LayoutManager} associated with the attached
127849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     *                      {@link RecyclerView}.
128849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * @param helper The relevant {@link OrientationHelper} for the attached {@link RecyclerView}.
129849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     *
130849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * @return the child view that is currently closest to the center of this parent.
131849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     */
132849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Nullable
133849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    private View findCenterView(RecyclerView.LayoutManager layoutManager,
134849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            OrientationHelper helper) {
135849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        int childCount = layoutManager.getChildCount();
136849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (childCount == 0) {
137849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            return null;
138849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
139849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
140849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        View closestChild = null;
141849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        final int center;
142849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (layoutManager.getClipToPadding()) {
143849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            center = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;
144849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        } else {
145849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            center = helper.getEnd() / 2;
146849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
147849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        int absClosest = Integer.MAX_VALUE;
148849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
149849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        for (int i = 0; i < childCount; i++) {
150849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            final View child = layoutManager.getChildAt(i);
151849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            int childCenter = helper.getDecoratedStart(child)
152849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                    + (helper.getDecoratedMeasurement(child) / 2);
153849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            int absDistance = Math.abs(childCenter - center);
154849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
155849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            /** if child center is closer than previous closest, set it as closest  **/
156849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            if (absDistance < absClosest) {
157849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                absClosest = absDistance;
158849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                closestChild = child;
159849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            }
160849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
161849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return closestChild;
162849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
163849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
164849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    /**
165849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * Return the child view that is currently closest to the start of this parent.
166849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     *
167849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * @param layoutManager The {@link RecyclerView.LayoutManager} associated with the attached
168849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     *                      {@link RecyclerView}.
169849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * @param helper The relevant {@link OrientationHelper} for the attached {@link RecyclerView}.
170849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     *
171849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     * @return the child view that is currently closest to the start of this parent.
172849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas     */
173849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @Nullable
174849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    private View findStartView(RecyclerView.LayoutManager layoutManager,
175849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            OrientationHelper helper) {
176849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        int childCount = layoutManager.getChildCount();
177849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (childCount == 0) {
178849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            return null;
179849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
180849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
181849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        View closestChild = null;
182849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        int startest = Integer.MAX_VALUE;
183849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
184849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        for (int i = 0; i < childCount; i++) {
185849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            final View child = layoutManager.getChildAt(i);
186849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            int childStart = helper.getDecoratedStart(child);
187849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
188849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            /** if child is more to start than previous closest, set it as closest  **/
189849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            if (childStart < startest) {
190849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                startest = childStart;
191849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas                closestChild = child;
192849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            }
193849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
194849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return closestChild;
195849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
196849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
197849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @NonNull
198849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    private OrientationHelper getVerticalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
199849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (mVerticalHelper == null || mVerticalHelper.mLayoutManager != layoutManager) {
200849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
201849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
202849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return mVerticalHelper;
203849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
204849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas
205849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    @NonNull
206849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    private OrientationHelper getHorizontalHelper(
207849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            @NonNull RecyclerView.LayoutManager layoutManager) {
208849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        if (mHorizontalHelper == null || mHorizontalHelper.mLayoutManager != layoutManager) {
209849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
210849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        }
211849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas        return mHorizontalHelper;
212849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas    }
213849542dfdc5e83411c8b959251eb6f2a1556fc9dAurimas Liutikas}
214