blob: 99ec4ed8aa3c92a4ecc1bc6cf5df2abe97fac107 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.v7.widget;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import android.util.Log;
import android.view.View;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@RunWith(Parameterized.class)
public class GridLayoutManagerBaseConfigSetTest extends BaseGridLayoutManagerTest {
@Parameterized.Parameters(name = "{0}")
public static List<Config> params() {
return createBaseVariations();
}
private final Config mConfig;
public GridLayoutManagerBaseConfigSetTest(Config config) {
mConfig = config;
}
@Test
public void scrollBackAndPreservePositions() throws Throwable {
Config config = (Config) mConfig.clone();
config.mItemCount = 150;
scrollBackAndPreservePositionsTest(config);
}
public void scrollBackAndPreservePositionsTest(final Config config) throws Throwable {
final RecyclerView rv = setupBasic(config);
for (int i = 1; i < mAdapter.getItemCount(); i += config.mSpanCount + 2) {
mAdapter.setFullSpan(i);
}
waitForFirstLayout(rv);
final int[] globalPositions = new int[mAdapter.getItemCount()];
Arrays.fill(globalPositions, Integer.MIN_VALUE);
final int scrollStep = (mGlm.mOrientationHelper.getTotalSpace() / 20)
* (config.mReverseLayout ? -1 : 1);
final String logPrefix = config.toString();
final int[] globalPos = new int[1];
runTestOnUiThread(new Runnable() {
@Override
public void run() {
assertSame("test sanity", mRecyclerView, rv);
int globalScrollPosition = 0;
int visited = 0;
while (visited < mAdapter.getItemCount()) {
for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
View child = mRecyclerView.getChildAt(i);
final int pos = mRecyclerView.getChildLayoutPosition(child);
if (globalPositions[pos] != Integer.MIN_VALUE) {
continue;
}
visited++;
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
child.getLayoutParams();
if (config.mReverseLayout) {
globalPositions[pos] = globalScrollPosition +
mGlm.mOrientationHelper.getDecoratedEnd(child);
} else {
globalPositions[pos] = globalScrollPosition +
mGlm.mOrientationHelper.getDecoratedStart(child);
}
assertEquals(logPrefix + " span index should match",
mGlm.getSpanSizeLookup().getSpanIndex(pos, mGlm.getSpanCount()),
lp.getSpanIndex());
}
int scrolled = mGlm.scrollBy(scrollStep,
mRecyclerView.mRecycler, mRecyclerView.mState);
globalScrollPosition += scrolled;
if (scrolled == 0) {
assertEquals(
logPrefix + " If scroll is complete, all views should be visited",
visited, mAdapter.getItemCount());
}
}
if (DEBUG) {
Log.d(TAG, "done recording positions " + Arrays.toString(globalPositions));
}
globalPos[0] = globalScrollPosition;
}
});
checkForMainThreadException();
// test sanity, ensure scroll happened
runTestOnUiThread(new Runnable() {
@Override
public void run() {
final int childCount = mGlm.getChildCount();
final BitSet expectedPositions = new BitSet();
for (int i = 0; i < childCount; i ++) {
expectedPositions.set(mAdapter.getItemCount() - i - 1);
}
for (int i = 0; i <childCount; i ++) {
final View view = mGlm.getChildAt(i);
int position = mGlm.getPosition(view);
assertTrue("child position should be in last page", expectedPositions.get(position));
}
}
});
getInstrumentation().waitForIdleSync();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
int globalScrollPosition = globalPos[0];
// now scroll back and make sure global positions match
BitSet shouldTest = new BitSet(mAdapter.getItemCount());
shouldTest.set(0, mAdapter.getItemCount() - 1, true);
String assertPrefix = config
+ " global pos must match when scrolling in reverse for position ";
int scrollAmount = Integer.MAX_VALUE;
while (!shouldTest.isEmpty() && scrollAmount != 0) {
for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
View child = mRecyclerView.getChildAt(i);
int pos = mRecyclerView.getChildLayoutPosition(child);
if (!shouldTest.get(pos)) {
continue;
}
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
child.getLayoutParams();
shouldTest.clear(pos);
int globalPos;
if (config.mReverseLayout) {
globalPos = globalScrollPosition +
mGlm.mOrientationHelper.getDecoratedEnd(child);
} else {
globalPos = globalScrollPosition +
mGlm.mOrientationHelper.getDecoratedStart(child);
}
assertEquals(assertPrefix + pos,
globalPositions[pos], globalPos);
assertEquals("span index should match",
mGlm.getSpanSizeLookup().getSpanIndex(pos, mGlm.getSpanCount()),
lp.getSpanIndex());
}
scrollAmount = mGlm.scrollBy(-scrollStep,
mRecyclerView.mRecycler, mRecyclerView.mState);
globalScrollPosition += scrollAmount;
}
assertTrue("all views should be seen", shouldTest.isEmpty());
}
});
checkForMainThreadException();
}
}