195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar/* 295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * Copyright (C) 2016 The Android Open Source Project 395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * 495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * you may not use this file except in compliance with the License. 695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * You may obtain a copy of the License at 795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * 895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * 1095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * Unless required by applicable law or agreed to in writing, software 1195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 1295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * See the License for the specific language governing permissions and 1495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * limitations under the License. 1595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar */ 1695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 1795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarpackage android.support.v7.widget; 1895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 1995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport static org.junit.Assert.assertEquals; 2095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport static org.junit.Assert.assertNotNull; 2195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 2295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport android.graphics.Rect; 23754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.MediumTest; 2495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport android.view.View; 2595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 2695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport org.junit.Test; 2795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport org.junit.runner.RunWith; 2895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport org.junit.runners.Parameterized; 2995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 3095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport java.util.ArrayList; 3195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport java.util.HashMap; 3295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport java.util.List; 3395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarimport java.util.Map; 3495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 3595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar/** 3695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar * Tests dispatching no-op updates to the GLM and ensures it re-lays out items in the same location 3795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar */ 38754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikas@MediumTest 3995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar@RunWith(Parameterized.class) 4095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyarpublic class GridLayoutManagerNoOpUpdateTest extends BaseGridLayoutManagerTest { 41e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas @Parameterized.Parameters(name = "conf:{0},rtl={1}") 4295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar public static List<Object[]> getParams() { 4395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar List<Object[]> result = new ArrayList<>(); 4495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar for (BaseGridLayoutManagerTest.Config config : createBaseVariations()) { 4595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar result.add(new Object[]{ 4695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar config, 4795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar true 4895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar }); 4995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar result.add(new Object[]{ 5095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar config, 5195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar false 5295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar }); 5395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 5495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar return result; 5595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 5695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 5795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar private final Config mConfig; 5895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar private final boolean mRtl; 5995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 6095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar public GridLayoutManagerNoOpUpdateTest(Config config, boolean rtl) { 6195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mConfig = config; 6295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mRtl = rtl; 6395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 6495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 6595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar @Test 6695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar public void rtlChanges() throws Throwable { 6795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar RecyclerView rv = createRecyclerView(); 6895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mGlm.setFakeRtl(mRtl); 6995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar waitForFirstLayout(rv); 7095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar Map<Long, Rect> before = takeSnapshot(); 7195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 7295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar View chosen = mGlm.findViewByPosition(1); 7395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar assertNotNull("test sanity", chosen); 7495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mGlm.expectLayout(2); 7595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mAdapter.changeAndNotify(1, 1); 7695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mGlm.waitForLayout(2); 7795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar Map<Long, Rect> after = takeSnapshot(); 7895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar assertSnapshotsEqual(before, after); 7995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 8095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 8195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar private void assertSnapshotsEqual(Map<Long, Rect> before, Map<Long, Rect> after) { 8295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar for (Map.Entry<Long, Rect> entry : before.entrySet()) { 8395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar Rect newPosition = after.get(entry.getKey()); 8495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar assertNotNull("cannot find " + entry.getKey() + " in after map", newPosition); 8595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar assertEquals("position should be the same", entry.getValue(), newPosition); 8695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 8795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar assertEquals("visible view count should be equal", before.size(), after.size()); 8895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 8995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 9095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar private Map<Long, Rect> takeSnapshot() { 9195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar Rect rvBounds = new Rect(); 9295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar if (mRecyclerView.getClipToPadding()) { 9395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar rvBounds.set(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), 9495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mRecyclerView.getWidth() - mRecyclerView.getPaddingRight(), 9595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar mRecyclerView.getHeight() - mRecyclerView.getPaddingBottom()); 9695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } else { 9795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar rvBounds.set(0, 0, mRecyclerView.getWidth(), mRecyclerView.getHeight()); 9895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 9995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar Map<Long, Rect> positionMap = new HashMap<>(); 10095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar for (int i = 0; i < mGlm.getChildCount(); i++) { 10195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar View child = mGlm.getChildAt(i); 10295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar Rect childBounds = getChildBounds(mRecyclerView, child, true); 10395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar long id = mRecyclerView.getChildViewHolder(child).getItemId(); 10495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar if (rvBounds.intersect(childBounds)) { 10595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar positionMap.put(id, childBounds); 10695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 10795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 10895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar return positionMap; 10995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 11095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 11195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar private Rect getChildBounds(RecyclerView recyclerView, View child, boolean offset) { 11295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); 11395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams(); 11495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar Rect rect = new Rect(layoutManager.getDecoratedLeft(child) - lp.leftMargin, 11595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar layoutManager.getDecoratedTop(child) - lp.topMargin, 11695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar layoutManager.getDecoratedRight(child) + lp.rightMargin, 11795017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar layoutManager.getDecoratedBottom(child) + lp.bottomMargin); 11895017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar return rect; 11995017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 12095017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar 12195017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar private RecyclerView createRecyclerView() throws Throwable { 12295017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar GridTestAdapter adapter = new GridTestAdapter(mConfig.mItemCount); 12395017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar adapter.setHasStableIds(true); 12495017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar return setupBasic(mConfig, adapter); 12595017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar } 12695017f70973e4cbc9b7be1142e2cf887af4f4a48Yigit Boyar} 127