• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v7.widget;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 
22 import android.graphics.Rect;
23 import android.view.View;
24 
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27 import org.junit.runners.Parameterized;
28 
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 
34 /**
35  * Tests dispatching no-op updates to the GLM and ensures it re-lays out items in the same location
36  */
37 @RunWith(Parameterized.class)
38 public class GridLayoutManagerNoOpUpdateTest extends BaseGridLayoutManagerTest {
39     @Parameterized.Parameters(name = "conf:{0} rtl={1}")
getParams()40     public static List<Object[]> getParams() {
41         List<Object[]> result = new ArrayList<>();
42         for (BaseGridLayoutManagerTest.Config config : createBaseVariations()) {
43             result.add(new Object[]{
44                     config,
45                     true
46             });
47             result.add(new Object[]{
48                     config,
49                     false
50             });
51         }
52         return result;
53     }
54 
55     private final Config mConfig;
56     private final boolean mRtl;
57 
GridLayoutManagerNoOpUpdateTest(Config config, boolean rtl)58     public GridLayoutManagerNoOpUpdateTest(Config config, boolean rtl) {
59         mConfig = config;
60         mRtl = rtl;
61     }
62 
63     @Test
rtlChanges()64     public void rtlChanges() throws Throwable {
65         RecyclerView rv = createRecyclerView();
66         mGlm.setFakeRtl(mRtl);
67         waitForFirstLayout(rv);
68         Map<Long, Rect> before = takeSnapshot();
69 
70         View chosen = mGlm.findViewByPosition(1);
71         assertNotNull("test sanity", chosen);
72         mGlm.expectLayout(2);
73         mAdapter.changeAndNotify(1, 1);
74         mGlm.waitForLayout(2);
75         Map<Long, Rect> after = takeSnapshot();
76         assertSnapshotsEqual(before, after);
77     }
78 
assertSnapshotsEqual(Map<Long, Rect> before, Map<Long, Rect> after)79     private void assertSnapshotsEqual(Map<Long, Rect> before, Map<Long, Rect> after) {
80         for (Map.Entry<Long, Rect> entry : before.entrySet()) {
81             Rect newPosition = after.get(entry.getKey());
82             assertNotNull("cannot find " + entry.getKey() + " in after map", newPosition);
83             assertEquals("position should be the same", entry.getValue(), newPosition);
84         }
85         assertEquals("visible view count should be equal", before.size(), after.size());
86     }
87 
takeSnapshot()88     private Map<Long, Rect> takeSnapshot() {
89         Rect rvBounds = new Rect();
90         if (mRecyclerView.getClipToPadding()) {
91             rvBounds.set(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(),
92                     mRecyclerView.getWidth() - mRecyclerView.getPaddingRight(),
93                     mRecyclerView.getHeight() - mRecyclerView.getPaddingBottom());
94         } else {
95             rvBounds.set(0, 0, mRecyclerView.getWidth(), mRecyclerView.getHeight());
96         }
97         Map<Long, Rect> positionMap = new HashMap<>();
98         for (int i = 0; i < mGlm.getChildCount(); i++) {
99             View child = mGlm.getChildAt(i);
100             Rect childBounds = getChildBounds(mRecyclerView, child, true);
101             long id = mRecyclerView.getChildViewHolder(child).getItemId();
102             if (rvBounds.intersect(childBounds)) {
103                 positionMap.put(id, childBounds);
104             }
105         }
106         return positionMap;
107     }
108 
getChildBounds(RecyclerView recyclerView, View child, boolean offset)109     private Rect getChildBounds(RecyclerView recyclerView, View child, boolean offset) {
110         RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
111         RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams();
112         Rect rect = new Rect(layoutManager.getDecoratedLeft(child) - lp.leftMargin,
113                 layoutManager.getDecoratedTop(child) - lp.topMargin,
114                 layoutManager.getDecoratedRight(child) + lp.rightMargin,
115                 layoutManager.getDecoratedBottom(child) + lp.bottomMargin);
116         return rect;
117     }
118 
createRecyclerView()119     private RecyclerView createRecyclerView() throws Throwable {
120         GridTestAdapter adapter = new GridTestAdapter(mConfig.mItemCount);
121         adapter.setHasStableIds(true);
122         return setupBasic(mConfig, adapter);
123     }
124 }
125