1a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar/* 2a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * Copyright (C) 2014 The Android Open Source Project 3a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * 4a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * you may not use this file except in compliance with the License. 6a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * You may obtain a copy of the License at 7a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * 8a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * 10a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * Unless required by applicable law or agreed to in writing, software 11a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * See the License for the specific language governing permissions and 14a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * limitations under the License. 15a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar */ 16a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 17a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarpackage android.support.v7.widget; 18a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.Test; 200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.runner.RunWith; 210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.runners.Parameterized; 220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 23a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.AccessibilityDelegateCompat; 24a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.accessibility.AccessibilityEventCompat; 25a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 26a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.accessibility.AccessibilityRecordCompat; 27f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyarimport android.test.suitebuilder.annotation.MediumTest; 28a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.view.View; 29a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.view.accessibility.AccessibilityEvent; 30a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 310a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.ArrayList; 320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.Arrays; 330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.List; 34a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport java.util.concurrent.atomic.AtomicBoolean; 35a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 360a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertEquals; 370a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertFalse; 380a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertNotNull; 390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertTrue; 400a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 41f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyar@MediumTest 420a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar@RunWith(Parameterized.class) 43a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarpublic class RecyclerViewAccessibilityTest extends BaseRecyclerViewInstrumentationTest { 44da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar 450a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar final boolean verticalScrollBefore, horizontalScrollBefore, verticalScrollAfter, 460a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar horizontalScrollAfter; 470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public RecyclerViewAccessibilityTest(boolean verticalScrollBefore, 490a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar boolean horizontalScrollBefore, boolean verticalScrollAfter, 500a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar boolean horizontalScrollAfter) { 510a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.verticalScrollBefore = verticalScrollBefore; 520a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.horizontalScrollBefore = horizontalScrollBefore; 530a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.verticalScrollAfter = verticalScrollAfter; 540a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.horizontalScrollAfter = horizontalScrollAfter; 55da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar } 56da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar 570a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Parameterized.Parameters(name = "vBefore={0} vAfter={1} hBefore={2} hAfter={3}") 580a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public static List<Object[]> getParams() { 590a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar List<Object[]> params = new ArrayList<>(); 60a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar for (boolean vBefore : new boolean[]{true, false}) { 61a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar for (boolean vAfter : new boolean[]{true, false}) { 62a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar for (boolean hBefore : new boolean[]{true, false}) { 63a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar for (boolean hAfter : new boolean[]{true, false}) { 640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar params.add(new Object[]{vBefore, hBefore, vAfter, hAfter}); 65a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 66a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 67a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 68a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 690a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar return params; 70a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 71da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar 720a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 730a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void onInitializeAccessibilityNodeInfoTest() throws Throwable { 74a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final RecyclerView recyclerView = new RecyclerView(getActivity()) { 75a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar //@Override 76a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public boolean canScrollHorizontally(int direction) { 77a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return direction < 0 && horizontalScrollBefore || 78a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar direction > 0 && horizontalScrollAfter; 79a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 80a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 81a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar //@Override 82a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public boolean canScrollVertically(int direction) { 83a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return direction < 0 && verticalScrollBefore || 84a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar direction > 0 && verticalScrollAfter; 85a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 86a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }; 87a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final TestAdapter adapter = new TestAdapter(10); 88a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AtomicBoolean hScrolledBack = new AtomicBoolean(false); 89a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AtomicBoolean vScrolledBack = new AtomicBoolean(false); 90a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AtomicBoolean hScrolledFwd = new AtomicBoolean(false); 91a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AtomicBoolean vScrolledFwd = new AtomicBoolean(false); 92a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar recyclerView.setAdapter(adapter); 93a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar recyclerView.setLayoutManager(new TestLayoutManager() { 94a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 95a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 96a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 97a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar layoutRange(recycler, 0, 5); 98a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 99a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 100a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 101a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public RecyclerView.LayoutParams generateDefaultLayoutParams() { 102a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return new RecyclerView.LayoutParams(-1, -1); 103a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 104a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 105a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 106a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public boolean canScrollVertically() { 107a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return verticalScrollAfter || verticalScrollBefore; 108a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 109a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 110a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 111a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, 112a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar RecyclerView.State state) { 113a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (dx > 0) { 114a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar hScrolledFwd.set(true); 115a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } else if (dx < 0) { 116a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar hScrolledBack.set(true); 117a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 118a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return 0; 119a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 120a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 121a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 122a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, 123a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar RecyclerView.State state) { 124a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (dy > 0) { 125a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar vScrolledFwd.set(true); 126a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } else if (dy < 0) { 127a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar vScrolledBack.set(true); 128a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 129a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return 0; 130a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 131a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 132a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 133a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public boolean canScrollHorizontally() { 134a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return horizontalScrollAfter || horizontalScrollBefore; 135a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 136a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }); 137a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar setRecyclerView(recyclerView); 138a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final RecyclerViewAccessibilityDelegate delegateCompat = recyclerView 139a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar .getCompatAccessibilityDelegate(); 140a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 141a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar runTestOnUiThread(new Runnable() { 142a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 143a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void run() { 144a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar delegateCompat.onInitializeAccessibilityNodeInfo(recyclerView, info); 145a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 146a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }); 147a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(horizontalScrollAfter || horizontalScrollBefore 148a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar || verticalScrollAfter || verticalScrollBefore, info.isScrollable()); 149a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(horizontalScrollBefore || verticalScrollBefore, 150a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar (info.getActions() & AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD) != 0); 151a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(horizontalScrollAfter || verticalScrollAfter, 152a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar (info.getActions() & AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD) != 0); 153a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfo = info 154a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar .getCollectionInfo(); 155a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertNotNull(collectionInfo); 156a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (recyclerView.getLayoutManager().canScrollVertically()) { 157a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(adapter.getItemCount(), collectionInfo.getRowCount()); 158a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 159a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (recyclerView.getLayoutManager().canScrollHorizontally()) { 160a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(adapter.getItemCount(), collectionInfo.getColumnCount()); 161a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 162a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 163a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityEvent event = AccessibilityEvent.obtain(); 164a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar runTestOnUiThread(new Runnable() { 165a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 166a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void run() { 167a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar delegateCompat.onInitializeAccessibilityEvent(recyclerView, event); 168a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 169a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }); 170a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityRecordCompat record = AccessibilityEventCompat 171a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar .asRecord(event); 172a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(record.isScrollable(), verticalScrollAfter || horizontalScrollAfter || 1730a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar verticalScrollBefore || horizontalScrollBefore); 174a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(record.getItemCount(), adapter.getItemCount()); 175a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 176a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar getInstrumentation().waitForIdleSync(); 1770a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar for (int i = 0; i < mRecyclerView.getChildCount(); i++) { 178a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final View view = mRecyclerView.getChildAt(i); 179a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityNodeInfoCompat childInfo = AccessibilityNodeInfoCompat.obtain(); 180a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar runTestOnUiThread(new Runnable() { 181a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 182a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void run() { 183a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar delegateCompat.getItemDelegate(). 184a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar onInitializeAccessibilityNodeInfo(view, childInfo); 185a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 186a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }); 187a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfo 188a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar = childInfo.getCollectionItemInfo(); 189a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertNotNull(collectionItemInfo); 190a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (recyclerView.getLayoutManager().canScrollHorizontally()) { 191a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(i, collectionItemInfo.getColumnIndex()); 192a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } else { 193a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(0, collectionItemInfo.getColumnIndex()); 194a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 195a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 196a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (recyclerView.getLayoutManager().canScrollVertically()) { 197a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(i, collectionItemInfo.getRowIndex()); 198a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } else { 199a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(0, collectionItemInfo.getRowIndex()); 200a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 201a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 202a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 203a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar runTestOnUiThread(new Runnable() { 204a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 205a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void run() { 206a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 207a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 208a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }); 209a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar hScrolledBack.set(false); 210a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar vScrolledBack.set(false); 211a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar hScrolledFwd.set(false); 212a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar vScrolledBack.set(false); 213a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar performAccessibilityAction(delegateCompat, recyclerView, 214a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD); 215a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(horizontalScrollBefore, hScrolledBack.get()); 216a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(verticalScrollBefore, vScrolledBack.get()); 217a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(false, hScrolledFwd.get()); 218a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(false, vScrolledFwd.get()); 219a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 220a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar hScrolledBack.set(false); 221a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar vScrolledBack.set(false); 222a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar hScrolledFwd.set(false); 223a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar vScrolledBack.set(false); 224a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar performAccessibilityAction(delegateCompat, recyclerView, 225a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD); 226a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(false, hScrolledBack.get()); 227a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(false, vScrolledBack.get()); 228a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(horizontalScrollAfter, hScrolledFwd.get()); 229a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(verticalScrollAfter, vScrolledFwd.get()); 230a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 231a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 2320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 2330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void ignoreAccessibilityIfAdapterHasChanged() throws Throwable { 234da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar final RecyclerView recyclerView = new RecyclerView(getActivity()) { 235da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar //@Override 236da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar public boolean canScrollHorizontally(int direction) { 237da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar return true; 238da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar } 239da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar 240da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar //@Override 241da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar public boolean canScrollVertically(int direction) { 242da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar return true; 243da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar } 244da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar }; 245da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar final DumbLayoutManager layoutManager = new DumbLayoutManager(); 246da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar final TestAdapter adapter = new TestAdapter(10); 247da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar recyclerView.setAdapter(adapter); 248da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar recyclerView.setLayoutManager(layoutManager); 249da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar layoutManager.expectLayouts(1); 250da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar setRecyclerView(recyclerView); 251da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar layoutManager.waitForLayout(1); 252da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar 253da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar final RecyclerViewAccessibilityDelegate delegateCompat = recyclerView 254da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar .getCompatAccessibilityDelegate(); 255da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 256da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar runTestOnUiThread(new Runnable() { 257da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar @Override 258da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar public void run() { 259da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar delegateCompat.onInitializeAccessibilityNodeInfo(recyclerView, info); 260da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar } 261da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar }); 262da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar assertTrue("test sanity", info.isScrollable()); 263da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar final AccessibilityNodeInfoCompat info2 = AccessibilityNodeInfoCompat.obtain(); 26466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar runTestOnUiThread(new Runnable() { 26566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar @Override 26666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar public void run() { 26766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar try { 26866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar adapter.deleteAndNotify(1, 1); 26966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } catch (Throwable throwable) { 27066826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar postExceptionToInstrumentation(throwable); 27166826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 27266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar delegateCompat.onInitializeAccessibilityNodeInfo(recyclerView, info2); 27366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar assertFalse("info should not be filled if data is out of date", 27466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar info2.isScrollable()); 27566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 27666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar }); 27766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar checkForMainThreadException(); 278da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar } 279da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar 280da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar boolean performAccessibilityAction(final AccessibilityDelegateCompat delegate, 2810a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar final RecyclerView recyclerView, final int action) throws Throwable { 282da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar final boolean[] result = new boolean[1]; 283a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar runTestOnUiThread(new Runnable() { 284a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 285a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void run() { 286da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar result[0] = delegate.performAccessibilityAction(recyclerView, action, null); 287a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 288a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }); 289a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar getInstrumentation().waitForIdleSync(); 290a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar Thread.sleep(250); 291da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar return result[0]; 292a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 293a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar} 294