1a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte/*
2a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * Copyright (C) 2017 The Android Open Source Project
3a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte *
4a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * Licensed under the Apache License, Version 2.0 (the "License");
5a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * you may not use this file except in compliance with the License.
6a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * You may obtain a copy of the License at
7a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte *
8a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte *      http://www.apache.org/licenses/LICENSE-2.0
9a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte *
10a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * Unless required by applicable law or agreed to in writing, software
11a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * distributed under the License is distributed on an "AS IS" BASIS,
12a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * See the License for the specific language governing permissions and
14a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte * limitations under the License.
15a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte */
16a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
17a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whytepackage android.support.v7.widget;
18a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
19a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport static org.junit.Assert.assertEquals;
20a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport static org.junit.Assert.assertNotEquals;
21a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
22a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.content.Context;
23a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.test.InstrumentationRegistry;
24a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.test.filters.SmallTest;
25a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.test.runner.AndroidJUnit4;
26a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.v4.view.InputDeviceCompat;
27a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.v4.view.MotionEventCompat;
28a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.v4.view.ViewConfigurationCompat;
29a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.view.MotionEvent;
30a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.view.View;
31a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.view.ViewConfiguration;
32a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.view.ViewGroup;
33a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.widget.TextView;
34a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
35a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport org.junit.Before;
36a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport org.junit.Test;
37a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport org.junit.runner.RunWith;
38a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
39a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte@SmallTest
40a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte@RunWith(AndroidJUnit4.class)
41a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whytepublic class RecyclerViewOnGenericMotionEventTest {
42a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
43a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    TestRecyclerView mRecyclerView;
44a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
45a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    @Before
46a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public void setUp() throws Exception {
47a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView = new TestRecyclerView(getContext());
48a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
49a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
50a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private Context getContext() {
51a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        return InstrumentationRegistry.getContext();
52a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
53a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
54a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private void layout() {
55a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.layout(0, 0, 320, 320);
56a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
57a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
58a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    @Test
59a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public void rotaryEncoderVerticalScroll() {
60a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MockLayoutManager layoutManager = new MockLayoutManager(true, true);
61a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.setLayoutManager(layoutManager);
62a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        layout();
63a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MotionEvent e = obtainScrollMotionEvent(
64a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                MotionEventCompat.AXIS_SCROLL, 2, InputDeviceCompat.SOURCE_ROTARY_ENCODER);
65a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.onGenericMotionEvent(e);
66a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertTotalScroll(0, (int) (-2f * getScaledVerticalScrollFactor()));
67a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
68a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
69a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    @Test
70a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public void rotaryEncoderHorizontalScroll() {
71a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        // The encoder is one-dimensional, and can only scroll horizontally if vertical scrolling
72a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        // is not enabled.
73a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MockLayoutManager layoutManager = new MockLayoutManager(true, false);
74a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.setLayoutManager(layoutManager);
75a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        layout();
76a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MotionEvent e = obtainScrollMotionEvent(
77a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                MotionEventCompat.AXIS_SCROLL, 2, InputDeviceCompat.SOURCE_ROTARY_ENCODER);
78a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.onGenericMotionEvent(e);
79a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertTotalScroll((int) (2f * getScaledHorizontalScrollFactor()), 0);
80a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
81a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
82a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    @Test
83a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public void pointerVerticalScroll() {
84a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MockLayoutManager layoutManager = new MockLayoutManager(true, true);
85a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.setLayoutManager(layoutManager);
86a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        layout();
87a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MotionEvent e = obtainScrollMotionEvent(
88a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                MotionEventCompat.AXIS_VSCROLL, 2, InputDeviceCompat.SOURCE_CLASS_POINTER);
89a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.onGenericMotionEvent(e);
90a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertTotalScroll(0, (int) (-2f * getScaledVerticalScrollFactor()));
91a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
92a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
93a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    @Test
94a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public void pointerHorizontalScroll() {
95a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MockLayoutManager layoutManager = new MockLayoutManager(true, true);
96a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.setLayoutManager(layoutManager);
97a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        layout();
98a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MotionEvent e = obtainScrollMotionEvent(
99a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                MotionEventCompat.AXIS_HSCROLL, 2, InputDeviceCompat.SOURCE_CLASS_POINTER);
100a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        mRecyclerView.onGenericMotionEvent(e);
101a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertTotalScroll((int) (2f * getScaledHorizontalScrollFactor()), 0);
102a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
103a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
104a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    @Test
105a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public void nonZeroScaledVerticalScrollFactor() {
106a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertNotEquals(0, getScaledVerticalScrollFactor());
107a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
108a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
109a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    @Test
110a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public void nonZeroScaledHorizontalScrollFactor() {
111a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertNotEquals(0, getScaledHorizontalScrollFactor());
112a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
113a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
114a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private void assertTotalScroll(int x, int y) {
115a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertEquals("x total scroll", x, mRecyclerView.mTotalX);
116a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        assertEquals("y total scroll", y, mRecyclerView.mTotalY);
117a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
118a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
119a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private static MotionEvent obtainScrollMotionEvent(int axis, int axisValue, int inputDevice) {
120a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MotionEvent.PointerProperties[] pointerProperties = { new MotionEvent.PointerProperties() };
121a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
122a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        coords.setAxisValue(axis, axisValue);
123a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MotionEvent.PointerCoords[] pointerCoords = { coords };
124a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        float xPrecision = 1;
125a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        float yPrecision = 1;
126a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        int deviceId = 0;
127a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        int edgeFlags = 0;
128a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        int flags = 0;
129a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        return MotionEvent.obtain(0, System.currentTimeMillis(), MotionEvent.ACTION_SCROLL,
130a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                1, pointerProperties, pointerCoords, 0, 0, xPrecision, yPrecision, deviceId,
131a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                edgeFlags, inputDevice, flags);
132a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
133a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
134a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private float getScaledVerticalScrollFactor() {
135a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        return ViewConfigurationCompat.getScaledVerticalScrollFactor(
136a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                ViewConfiguration.get(getContext()), getContext());
137a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
138a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
139a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private float getScaledHorizontalScrollFactor() {
140a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        return ViewConfigurationCompat.getScaledHorizontalScrollFactor(
141a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                ViewConfiguration.get(getContext()), getContext());
142a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
143a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
144a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    static class MockLayoutManager extends RecyclerView.LayoutManager {
145a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
146a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        private final boolean mCanScrollHorizontally;
147a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
148a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        private final boolean mCanScrollVertically;
149a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
150a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MockLayoutManager(boolean canScrollHorizontally, boolean canScrollVertically) {
151a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            mCanScrollHorizontally = canScrollHorizontally;
152a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            mCanScrollVertically = canScrollVertically;
153a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
154a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
155a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
156a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public RecyclerView.LayoutParams generateDefaultLayoutParams() {
157a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
158a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                    ViewGroup.LayoutParams.WRAP_CONTENT);
159a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
160a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
161a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
162a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
163a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                RecyclerView.State state) {
164a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return dx;
165a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
166a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
167a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
168a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
169a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                RecyclerView.State state) {
170a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return dy;
171a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
172a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
173a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
174a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public boolean canScrollHorizontally() {
175a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return mCanScrollHorizontally;
176a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
177a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
178a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
179a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public boolean canScrollVertically() {
180a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return mCanScrollVertically;
181a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
182a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
183a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
184a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    static class MockAdapter extends RecyclerView.Adapter {
185a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
186a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        private int mCount = 0;
187a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
188a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MockAdapter(int count) {
189a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            this.mCount = count;
190a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
191a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
192a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
193a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
194a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return new MockViewHolder(new TextView(parent.getContext()));
195a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
196a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
197a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
198a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
199a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
200a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
201a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
202a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        @Override
203a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        public int getItemCount() {
204a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return mCount;
205a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
206a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
207a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
208a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    static class MockViewHolder extends RecyclerView.ViewHolder {
209a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        MockViewHolder(View itemView) {
210a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            super(itemView);
211a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
212a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
213a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
214a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private static class TestRecyclerView extends RecyclerView {
215a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        int mTotalX = 0;
216a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        int mTotalY = 0;
217a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
218a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        TestRecyclerView(Context context) {
219a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            super(context);
220a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
221a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
222a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        boolean scrollByInternal(int x, int y, MotionEvent ev) {
223a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            mTotalX += x;
224a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            mTotalY += y;
225a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return super.scrollByInternal(x, y, ev);
226a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
227a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
228a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte}
229