| /* |
| * Copyright (C) 2015 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 androidx.leanback.widget; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNotSame; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.mockito.Mockito.any; |
| import static org.mockito.Mockito.anyInt; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.timeout; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| |
| import android.content.Intent; |
| import android.graphics.Canvas; |
| import android.graphics.Color; |
| import android.graphics.Rect; |
| import android.graphics.drawable.ColorDrawable; |
| import android.os.Build; |
| import android.os.Parcelable; |
| import android.text.Selection; |
| import android.text.Spannable; |
| import android.util.DisplayMetrics; |
| import android.util.SparseArray; |
| import android.util.SparseIntArray; |
| import android.util.TypedValue; |
| import android.view.KeyEvent; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.TextView; |
| |
| import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; |
| import androidx.leanback.test.R; |
| import androidx.leanback.testutils.PollingCheck; |
| import androidx.recyclerview.widget.DefaultItemAnimator; |
| import androidx.recyclerview.widget.RecyclerView; |
| import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate; |
| import androidx.test.ext.junit.runners.AndroidJUnit4; |
| import androidx.test.filters.FlakyTest; |
| import androidx.test.filters.LargeTest; |
| import androidx.test.filters.SdkSuppress; |
| import androidx.test.platform.app.InstrumentationRegistry; |
| import androidx.test.rule.ActivityTestRule; |
| |
| import org.junit.After; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.TestName; |
| import org.junit.runner.RunWith; |
| import org.mockito.Mockito; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| |
| @LargeTest |
| @RunWith(AndroidJUnit4.class) |
| public class GridWidgetTest { |
| |
| private static final float DELTA = 1f; |
| private static final boolean HUMAN_DELAY = false; |
| private static final long WAIT_FOR_SCROLL_IDLE_TIMEOUT_MS = 60000; |
| private static final int WAIT_FOR_LAYOUT_PASS_TIMEOUT_MS = 2000; |
| private static final int WAIT_FOR_ITEM_ANIMATION_FINISH_TIMEOUT_MS = 6000; |
| |
| protected ActivityTestRule<GridActivity> mActivityTestRule; |
| protected GridActivity mActivity; |
| protected BaseGridView mGridView; |
| protected GridLayoutManager mLayoutManager; |
| private GridLayoutManager.OnLayoutCompleteListener mWaitLayoutListener; |
| protected int mOrientation; |
| protected int mNumRows; |
| protected int[] mRemovedItems; |
| |
| private final Comparator<View> mRowSortComparator = new Comparator<View>() { |
| @Override |
| public int compare(View lhs, View rhs) { |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| return lhs.getLeft() - rhs.getLeft(); |
| } else { |
| return lhs.getTop() - rhs.getTop(); |
| } |
| }; |
| }; |
| |
| /** |
| * Verify margins between items on same row are same. |
| */ |
| private final Runnable mVerifyLayout = new Runnable() { |
| @Override |
| public void run() { |
| verifyMargin(); |
| } |
| }; |
| |
| @Rule public TestName testName = new TestName(); |
| |
| public static void sendKey(int keyCode) { |
| InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keyCode); |
| } |
| |
| public static void sendRepeatedKeys(int repeats, int keyCode) { |
| for (int i = 0; i < repeats; i++) { |
| InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keyCode); |
| } |
| } |
| |
| private void humanDelay(int delay) throws InterruptedException { |
| if (HUMAN_DELAY) Thread.sleep(delay); |
| } |
| /** |
| * Change size of the Adapter and notifyDataSetChanged. |
| */ |
| private void changeArraySize(final int size) throws Throwable { |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.changeArraySize(size); |
| } |
| }); |
| } |
| |
| static String dumpGridView(BaseGridView gridView) { |
| return "findFocus:" + gridView.getRootView().findFocus() |
| + " isLayoutRequested:" + gridView.isLayoutRequested() |
| + " selectedPosition:" + gridView.getSelectedPosition() |
| + " adapter.itemCount:" + gridView.getAdapter().getItemCount() |
| + " itemAnimator.isRunning:" + gridView.getItemAnimator().isRunning() |
| + " scrollState:" + gridView.getScrollState(); |
| } |
| |
| /** |
| * Change selected position. |
| */ |
| private void setSelectedPosition(final int position, final int scrollExtra) throws Throwable { |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPosition(position, scrollExtra); |
| } |
| }); |
| waitForLayout(false); |
| } |
| |
| private void setSelectedPosition(final int position) throws Throwable { |
| setSelectedPosition(position, 0); |
| } |
| |
| private void setSelectedPositionSmooth(final int position) throws Throwable { |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(position); |
| } |
| }); |
| } |
| /** |
| * Scrolls using given key. |
| */ |
| protected void scroll(int key, Runnable verify) throws Throwable { |
| do { |
| if (verify != null) { |
| mActivityTestRule.runOnUiThread(verify); |
| } |
| sendRepeatedKeys(100, key); |
| try { |
| Thread.sleep(300); |
| } catch (InterruptedException ex) { |
| break; |
| } |
| } while (mGridView.getLayoutManager().isSmoothScrolling() |
| || mGridView.getScrollState() != BaseGridView.SCROLL_STATE_IDLE); |
| } |
| |
| protected void scrollToBegin(Runnable verify) throws Throwable { |
| int key; |
| // first move to first column/row |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| key = KeyEvent.KEYCODE_DPAD_UP; |
| } else { |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| key = KeyEvent.KEYCODE_DPAD_RIGHT; |
| } else { |
| key = KeyEvent.KEYCODE_DPAD_LEFT; |
| } |
| } |
| scroll(key, null); |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| key = KeyEvent.KEYCODE_DPAD_RIGHT; |
| } else { |
| key = KeyEvent.KEYCODE_DPAD_LEFT; |
| } |
| } else { |
| key = KeyEvent.KEYCODE_DPAD_UP; |
| } |
| scroll(key, verify); |
| } |
| |
| protected void scrollToEnd(Runnable verify) throws Throwable { |
| int key; |
| // first move to first column/row |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| key = KeyEvent.KEYCODE_DPAD_UP; |
| } else { |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| key = KeyEvent.KEYCODE_DPAD_RIGHT; |
| } else { |
| key = KeyEvent.KEYCODE_DPAD_LEFT; |
| } |
| } |
| scroll(key, null); |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| key = KeyEvent.KEYCODE_DPAD_LEFT; |
| } else { |
| key = KeyEvent.KEYCODE_DPAD_RIGHT; |
| } |
| } else { |
| key = KeyEvent.KEYCODE_DPAD_DOWN; |
| } |
| scroll(key, verify); |
| } |
| |
| /** |
| * Group and sort children by their position on each row (HORIZONTAL) or column(VERTICAL). |
| */ |
| protected View[][] sortByRows() { |
| final HashMap<Integer, ArrayList<View>> rows = new HashMap<Integer, ArrayList<View>>(); |
| ArrayList<Integer> rowLocations = new ArrayList<>(); |
| for (int i = 0; i < mGridView.getChildCount(); i++) { |
| View v = mGridView.getChildAt(i); |
| int rowLocation; |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| rowLocation = v.getTop(); |
| } else { |
| rowLocation = mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL |
| ? v.getRight() : v.getLeft(); |
| } |
| ArrayList<View> views = rows.get(rowLocation); |
| if (views == null) { |
| views = new ArrayList<View>(); |
| rows.put(rowLocation, views); |
| rowLocations.add(rowLocation); |
| } |
| views.add(v); |
| } |
| Object[] sortedLocations = rowLocations.toArray(); |
| Arrays.sort(sortedLocations); |
| if (mNumRows != rows.size()) { |
| assertEquals("Dump Views by rows "+rows, mNumRows, rows.size()); |
| } |
| View[][] sorted = new View[rows.size()][]; |
| for (int i = 0; i < rowLocations.size(); i++) { |
| Integer rowLocation = rowLocations.get(i); |
| ArrayList<View> arr = rows.get(rowLocation); |
| View[] views = arr.toArray(new View[arr.size()]); |
| Arrays.sort(views, mRowSortComparator); |
| sorted[i] = views; |
| } |
| return sorted; |
| } |
| |
| protected void verifyMargin() { |
| View[][] sorted = sortByRows(); |
| for (int row = 0; row < sorted.length; row++) { |
| View[] views = sorted[row]; |
| int margin = -1; |
| for (int i = 1; i < views.length; i++) { |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| assertEquals(mGridView.getHorizontalMargin(), |
| views[i].getLeft() - views[i - 1].getRight()); |
| } else { |
| assertEquals(mGridView.getVerticalMargin(), |
| views[i].getTop() - views[i - 1].getBottom()); |
| } |
| } |
| } |
| } |
| |
| protected void verifyBeginAligned() { |
| View[][] sorted = sortByRows(); |
| int alignedLocation = 0; |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| for (int i = 0; i < sorted.length; i++) { |
| if (i == 0) { |
| alignedLocation = sorted[i][sorted[i].length - 1].getRight(); |
| } else { |
| assertEquals(alignedLocation, sorted[i][sorted[i].length - 1].getRight()); |
| } |
| } |
| } else { |
| for (int i = 0; i < sorted.length; i++) { |
| if (i == 0) { |
| alignedLocation = sorted[i][0].getLeft(); |
| } else { |
| assertEquals(alignedLocation, sorted[i][0].getLeft()); |
| } |
| } |
| } |
| } else { |
| for (int i = 0; i < sorted.length; i++) { |
| if (i == 0) { |
| alignedLocation = sorted[i][0].getTop(); |
| } else { |
| assertEquals(alignedLocation, sorted[i][0].getTop()); |
| } |
| } |
| } |
| } |
| |
| protected int[] getEndEdges() { |
| View[][] sorted = sortByRows(); |
| int[] edges = new int[sorted.length]; |
| if (mOrientation == BaseGridView.HORIZONTAL) { |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| for (int i = 0; i < sorted.length; i++) { |
| edges[i] = sorted[i][0].getLeft(); |
| } |
| } else { |
| for (int i = 0; i < sorted.length; i++) { |
| edges[i] = sorted[i][sorted[i].length - 1].getRight(); |
| } |
| } |
| } else { |
| for (int i = 0; i < sorted.length; i++) { |
| edges[i] = sorted[i][sorted[i].length - 1].getBottom(); |
| } |
| } |
| return edges; |
| } |
| |
| protected void verifyEdgesSame(int[] edges, int[] edges2) { |
| assertEquals(edges.length, edges2.length); |
| for (int i = 0; i < edges.length; i++) { |
| assertEquals(edges[i], edges2[i]); |
| } |
| } |
| |
| protected void verifyBoundCount(int count) { |
| if (mActivity.getBoundCount() != count) { |
| StringBuffer b = new StringBuffer(); |
| b.append("ItemsLength: "); |
| for (int i = 0; i < mActivity.mItemLengths.length; i++) { |
| b.append(mActivity.mItemLengths[i]).append(","); |
| } |
| assertEquals("Bound count does not match, ItemsLengths: "+ b, |
| count, mActivity.getBoundCount()); |
| } |
| } |
| |
| private static int getCenterY(View v) { |
| return (v.getTop() + v.getBottom())/2; |
| } |
| |
| private static int getCenterX(View v) { |
| return (v.getLeft() + v.getRight())/2; |
| } |
| |
| private void initActivity(Intent intent) throws Throwable { |
| mActivityTestRule = new ActivityTestRule<GridActivity>(GridActivity.class, false, false); |
| mActivity = mActivityTestRule.launchActivity(intent); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.setTitle(testName.getMethodName()); |
| } |
| }); |
| Thread.sleep(1000); |
| mGridView = mActivity.mGridView; |
| mLayoutManager = (GridLayoutManager) mGridView.getLayoutManager(); |
| } |
| |
| @After |
| public void clearTest() { |
| mWaitLayoutListener = null; |
| mLayoutManager = null; |
| mGridView = null; |
| mActivity = null; |
| mActivityTestRule = null; |
| } |
| |
| /** |
| * Must be called before waitForLayout() to prepare layout listener. |
| */ |
| protected void startWaitLayout() { |
| if (mWaitLayoutListener != null) { |
| throw new IllegalStateException("startWaitLayout() already called"); |
| } |
| if (mLayoutManager.mLayoutCompleteListener != null) { |
| throw new IllegalStateException("Cannot startWaitLayout()"); |
| } |
| mWaitLayoutListener = mLayoutManager.mLayoutCompleteListener = |
| mock(GridLayoutManager.OnLayoutCompleteListener.class); |
| } |
| |
| /** |
| * wait layout to be called and remove the listener. |
| */ |
| protected void waitForLayout() { |
| waitForLayout(true); |
| } |
| |
| /** |
| * wait layout to be called and remove the listener. |
| * @param force True if always wait regardless if layout requested |
| */ |
| protected void waitForLayout(boolean force) { |
| if (mWaitLayoutListener == null) { |
| throw new IllegalStateException("startWaitLayout() not called"); |
| } |
| if (mWaitLayoutListener != mLayoutManager.mLayoutCompleteListener) { |
| throw new IllegalStateException("layout listener inconistent"); |
| } |
| try { |
| if (force || mGridView.isLayoutRequested()) { |
| verify(mWaitLayoutListener, timeout(WAIT_FOR_LAYOUT_PASS_TIMEOUT_MS).atLeastOnce()) |
| .onLayoutCompleted(any(RecyclerView.State.class)); |
| } |
| } finally { |
| mWaitLayoutListener = null; |
| mLayoutManager.mLayoutCompleteListener = null; |
| } |
| } |
| |
| /** |
| * If currently running animator, wait for it to finish, otherwise return immediately. |
| * To wait the ItemAnimator start, you can use waitForLayout() to make sure layout pass has |
| * processed adapter change. |
| */ |
| protected void waitForItemAnimation(int timeoutMs) throws Throwable { |
| final RecyclerView.ItemAnimator.ItemAnimatorFinishedListener listener = mock( |
| RecyclerView.ItemAnimator.ItemAnimatorFinishedListener.class); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().isRunning(listener); |
| } |
| }); |
| verify(listener, timeout(timeoutMs).atLeastOnce()).onAnimationsFinished(); |
| } |
| |
| protected void waitForItemAnimation() throws Throwable { |
| waitForItemAnimation(WAIT_FOR_ITEM_ANIMATION_FINISH_TIMEOUT_MS); |
| } |
| |
| /** |
| * wait animation start |
| */ |
| protected void waitForItemAnimationStart() throws Throwable { |
| long totalWait = 0; |
| while (!mGridView.getItemAnimator().isRunning()) { |
| Thread.sleep(10); |
| if ((totalWait += 10) > WAIT_FOR_ITEM_ANIMATION_FINISH_TIMEOUT_MS) { |
| throw new RuntimeException("waitForItemAnimationStart Timeout"); |
| } |
| } |
| } |
| |
| /** |
| * Run task in UI thread and wait for layout and ItemAnimator finishes. |
| */ |
| protected void performAndWaitForAnimation(Runnable task) throws Throwable { |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(task); |
| waitForLayout(); |
| waitForItemAnimation(); |
| } |
| |
| protected void waitForScrollIdle() throws Throwable { |
| waitForScrollIdle(null); |
| } |
| |
| /** |
| * Wait for grid view stop scroll and optionally verify state of grid view. |
| */ |
| protected void waitForScrollIdle(Runnable verify) throws Throwable { |
| Thread.sleep(100); |
| int total = 0; |
| while (mGridView.getLayoutManager().isSmoothScrolling() |
| || mGridView.getScrollState() != BaseGridView.SCROLL_STATE_IDLE) { |
| if ((total += 100) >= WAIT_FOR_SCROLL_IDLE_TIMEOUT_MS) { |
| throw new RuntimeException("waitForScrollIdle Timeout"); |
| } |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException ex) { |
| break; |
| } |
| if (verify != null) { |
| mActivityTestRule.runOnUiThread(verify); |
| } |
| } |
| } |
| |
| @Test |
| public void testThreeRowHorizontalBasic() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| scrollToEnd(mVerifyLayout); |
| |
| scrollToBegin(mVerifyLayout); |
| |
| verifyBeginAligned(); |
| } |
| |
| static class DividerDecoration extends RecyclerView.ItemDecoration { |
| |
| private ColorDrawable mTopDivider; |
| private ColorDrawable mBottomDivider; |
| private int mLeftOffset; |
| private int mRightOffset; |
| private int mTopOffset; |
| private int mBottomOffset; |
| |
| DividerDecoration(int leftOffset, int topOffset, int rightOffset, int bottomOffset) { |
| mLeftOffset = leftOffset; |
| mTopOffset = topOffset; |
| mRightOffset = rightOffset; |
| mBottomOffset = bottomOffset; |
| } |
| |
| @Override |
| public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { |
| if (mTopDivider == null) { |
| mTopDivider = new ColorDrawable(Color.RED); |
| } |
| if (mBottomDivider == null) { |
| mBottomDivider = new ColorDrawable(Color.BLUE); |
| } |
| final int childCount = parent.getChildCount(); |
| final int width = parent.getWidth(); |
| for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) { |
| final View view = parent.getChildAt(childViewIndex); |
| mTopDivider.setBounds(0, (int) view.getY() - mTopOffset, width, (int) view.getY()); |
| mTopDivider.draw(c); |
| mBottomDivider.setBounds(0, (int) view.getY() + view.getHeight(), width, |
| (int) view.getY() + view.getHeight() + mBottomOffset); |
| mBottomDivider.draw(c); |
| } |
| } |
| |
| @Override |
| public void getItemOffsets(Rect outRect, View view, RecyclerView parent, |
| RecyclerView.State state) { |
| outRect.left = mLeftOffset; |
| outRect.top = mTopOffset; |
| outRect.right = mRightOffset; |
| outRect.bottom = mBottomOffset; |
| } |
| } |
| |
| @Test |
| public void testItemDecorationAndMargins() throws Throwable { |
| |
| final int leftMargin = 3; |
| final int topMargin = 4; |
| final int rightMargin = 7; |
| final int bottomMargin = 8; |
| final int itemHeight = 100; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{itemHeight, itemHeight, itemHeight}); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_MARGINS, |
| new int[]{leftMargin, topMargin, rightMargin, bottomMargin}); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| final int paddingLeft = mGridView.getPaddingLeft(); |
| final int paddingTop = mGridView.getPaddingTop(); |
| final int verticalSpace = mGridView.getVerticalMargin(); |
| final int decorationLeft = 17; |
| final int decorationTop = 1; |
| final int decorationRight = 19; |
| final int decorationBottom = 2; |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.addItemDecoration(new DividerDecoration(decorationLeft, decorationTop, |
| decorationRight, decorationBottom)); |
| } |
| }); |
| |
| View child0 = mGridView.getChildAt(0); |
| View child1 = mGridView.getChildAt(1); |
| View child2 = mGridView.getChildAt(2); |
| |
| assertEquals(itemHeight, child0.getBottom() - child0.getTop()); |
| |
| // verify left margins |
| assertEquals(paddingLeft + leftMargin + decorationLeft, child0.getLeft()); |
| assertEquals(paddingLeft + leftMargin + decorationLeft, child1.getLeft()); |
| assertEquals(paddingLeft + leftMargin + decorationLeft, child2.getLeft()); |
| // verify top bottom margins and decoration offset |
| assertEquals(paddingTop + topMargin + decorationTop, child0.getTop()); |
| assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin, |
| child1.getTop() - child0.getBottom()); |
| assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin, |
| child2.getTop() - child1.getBottom()); |
| |
| } |
| |
| @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) |
| @Test |
| public void testItemDecorationAndMarginsAndOpticalBounds() throws Throwable { |
| final int leftMargin = 3; |
| final int topMargin = 4; |
| final int rightMargin = 7; |
| final int bottomMargin = 8; |
| final int itemHeight = 100; |
| final int ninePatchDrawableResourceId = R.drawable.lb_card_shadow_focused; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{itemHeight, itemHeight, itemHeight}); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_MARGINS, |
| new int[]{leftMargin, topMargin, rightMargin, bottomMargin}); |
| intent.putExtra(GridActivity.EXTRA_NINEPATCH_SHADOW, ninePatchDrawableResourceId); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| final int paddingLeft = mGridView.getPaddingLeft(); |
| final int paddingTop = mGridView.getPaddingTop(); |
| final int verticalSpace = mGridView.getVerticalMargin(); |
| final int decorationLeft = 17; |
| final int decorationTop = 1; |
| final int decorationRight = 19; |
| final int decorationBottom = 2; |
| |
| final Rect opticalPaddings = new Rect(); |
| mGridView.getResources().getDrawable(ninePatchDrawableResourceId) |
| .getPadding(opticalPaddings); |
| final int opticalInsetsLeft = opticalPaddings.left; |
| final int opticalInsetsTop = opticalPaddings.top; |
| final int opticalInsetsRight = opticalPaddings.right; |
| final int opticalInsetsBottom = opticalPaddings.bottom; |
| assertTrue(opticalInsetsLeft > 0); |
| assertTrue(opticalInsetsTop > 0); |
| assertTrue(opticalInsetsRight > 0); |
| assertTrue(opticalInsetsBottom > 0); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.addItemDecoration(new DividerDecoration(decorationLeft, decorationTop, |
| decorationRight, decorationBottom)); |
| } |
| }); |
| |
| View child0 = mGridView.getChildAt(0); |
| View child1 = mGridView.getChildAt(1); |
| View child2 = mGridView.getChildAt(2); |
| |
| assertEquals(itemHeight + opticalInsetsTop + opticalInsetsBottom, |
| child0.getBottom() - child0.getTop()); |
| |
| // verify left margins decoration and optical insets |
| assertEquals(paddingLeft + leftMargin + decorationLeft - opticalInsetsLeft, |
| child0.getLeft()); |
| assertEquals(paddingLeft + leftMargin + decorationLeft - opticalInsetsLeft, |
| child1.getLeft()); |
| assertEquals(paddingLeft + leftMargin + decorationLeft - opticalInsetsLeft, |
| child2.getLeft()); |
| // verify top bottom margins decoration offset and optical insets |
| assertEquals(paddingTop + topMargin + decorationTop, child0.getTop() + opticalInsetsTop); |
| assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin, |
| (child1.getTop() + opticalInsetsTop) - (child0.getBottom() - opticalInsetsBottom)); |
| assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin, |
| (child2.getTop() + opticalInsetsTop) - (child1.getBottom() - opticalInsetsBottom)); |
| |
| } |
| |
| @Test |
| public void testThreeColumnVerticalBasic() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| |
| scrollToEnd(mVerifyLayout); |
| |
| scrollToBegin(mVerifyLayout); |
| |
| verifyBeginAligned(); |
| } |
| |
| @Test |
| public void testRedundantAppendRemove() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid_testredundantappendremove); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{ |
| 149,177,128,234,227,187,163,223,146,210,228,148,227,193,182,197,177,142,225,207, |
| 157,171,209,204,187,184,123,221,197,153,202,179,193,214,226,173,225,143,188,159, |
| 139,193,233,143,227,203,222,124,228,223,164,131,228,126,211,160,165,152,235,184, |
| 155,224,149,181,171,229,200,234,177,130,164,172,188,139,132,203,179,220,147,131, |
| 226,127,230,239,183,203,206,227,123,170,239,234,200,149,237,204,160,133,202,234, |
| 173,122,139,149,151,153,216,231,121,145,227,153,186,174,223,180,123,215,206,216, |
| 239,222,219,207,193,218,140,133,171,153,183,132,233,138,159,174,189,171,143,128, |
| 152,222,141,202,224,190,134,120,181,231,230,136,132,224,136,210,207,150,128,183, |
| 221,194,179,220,126,221,137,205,223,193,172,132,226,209,133,191,227,127,159,171, |
| 180,149,237,177,194,207,170,202,161,144,147,199,205,186,164,140,193,203,224,129}); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| |
| scrollToEnd(mVerifyLayout); |
| |
| scrollToBegin(mVerifyLayout); |
| |
| verifyBeginAligned(); |
| } |
| |
| @Test |
| public void testRedundantAppendRemove2() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid_testredundantappendremove2); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{ |
| 318,333,199,224,246,273,269,289,340,313,265,306,349,269,185,282,257,354,316,252, |
| 237,290,283,343,196,313,290,343,191,262,342,228,343,349,251,203,226,305,265,213, |
| 216,333,295,188,187,281,288,311,244,232,224,332,290,181,267,276,226,261,335,355, |
| 225,217,219,183,234,285,257,304,182,250,244,223,257,219,342,185,347,205,302,315, |
| 299,309,292,237,192,309,228,250,347,227,337,298,299,185,185,331,223,284,265,351}); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| mLayoutManager = (GridLayoutManager) mGridView.getLayoutManager(); |
| |
| // test append without staggered result cache |
| scrollToEnd(mVerifyLayout); |
| |
| int[] endEdges = getEndEdges(); |
| |
| scrollToBegin(mVerifyLayout); |
| |
| verifyBeginAligned(); |
| |
| // now test append with staggered result cache |
| changeArraySize(3); |
| assertEquals("Staggerd cache should be kept as is when no item size change", |
| 100, ((StaggeredGrid) mLayoutManager.mGrid).mLocations.size()); |
| |
| changeArraySize(100); |
| |
| scrollToEnd(mVerifyLayout); |
| |
| // we should get same aligned end edges |
| int[] endEdges2 = getEndEdges(); |
| verifyEdgesSame(endEdges, endEdges2); |
| } |
| |
| |
| @Test |
| public void testLayoutWhenAViewIsInvalidated() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000); |
| intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, true); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mNumRows = 1; |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| waitOneUiCycle(); |
| |
| // push views to cache. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.mItemLengths[0] = mActivity.mItemLengths[0] * 3; |
| mActivity.mGridView.getAdapter().notifyItemChanged(0); |
| } |
| }); |
| waitForItemAnimation(); |
| |
| // notifyDataSetChange will mark the cached views FLAG_INVALID |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.mGridView.getAdapter().notifyDataSetChanged(); |
| } |
| }); |
| waitForItemAnimation(); |
| |
| // Cached views will be added in prelayout with FLAG_INVALID, in post layout we should |
| // handle it properly |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.mItemLengths[0] = mActivity.mItemLengths[0] / 3; |
| mActivity.mGridView.getAdapter().notifyItemChanged(0); |
| } |
| }); |
| |
| waitForItemAnimation(); |
| } |
| |
| @Test |
| public void testWrongInsertViewIndexInFastRelayout() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mNumRows = 1; |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| |
| // removing two children, they will be hidden views as first 2 children of RV. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setRemoveDuration(2000); |
| mActivity.removeItems(0, 2); |
| } |
| }); |
| waitForItemAnimationStart(); |
| |
| // add three views and notify change of the first item. |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, new int[]{161, 161, 161}); |
| } |
| }); |
| waitForLayout(); |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyItemChanged(0); |
| } |
| }); |
| waitForLayout(); |
| // after layout, the viewholder should still be the first child of LayoutManager. |
| assertEquals(0, mGridView.getChildAdapterPosition( |
| mGridView.getLayoutManager().getChildAt(0))); |
| } |
| |
| @Test |
| public void testMoveIntoPrelayoutItems() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mNumRows = 1; |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| |
| final int lastItemPos = mGridView.getChildCount() - 1; |
| assertTrue(mGridView.getChildCount() >= 4); |
| // notify change of 3 items, so prelayout will layout extra 3 items, then move an item |
| // into the extra layout range. Post layout's fastRelayout() should handle this properly. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyItemChanged(lastItemPos - 3); |
| mGridView.getAdapter().notifyItemChanged(lastItemPos - 2); |
| mGridView.getAdapter().notifyItemChanged(lastItemPos - 1); |
| mActivity.moveItem(900, lastItemPos + 2, true); |
| } |
| }); |
| waitForItemAnimation(); |
| } |
| |
| @Test |
| public void testMoveIntoPrelayoutItems2() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mNumRows = 1; |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| |
| setSelectedPosition(999); |
| final int firstItemPos = mGridView.getChildAdapterPosition(mGridView.getChildAt(0)); |
| assertTrue(mGridView.getChildCount() >= 4); |
| // notify change of 3 items, so prelayout will layout extra 3 items, then move an item |
| // into the extra layout range. Post layout's fastRelayout() should handle this properly. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyItemChanged(firstItemPos + 1); |
| mGridView.getAdapter().notifyItemChanged(firstItemPos + 2); |
| mGridView.getAdapter().notifyItemChanged(firstItemPos + 3); |
| mActivity.moveItem(0, firstItemPos - 2, true); |
| } |
| }); |
| waitForItemAnimation(); |
| } |
| |
| void preparePredictiveLayout() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setAddDuration(1000); |
| mGridView.getItemAnimator().setRemoveDuration(1000); |
| mGridView.getItemAnimator().setMoveDuration(1000); |
| mGridView.getItemAnimator().setChangeDuration(1000); |
| mGridView.setSelectedPositionSmooth(50); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| } |
| |
| @Test |
| public void testPredictiveLayoutAdd1() throws Throwable { |
| preparePredictiveLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(51, new int[]{300, 300, 300, 300}); |
| } |
| }); |
| waitForItemAnimationStart(); |
| waitForItemAnimation(); |
| assertEquals(50, mGridView.getSelectedPosition()); |
| assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState()); |
| } |
| |
| @Test |
| public void testPredictiveLayoutAdd2() throws Throwable { |
| preparePredictiveLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(50, new int[]{300, 300, 300, 300}); |
| } |
| }); |
| waitForItemAnimationStart(); |
| waitForItemAnimation(); |
| assertEquals(54, mGridView.getSelectedPosition()); |
| assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState()); |
| } |
| |
| @Test |
| public void testPredictiveLayoutRemove1() throws Throwable { |
| preparePredictiveLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(51, 3); |
| } |
| }); |
| waitForItemAnimationStart(); |
| waitForItemAnimation(); |
| assertEquals(50, mGridView.getSelectedPosition()); |
| assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState()); |
| } |
| |
| @Test |
| public void testPredictiveLayoutRemove2() throws Throwable { |
| preparePredictiveLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(47, 3); |
| } |
| }); |
| waitForItemAnimationStart(); |
| waitForItemAnimation(); |
| assertEquals(47, mGridView.getSelectedPosition()); |
| assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState()); |
| } |
| |
| @Test |
| public void testPredictiveLayoutRemove3() throws Throwable { |
| preparePredictiveLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(0, 51); |
| } |
| }); |
| waitForItemAnimationStart(); |
| waitForItemAnimation(); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState()); |
| } |
| |
| @Test |
| public void testPredictiveOnMeasureWrapContent() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear_wrap_content); |
| int count = 50; |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, count); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| waitForScrollIdle(mVerifyLayout); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setHasFixedSize(false); |
| } |
| }); |
| |
| for (int i = 0; i < 30; i++) { |
| final int oldCount = count; |
| final int newCount = i; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (oldCount > 0) { |
| mActivity.removeItems(0, oldCount); |
| } |
| if (newCount > 0) { |
| int[] newItems = new int[newCount]; |
| for (int i = 0; i < newCount; i++) { |
| newItems[i] = 400; |
| } |
| mActivity.addItems(0, newItems); |
| } |
| } |
| }); |
| waitForItemAnimationStart(); |
| waitForItemAnimation(); |
| count = newCount; |
| } |
| |
| } |
| |
| @Test |
| public void testPredictiveLayoutRemove4() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(50); |
| } |
| }); |
| waitForScrollIdle(); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(0, 49); |
| } |
| }); |
| assertEquals(1, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testPredictiveLayoutRemove5() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, true); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(50); |
| } |
| }); |
| waitForScrollIdle(); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(50, 40); |
| } |
| }); |
| assertEquals(50, mGridView.getSelectedPosition()); |
| scrollToBegin(mVerifyLayout); |
| verifyBeginAligned(); |
| } |
| |
| void waitOneUiCycle() throws Throwable { |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| } |
| }); |
| } |
| |
| @Test |
| public void testDontPruneMovingItem() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setMoveDuration(2000); |
| mGridView.setSelectedPosition(50); |
| } |
| }); |
| waitForScrollIdle(); |
| final ArrayList<RecyclerView.ViewHolder> moveViewHolders = new ArrayList(); |
| for (int i = 51;; i++) { |
| RecyclerView.ViewHolder vh = mGridView.findViewHolderForAdapterPosition(i); |
| if (vh == null) { |
| break; |
| } |
| moveViewHolders.add(vh); |
| } |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| // add a lot of items, so we will push everything to right of 51 out side window |
| int[] lots_items = new int[1000]; |
| for (int i = 0; i < lots_items.length; i++) { |
| lots_items[i] = 300; |
| } |
| mActivity.addItems(51, lots_items); |
| } |
| }); |
| waitOneUiCycle(); |
| // run a scroll pass, the scroll pass should not remove the animating views even they are |
| // outside visible areas. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.scrollBy(-3, 0); |
| } |
| }); |
| waitOneUiCycle(); |
| for (int i = 0; i < moveViewHolders.size(); i++) { |
| assertSame(mGridView, moveViewHolders.get(i).itemView.getParent()); |
| } |
| } |
| |
| @Test |
| public void testMoveItemToTheRight() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setAddDuration(2000); |
| mGridView.getItemAnimator().setMoveDuration(2000); |
| mGridView.setSelectedPosition(50); |
| } |
| }); |
| waitForScrollIdle(); |
| RecyclerView.ViewHolder moveViewHolder = mGridView.findViewHolderForAdapterPosition(51); |
| |
| int lastPos = mGridView.getChildAdapterPosition(mGridView.getChildAt( |
| mGridView.getChildCount() - 1)); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.moveItem(51, 1000, true); |
| } |
| }); |
| final ArrayList<View> moveInViewHolders = new ArrayList(); |
| waitForItemAnimationStart(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < mGridView.getLayoutManager().getChildCount(); i++) { |
| View v = mGridView.getLayoutManager().getChildAt(i); |
| if (mGridView.getChildAdapterPosition(v) >= 51) { |
| moveInViewHolders.add(v); |
| } |
| } |
| } |
| }); |
| waitOneUiCycle(); |
| assertTrue("prelayout should layout extra items to slide in", |
| moveInViewHolders.size() > lastPos - 51); |
| // run a scroll pass, the scroll pass should not remove the animating views even they are |
| // outside visible areas. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.scrollBy(-3, 0); |
| } |
| }); |
| waitOneUiCycle(); |
| for (int i = 0; i < moveInViewHolders.size(); i++) { |
| assertSame(mGridView, moveInViewHolders.get(i).getParent()); |
| } |
| assertSame(mGridView, moveViewHolder.itemView.getParent()); |
| assertFalse(moveViewHolder.isRecyclable()); |
| waitForItemAnimation(); |
| assertNull(moveViewHolder.itemView.getParent()); |
| assertTrue(moveViewHolder.isRecyclable()); |
| } |
| |
| @Test |
| public void testMoveItemToTheLeft() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setAddDuration(2000); |
| mGridView.getItemAnimator().setMoveDuration(2000); |
| mGridView.setSelectedPosition(1500); |
| } |
| }); |
| waitForScrollIdle(); |
| RecyclerView.ViewHolder moveViewHolder = mGridView.findViewHolderForAdapterPosition(1499); |
| |
| int firstPos = mGridView.getChildAdapterPosition(mGridView.getChildAt(0)); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.moveItem(1499, 1, true); |
| } |
| }); |
| final ArrayList<View> moveInViewHolders = new ArrayList(); |
| waitForItemAnimationStart(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < mGridView.getLayoutManager().getChildCount(); i++) { |
| View v = mGridView.getLayoutManager().getChildAt(i); |
| if (mGridView.getChildAdapterPosition(v) <= 1499) { |
| moveInViewHolders.add(v); |
| } |
| } |
| } |
| }); |
| waitOneUiCycle(); |
| assertTrue("prelayout should layout extra items to slide in ", |
| moveInViewHolders.size() > 1499 - firstPos); |
| // run a scroll pass, the scroll pass should not remove the animating views even they are |
| // outside visible areas. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.scrollBy(3, 0); |
| } |
| }); |
| waitOneUiCycle(); |
| for (int i = 0; i < moveInViewHolders.size(); i++) { |
| assertSame(mGridView, moveInViewHolders.get(i).getParent()); |
| } |
| assertSame(mGridView, moveViewHolder.itemView.getParent()); |
| assertFalse(moveViewHolder.isRecyclable()); |
| waitForItemAnimation(); |
| assertNull(moveViewHolder.itemView.getParent()); |
| assertTrue(moveViewHolder.isRecyclable()); |
| } |
| |
| @Test |
| public void testContinuousSwapForward() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(150); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| for (int i = 150; i < 199; i++) { |
| final int swapIndex = i; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.swap(swapIndex, swapIndex + 1); |
| } |
| }); |
| Thread.sleep(10); |
| } |
| waitForItemAnimation(); |
| assertEquals(199, mGridView.getSelectedPosition()); |
| // check if ItemAnimation finishes at aligned positions: |
| int leftEdge = mGridView.getLayoutManager().findViewByPosition(199).getLeft(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(leftEdge, mGridView.getLayoutManager().findViewByPosition(199).getLeft()); |
| } |
| |
| @Test |
| public void testContinuousSwapBackward() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(50); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| for (int i = 50; i > 0; i--) { |
| final int swapIndex = i; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.swap(swapIndex, swapIndex - 1); |
| } |
| }); |
| Thread.sleep(10); |
| } |
| waitForItemAnimation(); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| // check if ItemAnimation finishes at aligned positions: |
| int leftEdge = mGridView.getLayoutManager().findViewByPosition(0).getLeft(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(leftEdge, mGridView.getLayoutManager().findViewByPosition(0).getLeft()); |
| } |
| |
| void testSetSelectedPosition(final boolean inSmoothScroll, final boolean layoutRequested, |
| final boolean viewVisible, final boolean smooth, |
| final boolean resultLayoutRequested, final boolean resultSmoothScroller, |
| final int resultScrollState) throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1500); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mNumRows = 1; |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| |
| if (inSmoothScroll) { |
| setSelectedPositionSmooth(500); |
| } |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (layoutRequested) { |
| mGridView.requestLayout(); |
| } |
| final int position; |
| if (viewVisible) { |
| position = mGridView.getChildAdapterPosition(mGridView.getChildAt( |
| mGridView.getChildCount() - 1)); |
| } else { |
| position = 1000; |
| } |
| if (smooth) { |
| mGridView.setSelectedPositionSmooth(position); |
| } else { |
| mGridView.setSelectedPosition(position); |
| } |
| assertEquals("isLayoutRequested", resultLayoutRequested, |
| mGridView.isLayoutRequested()); |
| assertEquals("isSmoothScrolling", resultSmoothScroller, |
| mGridView.getLayoutManager().isSmoothScrolling()); |
| if (!resultSmoothScroller) { |
| // getScrollState() only matters when is not running smoothScroller |
| assertEquals("getScrollState", resultScrollState, |
| mGridView.getScrollState()); |
| } |
| assertEquals("isLayoutRequested", resultLayoutRequested, |
| mGridView.isLayoutRequested()); |
| } |
| }); |
| } |
| |
| @Test |
| public void testSelectedPosition01() throws Throwable { |
| testSetSelectedPosition(false, false, false, false, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition02() throws Throwable { |
| testSetSelectedPosition(false, false, false, true, |
| false, true, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition03() throws Throwable { |
| testSetSelectedPosition(false, false, true, false, |
| false, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition04() throws Throwable { |
| testSetSelectedPosition(false, false, true, true, |
| false, false, RecyclerView.SCROLL_STATE_SETTLING); |
| } |
| |
| @Test |
| public void testSelectedPosition05() throws Throwable { |
| testSetSelectedPosition(false, true, false, false, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition06() throws Throwable { |
| testSetSelectedPosition(false, true, false, true, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition07() throws Throwable { |
| testSetSelectedPosition(false, true, true, false, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition08() throws Throwable { |
| testSetSelectedPosition(false, true, true, true, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition09() throws Throwable { |
| testSetSelectedPosition(true, false, false, false, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition10() throws Throwable { |
| testSetSelectedPosition(true, false, false, true, |
| false, true, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition11() throws Throwable { |
| testSetSelectedPosition(true, false, true, false, |
| false, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition12() throws Throwable { |
| testSetSelectedPosition(true, false, true, true, |
| false, true, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition13() throws Throwable { |
| testSetSelectedPosition(true, true, false, false, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition14() throws Throwable { |
| testSetSelectedPosition(true, true, false, true, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition15() throws Throwable { |
| testSetSelectedPosition(true, true, true, false, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testSelectedPosition16() throws Throwable { |
| testSetSelectedPosition(true, true, true, true, |
| true, false, RecyclerView.SCROLL_STATE_IDLE); |
| } |
| |
| @Test |
| public void testScrollAndStuck() throws Throwable { |
| // see b/67370222 fastRelayout() may be stuck. |
| final int numItems = 19; |
| final int[] itemsLength = new int[numItems]; |
| for (int i = 0; i < numItems; i++) { |
| itemsLength[i] = 288; |
| } |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, itemsLength); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| // set left right padding to 112, space between items to be 16. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| ViewGroup.LayoutParams lp = mGridView.getLayoutParams(); |
| lp.width = 1920; |
| mGridView.setLayoutParams(lp); |
| mGridView.setPadding(112, mGridView.getPaddingTop(), 112, |
| mGridView.getPaddingBottom()); |
| mGridView.setItemSpacing(16); |
| } |
| }); |
| waitOneUiCycle(); |
| |
| int scrollPos = 0; |
| while (true) { |
| final View view = mGridView.getChildAt(mGridView.getChildCount() - 1); |
| final int pos = mGridView.getChildViewHolder(view).getAdapterPosition(); |
| if (scrollPos != pos) { |
| scrollPos = pos; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.smoothScrollToPosition(pos); |
| } |
| }); |
| } |
| // wait until we see 2nd from last: |
| if (pos >= 17) { |
| if (pos == 17) { |
| // great we can test fastRelayout() bug. |
| Thread.sleep(50); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| view.requestLayout(); |
| } |
| }); |
| } |
| break; |
| } |
| Thread.sleep(16); |
| } |
| waitForScrollIdle(); |
| } |
| |
| @Test |
| public void testSwapAfterScroll() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setMoveDuration(1000); |
| mGridView.setSelectedPositionSmooth(150); |
| } |
| }); |
| waitForScrollIdle(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(151); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| // we want to swap and select new target which is at 150 before swap |
| mGridView.setSelectedPositionSmooth(150); |
| mActivity.swap(150, 151); |
| } |
| }); |
| waitForItemAnimation(); |
| waitForScrollIdle(); |
| assertEquals(151, mGridView.getSelectedPosition()); |
| // check if ItemAnimation finishes at aligned positions: |
| int leftEdge = mGridView.getLayoutManager().findViewByPosition(151).getLeft(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(leftEdge, mGridView.getLayoutManager().findViewByPosition(151).getLeft()); |
| } |
| |
| void testScrollInSmoothScrolling(final boolean smooth, final boolean scrollToInvisible, |
| final boolean useRecyclerViewMethod) throws Throwable { |
| final int numItems = 100; |
| final int[] itemsLength = new int[numItems]; |
| for (int i = 0; i < numItems; i++) { |
| itemsLength[i] = 288; |
| } |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, itemsLength); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| // start a smoothScroller |
| final int selectedPosition = 99; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.smoothScrollToPosition(selectedPosition); |
| } |
| }); |
| Thread.sleep(50); |
| // while smoothScroller is still running, scroll to a different position |
| final int[] existing_position = new int[1]; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| existing_position[0] = mGridView.getChildAdapterPosition( |
| mGridView.getChildAt(mGridView.getChildCount() - 1)); |
| if (scrollToInvisible) { |
| existing_position[0] = existing_position[0] + 3; |
| } |
| if (useRecyclerViewMethod) { |
| if (smooth) { |
| mGridView.smoothScrollToPosition(existing_position[0]); |
| } else { |
| mGridView.scrollToPosition(existing_position[0]); |
| } |
| } else { |
| if (smooth) { |
| mGridView.setSelectedPositionSmooth(existing_position[0]); |
| } else { |
| mGridView.setSelectedPosition(existing_position[0]); |
| } |
| } |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(existing_position[0], mGridView.getSelectedPosition()); |
| assertTrue(mGridView.findViewHolderForAdapterPosition(existing_position[0]) |
| .itemView.hasFocus()); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling1() throws Throwable { |
| testScrollInSmoothScrolling(false, false, false); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling2() throws Throwable { |
| testScrollInSmoothScrolling(false, false, true); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling3() throws Throwable { |
| testScrollInSmoothScrolling(false, true, false); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling4() throws Throwable { |
| testScrollInSmoothScrolling(false, true, true); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling5() throws Throwable { |
| testScrollInSmoothScrolling(true, false, false); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling6() throws Throwable { |
| testScrollInSmoothScrolling(true, false, true); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling7() throws Throwable { |
| testScrollInSmoothScrolling(true, true, false); |
| } |
| |
| @Test |
| public void testScrollInSmoothScrolling8() throws Throwable { |
| testScrollInSmoothScrolling(true, true, true); |
| } |
| |
| @Test |
| public void testScrollAfterRequestLayout() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setHasFixedSize(false); |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffsetPercent(30); |
| } |
| }); |
| waitOneUiCycle(); |
| |
| final boolean[] scrolled = new boolean[1]; |
| mGridView.addOnScrollListener(new RecyclerView.OnScrollListener() { |
| @Override |
| public void onScrolled(RecyclerView recyclerView, int dx, int dy) { |
| if (dx != 0) scrolled[0] = true; |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| mGridView.setSelectedPosition(1); |
| } |
| }); |
| waitOneUiCycle(); |
| assertFalse(scrolled[0]); |
| } |
| |
| @Test |
| public void testScrollAfterItemAnimator() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setHasFixedSize(false); |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffsetPercent(30); |
| } |
| }); |
| waitOneUiCycle(); |
| |
| final boolean[] scrolled = new boolean[1]; |
| mGridView.addOnScrollListener(new RecyclerView.OnScrollListener() { |
| @Override |
| public void onScrolled(RecyclerView recyclerView, int dx, int dy) { |
| if (dx != 0) scrolled[0] = true; |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.changeItem(0, 10); |
| mGridView.setSelectedPosition(1); |
| } |
| }); |
| waitOneUiCycle(); |
| assertFalse(scrolled[0]); |
| } |
| |
| @Test |
| public void testItemMovedHorizontal() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(150); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.swap(150, 152); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(mVerifyLayout); |
| |
| scrollToBegin(mVerifyLayout); |
| |
| verifyBeginAligned(); |
| } |
| |
| @Test |
| public void testItemMovedHorizontalRtl() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear_rtl); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[] {40, 40, 40}); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.moveItem(0, 1, true); |
| } |
| }); |
| assertEquals(mGridView.getWidth() - mGridView.getPaddingRight(), |
| mGridView.findViewHolderForAdapterPosition(0).itemView.getRight()); |
| } |
| |
| @Test |
| public void testScrollSecondaryCannotScroll() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| final int topPadding = 2; |
| final int bottomPadding = 2; |
| final int height = mGridView.getHeight(); |
| final int spacing = 2; |
| final int rowHeight = (height - topPadding - bottomPadding) / 4 - spacing; |
| final HorizontalGridView horizontalGridView = (HorizontalGridView) mGridView; |
| |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| horizontalGridView.setPadding(0, topPadding, 0, bottomPadding); |
| horizontalGridView.setItemSpacing(spacing); |
| horizontalGridView.setNumRows(mNumRows); |
| horizontalGridView.setRowHeight(rowHeight); |
| } |
| }); |
| waitForLayout(); |
| // navigate vertically in first column, first row should always be aligned to top padding |
| for (int i = 0; i < 3; i++) { |
| setSelectedPosition(i); |
| assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(0).itemView |
| .getTop()); |
| } |
| // navigate vertically in 100th column, first row should always be aligned to top padding |
| for (int i = 300; i < 301; i++) { |
| setSelectedPosition(i); |
| assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(300).itemView |
| .getTop()); |
| } |
| } |
| |
| @Test |
| public void testScrollSecondaryNeedScroll() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| // test a lot of rows so we have to scroll vertically to reach |
| mNumRows = 9; |
| final int topPadding = 2; |
| final int bottomPadding = 2; |
| final int height = mGridView.getHeight(); |
| final int spacing = 2; |
| final int rowHeight = (height - topPadding - bottomPadding) / 4 - spacing; |
| final HorizontalGridView horizontalGridView = (HorizontalGridView) mGridView; |
| |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| horizontalGridView.setPadding(0, topPadding, 0, bottomPadding); |
| horizontalGridView.setItemSpacing(spacing); |
| horizontalGridView.setNumRows(mNumRows); |
| horizontalGridView.setRowHeight(rowHeight); |
| } |
| }); |
| waitForLayout(); |
| View view; |
| // first row should be aligned to top padding |
| setSelectedPosition(0); |
| assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(0).itemView.getTop()); |
| // middle row should be aligned to keyline (1/2 of screen height) |
| setSelectedPosition(4); |
| view = mGridView.findViewHolderForAdapterPosition(4).itemView; |
| assertEquals(height / 2, (view.getTop() + view.getBottom()) / 2); |
| // last row should be aligned to bottom padding. |
| setSelectedPosition(8); |
| view = mGridView.findViewHolderForAdapterPosition(8).itemView; |
| assertEquals(height, view.getTop() + rowHeight + bottomPadding); |
| setSelectedPositionSmooth(4); |
| waitForScrollIdle(); |
| // middle row should be aligned to keyline (1/2 of screen height) |
| setSelectedPosition(4); |
| view = mGridView.findViewHolderForAdapterPosition(4).itemView; |
| assertEquals(height / 2, (view.getTop() + view.getBottom()) / 2); |
| // first row should be aligned to top padding |
| setSelectedPositionSmooth(0); |
| waitForScrollIdle(); |
| assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(0).itemView.getTop()); |
| } |
| |
| @Test |
| public void testItemMovedVertical() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| |
| mGridView.setSelectedPositionSmooth(150); |
| waitForScrollIdle(mVerifyLayout); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.swap(150, 152); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(mVerifyLayout); |
| |
| scrollToEnd(mVerifyLayout); |
| scrollToBegin(mVerifyLayout); |
| |
| verifyBeginAligned(); |
| } |
| |
| @Test |
| public void testAddLastItemHorizontal() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread( |
| new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(49); |
| } |
| } |
| ); |
| waitForScrollIdle(mVerifyLayout); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(50, new int[]{150}); |
| } |
| }); |
| |
| // assert new added item aligned to right edge |
| assertEquals(mGridView.getWidth() - mGridView.getPaddingRight(), |
| mGridView.getLayoutManager().findViewByPosition(50).getRight()); |
| } |
| |
| @Test |
| public void testAddMultipleLastItemsHorizontal() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread( |
| new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_BOTH_EDGE); |
| mGridView.setWindowAlignmentOffsetPercent(50); |
| mGridView.setSelectedPositionSmooth(49); |
| } |
| } |
| ); |
| waitForScrollIdle(mVerifyLayout); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(50, new int[]{150, 150, 150, 150, 150, 150, 150, 150, 150, |
| 150, 150, 150, 150, 150}); |
| } |
| }); |
| |
| // The focused item will be at center of window |
| View view = mGridView.getLayoutManager().findViewByPosition(49); |
| assertEquals(mGridView.getWidth() / 2, (view.getLeft() + view.getRight()) / 2); |
| } |
| |
| @Test |
| public void testItemAddRemoveHorizontal() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| scrollToEnd(mVerifyLayout); |
| int[] endEdges = getEndEdges(); |
| |
| mGridView.setSelectedPositionSmooth(150); |
| waitForScrollIdle(mVerifyLayout); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mRemovedItems = mActivity.removeItems(151, 4); |
| } |
| }); |
| |
| scrollToEnd(mVerifyLayout); |
| mGridView.setSelectedPositionSmooth(150); |
| waitForScrollIdle(mVerifyLayout); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(151, mRemovedItems); |
| } |
| }); |
| scrollToEnd(mVerifyLayout); |
| |
| // we should get same aligned end edges |
| int[] endEdges2 = getEndEdges(); |
| verifyEdgesSame(endEdges, endEdges2); |
| |
| scrollToBegin(mVerifyLayout); |
| verifyBeginAligned(); |
| } |
| |
| @Test |
| public void testSetSelectedPositionDetached() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int focusToIndex = 49; |
| final ViewGroup parent = (ViewGroup) mGridView.getParent(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| parent.removeView(mGridView); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| parent.addView(mGridView); |
| mGridView.requestFocus(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(mGridView.getSelectedPosition(), focusToIndex); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(focusToIndex).hasFocus()); |
| |
| final int focusToIndex2 = 0; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| parent.removeView(mGridView); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPosition(focusToIndex2); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| parent.addView(mGridView); |
| mGridView.requestFocus(); |
| } |
| }); |
| assertEquals(mGridView.getSelectedPosition(), focusToIndex2); |
| waitForScrollIdle(); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(focusToIndex2).hasFocus()); |
| } |
| |
| @Test |
| public void testBug22209986() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int focusToIndex = mGridView.getChildCount() - 1; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex); |
| } |
| }); |
| |
| waitForScrollIdle(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex + 1); |
| } |
| }); |
| // let the scroll running for a while and requestLayout during scroll |
| Thread.sleep(80); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| assertEquals(mGridView.getScrollState(), BaseGridView.SCROLL_STATE_SETTLING); |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| |
| int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft(); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(leftEdge, |
| mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft()); |
| } |
| |
| void testScrollAndRemove(int[] itemsLength, int numItems) throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| if (itemsLength != null) { |
| intent.putExtra(GridActivity.EXTRA_ITEMS, itemsLength); |
| } else { |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| } |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int focusToIndex = mGridView.getChildCount() - 1; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex); |
| } |
| }); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(focusToIndex, 1); |
| } |
| }); |
| |
| waitOneUiCycle(); |
| waitForScrollIdle(); |
| int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft(); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(leftEdge, |
| mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft(), DELTA); |
| } |
| |
| @Test |
| public void testScrollAndRemove() throws Throwable { |
| // test random lengths for 50 items |
| testScrollAndRemove(null, 50); |
| } |
| |
| /** |
| * This test verifies if scroll limits are ignored when onLayoutChildren compensate remaining |
| * scroll distance. b/64931938 |
| * In the test, second child is long, other children are short. |
| * Test scrolls to the long child, and when scrolling, remove the long child. We made it long |
| * to have enough remaining scroll distance when the layout pass kicks in. |
| * The onLayoutChildren() would compensate the remaining scroll distance, moving all items |
| * toward right, which will make the first item's left edge bigger than left padding, |
| * which would violate the "scroll limit of left" in a regular scroll case, but |
| * in layout pass, we still honor that scroll request, ignoring the scroll limit. |
| */ |
| @Test |
| public void testScrollAndRemoveSample1() throws Throwable { |
| DisplayMetrics dm = InstrumentationRegistry.getInstrumentation().getTargetContext() |
| .getResources().getDisplayMetrics(); |
| // screen width for long item and 4DP for other items |
| int longItemLength = dm.widthPixels; |
| int shortItemLength = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm); |
| int[] items = new int[1000]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = shortItemLength; |
| } |
| items[1] = longItemLength; |
| testScrollAndRemove(items, 0); |
| } |
| |
| @Test |
| public void testScrollAndInsert() throws Throwable { |
| testScrollAndInsert(3); |
| } |
| |
| @Test |
| public void testScrollAndInsertAlot() throws Throwable { |
| testScrollAndInsert(20); |
| } |
| |
| public void testScrollAndInsert(int insertedItems) throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| int[] items = new int[1000]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300 + (int)(Math.random() * 100); |
| } |
| final int[] newItems = new int[insertedItems]; |
| for (int i = 0; i < insertedItems; i++) { |
| newItems[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, true); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(150); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| |
| View view = mGridView.getChildAt(mGridView.getChildCount() - 1); |
| final int focusToIndex = mGridView.getChildAdapterPosition(view); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex); |
| } |
| }); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, newItems); |
| } |
| }); |
| waitForScrollIdle(); |
| int newFocusToIndex = focusToIndex + insertedItems; |
| assertEquals(newFocusToIndex, mGridView.getSelectedPosition()); |
| int topEdge = mGridView.getLayoutManager().findViewByPosition(newFocusToIndex).getTop(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(topEdge, |
| mGridView.getLayoutManager().findViewByPosition(newFocusToIndex).getTop()); |
| } |
| |
| @Test |
| public void testScrollAndInsertBeforeVisibleItem() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| int[] items = new int[1000]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300 + (int)(Math.random() * 100); |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, true); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(150); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| |
| View view = mGridView.getChildAt(mGridView.getChildCount() - 1); |
| final int focusToIndex = mGridView.getChildAdapterPosition(view); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex); |
| } |
| }); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| int[] newItems = new int[]{300, 300, 300}; |
| mActivity.addItems(focusToIndex, newItems); |
| } |
| }); |
| } |
| |
| @Test |
| public void testSmoothScrollAndRemove() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 300); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int focusToIndex = 200; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex); |
| } |
| }); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(focusToIndex, 1); |
| } |
| }); |
| |
| assertTrue("removing the index of not attached child should not affect smooth scroller", |
| mGridView.getLayoutManager().isSmoothScrolling()); |
| waitForScrollIdle(); |
| int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft(); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(leftEdge, |
| mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft()); |
| } |
| |
| @Test |
| public void testSmoothScrollAndRemove2() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 300); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int focusToIndex = 200; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusToIndex); |
| } |
| }); |
| |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| final int removeIndex = mGridView.getChildViewHolder( |
| mGridView.getChildAt(mGridView.getChildCount() - 1)).getAdapterPosition(); |
| mActivity.removeItems(removeIndex, 1); |
| } |
| }); |
| waitForLayout(); |
| |
| assertTrue("removing the index of attached child should not kill smooth scroller", |
| mGridView.getLayoutManager().isSmoothScrolling()); |
| waitForItemAnimation(); |
| waitForScrollIdle(); |
| int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft(); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(leftEdge, |
| mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft()); |
| } |
| |
| void testRemoveVisibleItemsInSmoothScrollingForward(final boolean focusOnGridView) |
| throws Throwable { |
| final int numItems = 200; |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| final View button = mActivity.findViewById(R.id.button); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (focusOnGridView) { |
| mGridView.requestFocus(); |
| } else { |
| button.requestFocus(); |
| } |
| mGridView.setSelectedPositionSmooth(numItems - 1); |
| } |
| }); |
| waitOneUiCycle(); |
| final int numRemoved = 4; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| int position = mGridView.getChildAdapterPosition(mGridView.getChildAt(0)); |
| mActivity.removeItems(position, numRemoved); |
| } |
| }); |
| |
| waitOneUiCycle(); |
| waitForScrollIdle(); |
| assertTrue("Should not keep lots of views", mGridView.getChildCount() < numItems / 2); |
| assertEquals(mGridView.getSelectedPosition(), numItems - 1 - numRemoved); |
| if (focusOnGridView) { |
| assertTrue("GridView should retain focus", mGridView.hasFocus()); |
| assertFalse("Gridview should pass focus to its child", mGridView.isFocused()); |
| } else { |
| assertTrue("button should has focus", button.hasFocus()); |
| } |
| } |
| |
| void testRemoveVisibleItemsInSmoothScrollingBackward(final boolean focusOnGridView) |
| throws Throwable { |
| final int numItems = 200; |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| final View button = mActivity.findViewById(R.id.button); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPosition(numItems - 1); |
| } |
| }); |
| waitOneUiCycle(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (focusOnGridView) { |
| mGridView.requestFocus(); |
| } else { |
| button.requestFocus(); |
| } |
| mGridView.setSelectedPositionSmooth(0); |
| } |
| }); |
| waitOneUiCycle(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| int position = mGridView.getChildAdapterPosition(mGridView.getChildAt(0)); |
| int numRemoved = numItems - 1 - position; |
| mActivity.removeItems(position, numRemoved); |
| } |
| }); |
| |
| waitOneUiCycle(); |
| waitForScrollIdle(); |
| assertTrue("Should not keep lots of views", mGridView.getChildCount() < numItems / 2); |
| assertEquals(mGridView.getSelectedPosition(), 0); |
| if (focusOnGridView) { |
| assertTrue("GridView should retain focus", mGridView.hasFocus()); |
| assertFalse("Gridview should pass focus to its child", mGridView.isFocused()); |
| } else { |
| assertTrue("button should has focus", button.hasFocus()); |
| } |
| } |
| |
| @Test |
| public void testRemoveVisibleItemsInSmoothScrollingForwardWithFocus() throws Throwable { |
| testRemoveVisibleItemsInSmoothScrollingForward(/*focusOnGridView=*/ true); |
| } |
| |
| @Test |
| public void testRemoveVisibleItemsInSmoothScrollingForwardWithoutFocus() throws Throwable { |
| testRemoveVisibleItemsInSmoothScrollingForward(/*focusOnGridView=*/ false); |
| } |
| |
| @Test |
| public void testRemoveVisibleItemsInSmoothScrollingBackwardWithFocus() throws Throwable { |
| testRemoveVisibleItemsInSmoothScrollingBackward(/*focusOnGridView=*/ true); |
| } |
| |
| @Test |
| public void testRemoveVisibleItemsInSmoothScrollingBackwardWithoutFocus() throws Throwable { |
| testRemoveVisibleItemsInSmoothScrollingBackward(/*focusOnGridView=*/ false); |
| } |
| |
| @Test |
| public void testPendingSmoothScrollAndRemove() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 630 + (int)(Math.random() * 100); |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, true); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mGridView.setSelectedPositionSmooth(0); |
| waitForScrollIdle(mVerifyLayout); |
| assertTrue(mGridView.getChildAt(0).hasFocus()); |
| |
| // Pressing lots of key to make sure smooth scroller is running |
| mGridView.mLayoutManager.mMaxPendingMoves = 100; |
| for (int i = 0; i < 100; i++) { |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| } |
| |
| assertTrue(mGridView.getLayoutManager().isSmoothScrolling()); |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| final int removeIndex = mGridView.getChildViewHolder( |
| mGridView.getChildAt(mGridView.getChildCount() - 1)).getAdapterPosition(); |
| mActivity.removeItems(removeIndex, 1); |
| } |
| }); |
| waitForLayout(); |
| |
| assertTrue("removing the index of attached child should not kill smooth scroller", |
| mGridView.getLayoutManager().isSmoothScrolling()); |
| |
| waitForItemAnimation(); |
| waitForScrollIdle(); |
| int focusIndex = mGridView.getSelectedPosition(); |
| int topEdge = mGridView.getLayoutManager().findViewByPosition(focusIndex).getTop(); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| } |
| }); |
| waitForScrollIdle(); |
| assertEquals(topEdge, |
| mGridView.getLayoutManager().findViewByPosition(focusIndex).getTop()); |
| } |
| |
| @Test |
| public void testFocusToFirstItem() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mRemovedItems = mActivity.removeItems(0, 200); |
| } |
| }); |
| |
| humanDelay(500); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, mRemovedItems); |
| } |
| }); |
| |
| humanDelay(500); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(0).hasFocus()); |
| |
| changeArraySize(0); |
| |
| changeArraySize(200); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(0).hasFocus()); |
| } |
| |
| @Test |
| public void testNonFocusableHorizontal() throws Throwable { |
| final int numItems = 200; |
| final int startPos = 45; |
| final int skips = 20; |
| final int numColumns = 3; |
| final int endPos = startPos + numColumns * (skips + 1); |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = numColumns; |
| boolean[] focusable = new boolean[numItems]; |
| for (int i = 0; i < focusable.length; i++) { |
| focusable[i] = true; |
| } |
| for (int i = startPos + mNumRows, j = 0; j < skips; i += mNumRows, j++) { |
| focusable[i] = false; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| mGridView.setSelectedPositionSmooth(startPos); |
| waitForScrollIdle(mVerifyLayout); |
| |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| sendKey(KeyEvent.KEYCODE_DPAD_LEFT); |
| } else { |
| sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); |
| } |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(endPos, mGridView.getSelectedPosition()); |
| |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); |
| } else { |
| sendKey(KeyEvent.KEYCODE_DPAD_LEFT); |
| } |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(startPos, mGridView.getSelectedPosition()); |
| |
| } |
| |
| @Test |
| public void testNoInitialFocusable() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| final int numItems = 100; |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| boolean[] focusable = new boolean[numItems]; |
| final int firstFocusableIndex = 10; |
| for (int i = 0; i < firstFocusableIndex; i++) { |
| focusable[i] = false; |
| } |
| for (int i = firstFocusableIndex; i < focusable.length; i++) { |
| focusable[i] = true; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| assertTrue(mGridView.isFocused()); |
| |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| sendKey(KeyEvent.KEYCODE_DPAD_LEFT); |
| } else { |
| sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); |
| } |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(firstFocusableIndex, mGridView.getSelectedPosition()); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(firstFocusableIndex).hasFocus()); |
| } |
| |
| @Test |
| public void testFocusOutOfEmptyListView() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| final int numItems = 100; |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| initActivity(intent); |
| |
| final View horizontalGridView = new HorizontalGridViewEx(mGridView.getContext()); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| horizontalGridView.setFocusable(true); |
| horizontalGridView.setFocusableInTouchMode(true); |
| horizontalGridView.setLayoutParams(new ViewGroup.LayoutParams(100, 100)); |
| ((ViewGroup) mGridView.getParent()).addView(horizontalGridView, 0); |
| horizontalGridView.requestFocus(); |
| } |
| }); |
| |
| assertTrue(horizontalGridView.isFocused()); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| |
| assertTrue(mGridView.hasFocus()); |
| } |
| |
| @Test |
| public void testTransferFocusToChildWhenGainFocus() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| final int numItems = 100; |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| boolean[] focusable = new boolean[numItems]; |
| final int firstFocusableIndex = 1; |
| for (int i = 0; i < firstFocusableIndex; i++) { |
| focusable[i] = false; |
| } |
| for (int i = firstFocusableIndex; i < focusable.length; i++) { |
| focusable[i] = true; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| assertEquals(firstFocusableIndex, mGridView.getSelectedPosition()); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(firstFocusableIndex).hasFocus()); |
| } |
| |
| @Test |
| public void testFocusFromSecondChild() throws Throwable { |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| final int numItems = 100; |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| boolean[] focusable = new boolean[numItems]; |
| for (int i = 0; i < focusable.length; i++) { |
| focusable[i] = false; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| // switching Adapter to cause a full rebind, test if it will focus to second item. |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.mNumItems = numItems; |
| mActivity.mItemFocusables[1] = true; |
| mActivity.rebindToNewAdapter(); |
| } |
| }); |
| assertTrue(mGridView.findViewHolderForAdapterPosition(1).itemView.hasFocus()); |
| } |
| |
| @Test |
| public void removeFocusableItemAndFocusableRecyclerViewGetsFocus() throws Throwable { |
| final int numItems = 100; |
| final int numColumns = 3; |
| final int focusableIndex = 2; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = numColumns; |
| boolean[] focusable = new boolean[numItems]; |
| for (int i = 0; i < focusable.length; i++) { |
| focusable[i] = false; |
| } |
| focusable[focusableIndex] = true; |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(focusableIndex); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(focusableIndex, mGridView.getSelectedPosition()); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(focusableIndex, 1); |
| } |
| }); |
| assertTrue(dumpGridView(mGridView), mGridView.isFocused()); |
| } |
| |
| @Test |
| public void removeFocusableItemAndUnFocusableRecyclerViewLosesFocus() throws Throwable { |
| final int numItems = 100; |
| final int numColumns = 3; |
| final int focusableIndex = 2; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = numColumns; |
| boolean[] focusable = new boolean[numItems]; |
| for (int i = 0; i < focusable.length; i++) { |
| focusable[i] = false; |
| } |
| focusable[focusableIndex] = true; |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setFocusableInTouchMode(false); |
| mGridView.setFocusable(false); |
| mGridView.setSelectedPositionSmooth(focusableIndex); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(focusableIndex, mGridView.getSelectedPosition()); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(focusableIndex, 1); |
| } |
| }); |
| assertFalse(dumpGridView(mGridView), mGridView.hasFocus()); |
| } |
| |
| @Test |
| public void testNonFocusableVertical() throws Throwable { |
| final int numItems = 200; |
| final int startPos = 44; |
| final int skips = 20; |
| final int numColumns = 3; |
| final int endPos = startPos + numColumns * (skips + 1); |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = numColumns; |
| boolean[] focusable = new boolean[numItems]; |
| for (int i = 0; i < focusable.length; i++) { |
| focusable[i] = true; |
| } |
| for (int i = startPos + mNumRows, j = 0; j < skips; i += mNumRows, j++) { |
| focusable[i] = false; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| mGridView.setSelectedPositionSmooth(startPos); |
| waitForScrollIdle(mVerifyLayout); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(endPos, mGridView.getSelectedPosition()); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_UP); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(startPos, mGridView.getSelectedPosition()); |
| |
| } |
| |
| @Test |
| public void testLtrFocusOutStartDisabled() throws Throwable { |
| final int numItems = 200; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_grid_ltr); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 2; |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestFocus(); |
| mGridView.setSelectedPositionSmooth(0); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_LEFT); |
| waitForScrollIdle(mVerifyLayout); |
| assertTrue(mGridView.hasFocus()); |
| } |
| |
| @Test |
| public void testVerticalGridRtl() throws Throwable { |
| final int numItems = 200; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_grid_rtl); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 2; |
| initActivity(intent); |
| |
| waitForScrollIdle(mVerifyLayout); |
| |
| View item0 = mGridView.findViewHolderForAdapterPosition(0).itemView; |
| View item1 = mGridView.findViewHolderForAdapterPosition(1).itemView; |
| assertEquals(mGridView.getWidth() - mGridView.getPaddingRight(), item0.getRight()); |
| assertEquals(item0.getLeft(), item1.getRight() + mGridView.getHorizontalSpacing()); |
| } |
| |
| @Test |
| public void testRtlFocusOutStartDisabled() throws Throwable { |
| final int numItems = 200; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_grid_rtl); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestFocus(); |
| mGridView.setSelectedPositionSmooth(0); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); |
| waitForScrollIdle(mVerifyLayout); |
| assertTrue(mGridView.hasFocus()); |
| } |
| |
| @Test |
| public void testTransferFocusable() throws Throwable { |
| final int numItems = 200; |
| final int numColumns = 3; |
| final int startPos = 1; |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = numColumns; |
| boolean[] focusable = new boolean[numItems]; |
| for (int i = 0; i < focusable.length; i++) { |
| focusable[i] = true; |
| } |
| for (int i = 0; i < startPos; i++) { |
| focusable[i] = false; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| changeArraySize(0); |
| assertTrue(mGridView.isFocused()); |
| |
| changeArraySize(numItems); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(startPos).hasFocus()); |
| } |
| |
| @Test |
| public void testTransferFocusable2() throws Throwable { |
| final int numItems = 200; |
| final int numColumns = 3; |
| final int startPos = 3; // make sure view at startPos is in visible area. |
| |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, true); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = numColumns; |
| boolean[] focusable = new boolean[numItems]; |
| for (int i = 0; i < focusable.length; i++) { |
| focusable[i] = true; |
| } |
| for (int i = 0; i < startPos; i++) { |
| focusable[i] = false; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable); |
| initActivity(intent); |
| |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(startPos).hasFocus()); |
| |
| changeArraySize(0); |
| assertTrue(mGridView.isFocused()); |
| |
| changeArraySize(numItems); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(startPos).hasFocus()); |
| } |
| |
| @Test |
| public void testNonFocusableLoseInFastLayout() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| int[] items = new int[300]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 480; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| int pressDown = 15; |
| |
| initActivity(intent); |
| |
| mGridView.setSelectedPositionSmooth(0); |
| waitForScrollIdle(mVerifyLayout); |
| |
| for (int i = 0; i < pressDown; i++) { |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| } |
| waitForScrollIdle(mVerifyLayout); |
| assertFalse(mGridView.isFocused()); |
| |
| } |
| |
| @Test |
| public void testFocusableViewAvailable() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 0); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, |
| new boolean[]{false, false, true, false, false}); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| // RecyclerView does not respect focusable and focusableInTouchMode flag, so |
| // set flags in code. |
| mGridView.setFocusableInTouchMode(false); |
| mGridView.setFocusable(false); |
| } |
| }); |
| |
| assertFalse(mGridView.isFocused()); |
| |
| final boolean[] scrolled = new boolean[]{false}; |
| mGridView.addOnScrollListener(new RecyclerView.OnScrollListener() { |
| @Override |
| public void onScrolled(RecyclerView recyclerView, int dx, int dy){ |
| if (dy > 0) { |
| scrolled[0] = true; |
| } |
| } |
| }); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, new int[]{200, 300, 500, 500, 200}); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| |
| assertFalse("GridView should not be scrolled", scrolled[0]); |
| assertTrue(mGridView.getLayoutManager().findViewByPosition(2).hasFocus()); |
| |
| } |
| |
| @Test |
| public void testSetSelectionWithDelta() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 300); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(3); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| int top1 = mGridView.getLayoutManager().findViewByPosition(3).getTop(); |
| |
| humanDelay(1000); |
| |
| // scroll to position with delta |
| setSelectedPosition(3, 100); |
| int top2 = mGridView.getLayoutManager().findViewByPosition(3).getTop(); |
| assertEquals(top1 - 100, top2); |
| |
| // scroll to same position without delta, it will be reset |
| setSelectedPosition(3, 0); |
| int top3 = mGridView.getLayoutManager().findViewByPosition(3).getTop(); |
| assertEquals(top1, top3); |
| |
| // scroll invisible item after last visible item |
| final int lastVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager()) |
| .mGrid.getLastVisibleIndex(); |
| setSelectedPosition(lastVisiblePos + 1, 100); |
| int top4 = mGridView.getLayoutManager().findViewByPosition(lastVisiblePos + 1).getTop(); |
| assertEquals(top1 - 100, top4); |
| |
| // scroll invisible item before first visible item |
| final int firstVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager()) |
| .mGrid.getFirstVisibleIndex(); |
| setSelectedPosition(firstVisiblePos - 1, 100); |
| int top5 = mGridView.getLayoutManager().findViewByPosition(firstVisiblePos - 1).getTop(); |
| assertEquals(top1 - 100, top5); |
| |
| // scroll to invisible item that is far away. |
| setSelectedPosition(50, 100); |
| int top6 = mGridView.getLayoutManager().findViewByPosition(50).getTop(); |
| assertEquals(top1 - 100, top6); |
| |
| // scroll to invisible item that is far away. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(100); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| int top7 = mGridView.getLayoutManager().findViewByPosition(100).getTop(); |
| assertEquals(top1, top7); |
| |
| // scroll to invisible item that is far away. |
| setSelectedPosition(10, 50); |
| int top8 = mGridView.getLayoutManager().findViewByPosition(10).getTop(); |
| assertEquals(top1 - 50, top8); |
| } |
| |
| @Test |
| public void testSetSelectionWithDeltaInGrid() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 500); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, true); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(10); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| int top1 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10)); |
| |
| humanDelay(500); |
| |
| // scroll to position with delta |
| setSelectedPosition(20, 100); |
| int top2 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20)); |
| assertEquals(top1 - 100, top2); |
| |
| // scroll to same position without delta, it will be reset |
| setSelectedPosition(20, 0); |
| int top3 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20)); |
| assertEquals(top1, top3); |
| |
| // scroll invisible item after last visible item |
| final int lastVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager()) |
| .mGrid.getLastVisibleIndex(); |
| setSelectedPosition(lastVisiblePos + 1, 100); |
| int top4 = getCenterY(mGridView.getLayoutManager().findViewByPosition(lastVisiblePos + 1)); |
| verifyMargin(); |
| assertEquals(top1 - 100, top4); |
| |
| // scroll invisible item before first visible item |
| final int firstVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager()) |
| .mGrid.getFirstVisibleIndex(); |
| setSelectedPosition(firstVisiblePos - 1, 100); |
| int top5 = getCenterY(mGridView.getLayoutManager().findViewByPosition(firstVisiblePos - 1)); |
| assertEquals(top1 - 100, top5); |
| |
| // scroll to invisible item that is far away. |
| setSelectedPosition(100, 100); |
| int top6 = getCenterY(mGridView.getLayoutManager().findViewByPosition(100)); |
| assertEquals(top1 - 100, top6); |
| |
| // scroll to invisible item that is far away. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(200); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| Thread.sleep(500); |
| int top7 = getCenterY(mGridView.getLayoutManager().findViewByPosition(200)); |
| assertEquals(top1, top7); |
| |
| // scroll to invisible item that is far away. |
| setSelectedPosition(10, 50); |
| int top8 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10)); |
| assertEquals(top1 - 50, top8); |
| } |
| |
| |
| @Test |
| public void testSetSelectionWithDeltaInGrid1() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{ |
| 193,176,153,141,203,184,232,139,177,206,222,136,132,237,172,137, |
| 188,172,163,213,158,219,209,147,133,229,170,197,138,215,188,205, |
| 223,192,225,170,195,127,229,229,210,195,134,142,160,139,130,222, |
| 150,163,180,176,157,137,234,169,159,167,182,150,224,231,202,236, |
| 123,140,181,223,120,185,183,221,123,210,134,158,166,208,149,128, |
| 192,214,212,198,133,140,158,133,229,173,226,141,180,128,127,218, |
| 192,235,183,213,216,150,143,193,125,141,219,210,195,195,192,191, |
| 212,236,157,189,160,220,147,158,220,199,233,231,201,180,168,141, |
| 156,204,191,183,190,153,123,210,238,151,139,221,223,200,175,191, |
| 132,184,197,204,236,157,230,151,195,219,212,143,172,149,219,184, |
| 164,211,132,187,172,142,174,146,127,147,206,238,188,129,199,226, |
| 132,220,210,159,235,153,208,182,196,123,180,159,131,135,175,226, |
| 127,134,237,211,133,225,132,124,160,226,224,200,173,137,217,169, |
| 182,183,176,185,122,168,195,159,172,129,126,129,166,136,149,220, |
| 178,191,192,238,180,208,234,154,222,206,239,228,129,140,203,125, |
| 214,175,125,169,196,132,234,138,192,142,234,190,215,232,239,122, |
| 188,158,128,221,159,237,207,157,232,138,132,214,122,199,121,191, |
| 199,209,126,164,175,187,173,186,194,224,191,196,146,208,213,210, |
| 164,176,202,213,123,157,179,138,217,129,186,166,237,211,157,130, |
| 137,132,171,232,216,239,180,151,137,132,190,133,218,155,171,227, |
| 193,147,197,164,120,218,193,154,170,196,138,222,161,235,143,154, |
| 192,178,228,195,178,133,203,178,173,206,178,212,136,157,169,124, |
| 172,121,128,223,238,125,217,187,184,156,169,215,231,124,210,174, |
| 146,226,185,134,223,228,183,182,136,133,199,146,180,233,226,225, |
| 174,233,145,235,216,170,192,171,132,132,134,223,233,148,154,162, |
| 192,179,197,203,139,197,174,187,135,132,180,136,192,195,124,221, |
| 120,189,233,233,146,225,234,163,215,143,132,198,156,205,151,190, |
| 204,239,221,229,123,138,134,217,219,136,218,215,167,139,195,125, |
| 202,225,178,226,145,208,130,194,228,197,157,215,124,147,174,123, |
| 237,140,172,181,161,151,229,216,199,199,179,213,146,122,222,162, |
| 139,173,165,150,160,217,207,137,165,175,129,158,134,133,178,199, |
| 215,213,122,197 |
| }); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, true); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(10); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| int top1 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10)); |
| |
| humanDelay(500); |
| |
| // scroll to position with delta |
| setSelectedPosition(20, 100); |
| int top2 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20)); |
| assertEquals(top1 - 100, top2); |
| |
| // scroll to same position without delta, it will be reset |
| setSelectedPosition(20, 0); |
| int top3 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20)); |
| assertEquals(top1, top3); |
| |
| // scroll invisible item after last visible item |
| final int lastVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager()) |
| .mGrid.getLastVisibleIndex(); |
| setSelectedPosition(lastVisiblePos + 1, 100); |
| int top4 = getCenterY(mGridView.getLayoutManager().findViewByPosition(lastVisiblePos + 1)); |
| verifyMargin(); |
| assertEquals(top1 - 100, top4); |
| |
| // scroll invisible item before first visible item |
| final int firstVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager()) |
| .mGrid.getFirstVisibleIndex(); |
| setSelectedPosition(firstVisiblePos - 1, 100); |
| int top5 = getCenterY(mGridView.getLayoutManager().findViewByPosition(firstVisiblePos - 1)); |
| assertEquals(top1 - 100, top5); |
| |
| // scroll to invisible item that is far away. |
| setSelectedPosition(100, 100); |
| int top6 = getCenterY(mGridView.getLayoutManager().findViewByPosition(100)); |
| assertEquals(top1 - 100, top6); |
| |
| // scroll to invisible item that is far away. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(200); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| Thread.sleep(500); |
| int top7 = getCenterY(mGridView.getLayoutManager().findViewByPosition(200)); |
| assertEquals(top1, top7); |
| |
| // scroll to invisible item that is far away. |
| setSelectedPosition(10, 50); |
| int top8 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10)); |
| assertEquals(top1 - 50, top8); |
| } |
| |
| @Test |
| public void testSmoothScrollSelectionEvents() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 500); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(30); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| humanDelay(500); |
| |
| final ArrayList<Integer> selectedPositions = new ArrayList<Integer>(); |
| mGridView.setOnChildSelectedListener(new OnChildSelectedListener() { |
| @Override |
| public void onChildSelected(ViewGroup parent, View view, int position, long id) { |
| selectedPositions.add(position); |
| } |
| }); |
| |
| sendRepeatedKeys(100, KeyEvent.KEYCODE_DPAD_UP); |
| humanDelay(500); |
| waitForScrollIdle(mVerifyLayout); |
| // should only get childselected event for item 0 once |
| assertTrue(selectedPositions.size() > 0); |
| assertEquals(0, selectedPositions.get(selectedPositions.size() - 1).intValue()); |
| for (int i = selectedPositions.size() - 2; i >= 0; i--) { |
| assertFalse(0 == selectedPositions.get(i).intValue()); |
| } |
| |
| } |
| |
| @Test |
| public void testSmoothScrollSelectionEventsLinear() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 500); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(10); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| humanDelay(500); |
| |
| final ArrayList<Integer> selectedPositions = new ArrayList<Integer>(); |
| mGridView.setOnChildSelectedListener(new OnChildSelectedListener() { |
| @Override |
| public void onChildSelected(ViewGroup parent, View view, int position, long id) { |
| selectedPositions.add(position); |
| } |
| }); |
| |
| sendRepeatedKeys(100, KeyEvent.KEYCODE_DPAD_UP); |
| humanDelay(500); |
| waitForScrollIdle(mVerifyLayout); |
| // should only get childselected event for item 0 once |
| assertTrue(selectedPositions.size() > 0); |
| assertEquals(0, selectedPositions.get(selectedPositions.size() - 1).intValue()); |
| for (int i = selectedPositions.size() - 2; i >= 0; i--) { |
| assertFalse(0 == selectedPositions.get(i).intValue()); |
| } |
| |
| } |
| |
| @Test |
| public void testScrollToNoneExisting() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 3; |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(99); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| humanDelay(500); |
| |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(50); |
| } |
| }); |
| Thread.sleep(100); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestLayout(); |
| mGridView.setSelectedPositionSmooth(0); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| humanDelay(500); |
| |
| } |
| |
| @Test |
| public void testSmoothscrollerInterrupted() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 680; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mGridView.setSelectedPositionSmooth(0); |
| waitForScrollIdle(mVerifyLayout); |
| assertTrue(mGridView.getChildAt(0).hasFocus()); |
| |
| // Pressing lots of key to make sure smooth scroller is running |
| for (int i = 0; i < 20; i++) { |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| } |
| while (mGridView.getLayoutManager().isSmoothScrolling() |
| || mGridView.getScrollState() != BaseGridView.SCROLL_STATE_IDLE) { |
| // Repeatedly pressing to make sure pending keys does not drop to zero. |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| } |
| } |
| |
| @Test |
| public void testSmoothscrollerCancelled() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 680; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mGridView.setSelectedPositionSmooth(0); |
| waitForScrollIdle(mVerifyLayout); |
| assertTrue(mGridView.getChildAt(0).hasFocus()); |
| |
| int targetPosition = items.length - 1; |
| mGridView.setSelectedPositionSmooth(targetPosition); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.stopScroll(); |
| } |
| }); |
| waitForScrollIdle(); |
| waitForItemAnimation(); |
| assertEquals(mGridView.getSelectedPosition(), targetPosition); |
| assertSame(mGridView.getLayoutManager().findViewByPosition(targetPosition), |
| mGridView.findFocus()); |
| } |
| |
| @Test |
| public void testSetNumRowsAndAddItem() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| final int[] items = new int[2]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mGridView.setSelectedPositionSmooth(0); |
| waitForScrollIdle(mVerifyLayout); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(items.length, new int[]{300}); |
| } |
| }); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| ((VerticalGridView) mGridView).setNumColumns(2); |
| } |
| }); |
| Thread.sleep(1000); |
| assertTrue(mGridView.getChildAt(2).getLeft() != mGridView.getChildAt(1).getLeft()); |
| } |
| |
| |
| @Test |
| public void testRequestLayoutBugInLayout() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(1); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_UP); |
| waitForScrollIdle(mVerifyLayout); |
| |
| assertEquals("Line 2", ((TextView) mGridView.findFocus()).getText().toString()); |
| } |
| |
| |
| @Test |
| public void testChangeLayoutInChild() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_wrap_content); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true); |
| int[] items = new int[2]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(0); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| verifyMargin(); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(1); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| verifyMargin(); |
| } |
| |
| @Test |
| public void testWrapContent() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_grid_wrap); |
| int[] items = new int[200]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.attachToNewAdapter(new int[0]); |
| } |
| }); |
| |
| } |
| |
| @Test |
| public void testZeroFixedSecondarySize() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_measured_with_zero); |
| intent.putExtra(GridActivity.EXTRA_SECONDARY_SIZE_ZERO, true); |
| int[] items = new int[2]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 0; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| } |
| |
| @Test |
| public void testChildStates() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 200; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.selectable_text_view); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| mGridView.setSaveChildrenPolicy(VerticalGridView.SAVE_ALL_CHILD); |
| |
| final SparseArray<Parcelable> container = new SparseArray<Parcelable>(); |
| |
| // 1 Save view states |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(0)) |
| .getText()), 0, 1); |
| Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(1)) |
| .getText()), 0, 1); |
| mGridView.saveHierarchyState(container); |
| } |
| }); |
| |
| // 2 Change view states |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(0)) |
| .getText()), 1, 2); |
| Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(1)) |
| .getText()), 1, 2); |
| } |
| }); |
| |
| // 3 Detached and re-attached, should still maintain state of (2) |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(1); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionStart(), 1); |
| assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionEnd(), 2); |
| assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionStart(), 1); |
| assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionEnd(), 2); |
| |
| // 4 Recycled and rebound, should load state from (2) |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(20); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPositionSmooth(0); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionStart(), 1); |
| assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionEnd(), 2); |
| assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionStart(), 1); |
| assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionEnd(), 2); |
| } |
| |
| |
| @Test |
| public void testNoDispatchSaveChildState() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 200; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.selectable_text_view); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| mGridView.setSaveChildrenPolicy(VerticalGridView.SAVE_NO_CHILD); |
| |
| final SparseArray<Parcelable> container = new SparseArray<Parcelable>(); |
| |
| // 1. Set text selection, save view states should do nothing on child |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < mGridView.getChildCount(); i++) { |
| Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(i)) |
| .getText()), 0, 1); |
| } |
| mGridView.saveHierarchyState(container); |
| } |
| }); |
| |
| // 2. clear the text selection |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < mGridView.getChildCount(); i++) { |
| Selection.removeSelection((Spannable)(((TextView) mGridView.getChildAt(i)) |
| .getText())); |
| } |
| } |
| }); |
| |
| // 3. Restore view states should be a no-op for child |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.restoreHierarchyState(container); |
| for (int i = 0; i < mGridView.getChildCount(); i++) { |
| assertEquals(-1, ((TextView) mGridView.getChildAt(i)).getSelectionStart()); |
| assertEquals(-1, ((TextView) mGridView.getChildAt(i)).getSelectionEnd()); |
| } |
| } |
| }); |
| } |
| |
| |
| static interface ViewTypeProvider { |
| public int getViewType(int position); |
| } |
| |
| static interface ItemAlignmentFacetProvider { |
| public ItemAlignmentFacet getItemAlignmentFacet(int viewType); |
| } |
| |
| static class TwoViewTypesProvider implements ViewTypeProvider { |
| static int VIEW_TYPE_FIRST = 1; |
| static int VIEW_TYPE_DEFAULT = 0; |
| @Override |
| public int getViewType(int position) { |
| if (position == 0) { |
| return VIEW_TYPE_FIRST; |
| } else { |
| return VIEW_TYPE_DEFAULT; |
| } |
| } |
| } |
| |
| static class ChangeableViewTypesProvider implements ViewTypeProvider { |
| static SparseIntArray sViewTypes = new SparseIntArray(); |
| @Override |
| public int getViewType(int position) { |
| return sViewTypes.get(position); |
| } |
| public static void clear() { |
| sViewTypes.clear(); |
| } |
| public static void setViewType(int position, int type) { |
| sViewTypes.put(position, type); |
| } |
| } |
| |
| static class PositionItemAlignmentFacetProviderForRelativeLayout1 |
| implements ItemAlignmentFacetProvider { |
| ItemAlignmentFacet mMultipleFacet; |
| |
| PositionItemAlignmentFacetProviderForRelativeLayout1() { |
| mMultipleFacet = new ItemAlignmentFacet(); |
| ItemAlignmentFacet.ItemAlignmentDef[] defs = |
| new ItemAlignmentFacet.ItemAlignmentDef[2]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t1); |
| defs[1] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[1].setItemAlignmentViewId(R.id.t2); |
| defs[1].setItemAlignmentOffsetPercent(100); |
| defs[1].setItemAlignmentOffset(-10); |
| mMultipleFacet.setAlignmentDefs(defs); |
| } |
| |
| @Override |
| public ItemAlignmentFacet getItemAlignmentFacet(int position) { |
| if (position == 0) { |
| return mMultipleFacet; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Test |
| public void testMultipleScrollPosition1() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS, |
| TwoViewTypesProvider.class.getName()); |
| // Set ItemAlignment for each ViewHolder and view type, ViewHolder should |
| // override the view type settings. |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS, |
| PositionItemAlignmentFacetProviderForRelativeLayout1.class.getName()); |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_VIEWTYPE_CLASS, |
| ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2.class.getName()); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", |
| mGridView.getPaddingTop(), mGridView.getChildAt(0).getTop()); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| waitForScrollIdle(mVerifyLayout); |
| |
| final View v = mGridView.getChildAt(0); |
| View t1 = v.findViewById(R.id.t1); |
| int t1align = (t1.getTop() + t1.getBottom()) / 2; |
| View t2 = v.findViewById(R.id.t2); |
| int t2align = t2.getBottom() - 10; |
| assertEquals("Expected alignment for 2nd textview", |
| mGridView.getPaddingTop() - (t2align - t1align), |
| v.getTop()); |
| } |
| |
| static class PositionItemAlignmentFacetProviderForRelativeLayout2 implements |
| ItemAlignmentFacetProvider { |
| ItemAlignmentFacet mMultipleFacet; |
| |
| PositionItemAlignmentFacetProviderForRelativeLayout2() { |
| mMultipleFacet = new ItemAlignmentFacet(); |
| ItemAlignmentFacet.ItemAlignmentDef[] defs = new ItemAlignmentFacet.ItemAlignmentDef[2]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t1); |
| defs[0].setItemAlignmentOffsetPercent(0); |
| defs[1] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[1].setItemAlignmentViewId(R.id.t2); |
| defs[1].setItemAlignmentOffsetPercent(ItemAlignmentFacet.ITEM_ALIGN_OFFSET_PERCENT_DISABLED); |
| defs[1].setItemAlignmentOffset(-10); |
| mMultipleFacet.setAlignmentDefs(defs); |
| } |
| |
| @Override |
| public ItemAlignmentFacet getItemAlignmentFacet(int position) { |
| if (position == 0) { |
| return mMultipleFacet; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Test |
| public void testMultipleScrollPosition2() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS, |
| TwoViewTypesProvider.class.getName()); |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS, |
| PositionItemAlignmentFacetProviderForRelativeLayout2.class.getName()); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| waitForScrollIdle(mVerifyLayout); |
| |
| final View v = mGridView.getChildAt(0); |
| View t1 = v.findViewById(R.id.t1); |
| int t1align = t1.getTop(); |
| View t2 = v.findViewById(R.id.t2); |
| int t2align = t2.getTop() - 10; |
| assertEquals("Expected alignment for 2nd textview", |
| mGridView.getPaddingTop() - (t2align - t1align), v.getTop()); |
| } |
| |
| static class ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2 implements |
| ItemAlignmentFacetProvider { |
| ItemAlignmentFacet mMultipleFacet; |
| |
| ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2() { |
| mMultipleFacet = new ItemAlignmentFacet(); |
| ItemAlignmentFacet.ItemAlignmentDef[] defs = new ItemAlignmentFacet.ItemAlignmentDef[2]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t1); |
| defs[0].setItemAlignmentOffsetPercent(0); |
| defs[1] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[1].setItemAlignmentViewId(R.id.t2); |
| defs[1].setItemAlignmentOffsetPercent(100); |
| defs[1].setItemAlignmentOffset(-10); |
| mMultipleFacet.setAlignmentDefs(defs); |
| } |
| |
| @Override |
| public ItemAlignmentFacet getItemAlignmentFacet(int viewType) { |
| if (viewType == TwoViewTypesProvider.VIEW_TYPE_FIRST) { |
| return mMultipleFacet; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Test |
| public void testMultipleScrollPosition3() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS, |
| TwoViewTypesProvider.class.getName()); |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_VIEWTYPE_CLASS, |
| ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2.class.getName()); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| waitForScrollIdle(mVerifyLayout); |
| |
| final View v = mGridView.getChildAt(0); |
| View t1 = v.findViewById(R.id.t1); |
| int t1align = t1.getTop(); |
| View t2 = v.findViewById(R.id.t2); |
| int t2align = t2.getBottom() - 10; |
| assertEquals("Expected alignment for 2nd textview", |
| mGridView.getPaddingTop() - (t2align - t1align), v.getTop()); |
| } |
| |
| static class TestFastLayoutWithItemAlignmentDefProvider implements |
| ItemAlignmentFacetProvider { |
| ItemAlignmentFacet mItemAlignmentFacet; |
| |
| TestFastLayoutWithItemAlignmentDefProvider() { |
| mItemAlignmentFacet = new ItemAlignmentFacet(); |
| ItemAlignmentFacet.ItemAlignmentDef[] defs = new ItemAlignmentFacet.ItemAlignmentDef[1]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentOffsetPercent(0); |
| defs[0].setItemAlignmentOffset(-500); |
| mItemAlignmentFacet.setAlignmentDefs(defs); |
| } |
| |
| @Override |
| public ItemAlignmentFacet getItemAlignmentFacet(int viewType) { |
| return mItemAlignmentFacet; |
| } |
| } |
| |
| private void testFastLayoutNotifyItemChange(boolean supportsChangeAnimation) throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_VIEWTYPE_CLASS, |
| TestFastLayoutWithItemAlignmentDefProvider.class.getName()); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffset(0); |
| mGridView.setWindowAlignmentOffsetPercent(BaseGridView |
| .WINDOW_ALIGN_OFFSET_PERCENT_DISABLED); |
| ((DefaultItemAnimator) mGridView.getItemAnimator()).setSupportsChangeAnimations( |
| supportsChangeAnimation); |
| } |
| }); |
| waitOneUiCycle(); |
| assertEquals(500, mGridView.findViewHolderForAdapterPosition(0).itemView.getTop()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyItemChanged(0); |
| } |
| }); |
| waitOneUiCycle(); |
| assertEquals(500, mGridView.findViewHolderForAdapterPosition(0).itemView.getTop()); |
| } |
| |
| @Test |
| public void testFastLayoutNotifyItemChangeWithoutChangeAnimation() throws Throwable { |
| testFastLayoutNotifyItemChange(/* supportsChangeAnimation= */ false); |
| } |
| |
| @Test |
| public void testFastLayoutNotifyItemChangeWithChangeAnimation() throws Throwable { |
| testFastLayoutNotifyItemChange(/* supportsChangeAnimation= */ true); |
| } |
| |
| @Test |
| public void testSelectionAndAddItemInOneCycle() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 0); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, new int[]{300, 300}); |
| mGridView.setSelectedPosition(0); |
| } |
| }); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testSelectViewTaskSmoothWithAdapterChange() throws Throwable { |
| testSelectViewTaskWithAdapterChange(true /*smooth*/); |
| } |
| |
| @Test |
| public void testSelectViewTaskWithAdapterChange() throws Throwable { |
| testSelectViewTaskWithAdapterChange(false /*smooth*/); |
| } |
| |
| private void testSelectViewTaskWithAdapterChange(final boolean smooth) throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final View firstView = mGridView.getLayoutManager().findViewByPosition(0); |
| final View[] selectedViewByTask = new View[1]; |
| final ViewHolderTask task = new ViewHolderTask() { |
| @Override |
| public void run(RecyclerView.ViewHolder viewHolder) { |
| selectedViewByTask[0] = viewHolder.itemView; |
| } |
| }; |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(0, 1); |
| if (smooth) { |
| mGridView.setSelectedPositionSmooth(0, task); |
| } else { |
| mGridView.setSelectedPosition(0, task); |
| } |
| } |
| }); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| assertNotNull(selectedViewByTask[0]); |
| assertNotSame(firstView, selectedViewByTask[0]); |
| assertSame(mGridView.getLayoutManager().findViewByPosition(0), selectedViewByTask[0]); |
| } |
| |
| @Test |
| public void testNotifyItemTypeChangedSelectionEvent() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10); |
| intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS, |
| ChangeableViewTypesProvider.class.getName()); |
| ChangeableViewTypesProvider.clear(); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final ArrayList<Integer> selectedLog = new ArrayList<Integer>(); |
| mGridView.setOnChildSelectedListener(new OnChildSelectedListener() { |
| @Override |
| public void onChildSelected(ViewGroup parent, View view, int position, long id) { |
| selectedLog.add(position); |
| } |
| }); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| ChangeableViewTypesProvider.setViewType(0, 1); |
| mGridView.getAdapter().notifyItemChanged(0, 1); |
| } |
| }); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| assertEquals(selectedLog.size(), 1); |
| assertEquals((int) selectedLog.get(0), 0); |
| } |
| |
| @Test |
| public void testNotifyItemChangedSelectionEvent() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| OnChildViewHolderSelectedListener listener = |
| Mockito.mock(OnChildViewHolderSelectedListener.class); |
| mGridView.setOnChildViewHolderSelectedListener(listener); |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyItemChanged(0, 1); |
| } |
| }); |
| Mockito.verify(listener, times(1)).onChildViewHolderSelected(any(RecyclerView.class), |
| any(RecyclerView.ViewHolder.class), anyInt(), anyInt()); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testSelectionSmoothAndAddItemInOneCycle() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 0); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, new int[]{300, 300}); |
| mGridView.setSelectedPositionSmooth(0); |
| } |
| }); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| } |
| |
| @FlakyTest |
| @Test |
| public void testExtraLayoutSpace() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| |
| final int windowSize = mGridView.getHeight(); |
| final int extraLayoutSize = windowSize; |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| // add extra layout space |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setExtraLayoutSpace(extraLayoutSize); |
| } |
| }); |
| waitForLayout(); |
| View v; |
| v = mGridView.getChildAt(mGridView.getChildCount() - 1); |
| assertTrue(v.getTop() < windowSize + extraLayoutSize); |
| assertTrue(v.getBottom() >= windowSize + extraLayoutSize - mGridView.getVerticalMargin()); |
| |
| mGridView.setSelectedPositionSmooth(150); |
| waitForScrollIdle(mVerifyLayout); |
| v = mGridView.getChildAt(0); |
| assertTrue(v.getBottom() > - extraLayoutSize); |
| assertTrue(v.getTop() <= -extraLayoutSize + mGridView.getVerticalMargin()); |
| |
| // clear extra layout space |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setExtraLayoutSpace(0); |
| verifyMargin(); |
| } |
| }); |
| Thread.sleep(50); |
| v = mGridView.getChildAt(mGridView.getChildCount() - 1); |
| assertTrue(v.getTop() < windowSize); |
| assertTrue(v.getBottom() >= windowSize - mGridView.getVerticalMargin()); |
| } |
| |
| @Test |
| public void testFocusFinder() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 3); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| // test focus from button to vertical grid view |
| final View button = mActivity.findViewById(R.id.button); |
| assertTrue(button.isFocused()); |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| assertFalse(mGridView.isFocused()); |
| assertTrue(mGridView.hasFocus()); |
| |
| // FocusFinder should find last focused(2nd) item on DPAD_DOWN |
| final View secondChild = mGridView.getChildAt(1); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| secondChild.requestFocus(); |
| button.requestFocus(); |
| } |
| }); |
| assertTrue(button.isFocused()); |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| assertTrue(secondChild.isFocused()); |
| |
| // Bug 26918143 Even VerticalGridView is not focusable, FocusFinder should find last focused |
| // (2nd) item on DPAD_DOWN. |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| button.requestFocus(); |
| } |
| }); |
| mGridView.setFocusable(false); |
| mGridView.setFocusableInTouchMode(false); |
| assertTrue(button.isFocused()); |
| sendKey(KeyEvent.KEYCODE_DPAD_DOWN); |
| assertTrue(secondChild.isFocused()); |
| } |
| |
| @Test |
| public void testRestoreIndexAndAddItems() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.horizontal_item); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 4); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| assertEquals(mGridView.getSelectedPosition(), 0); |
| final SparseArray<Parcelable> states = new SparseArray<>(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.saveHierarchyState(states); |
| mGridView.setAdapter(null); |
| } |
| |
| }); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.restoreHierarchyState(states); |
| mActivity.attachToNewAdapter(new int[0]); |
| mActivity.addItems(0, new int[]{100, 100, 100, 100}); |
| } |
| |
| }); |
| assertEquals(mGridView.getSelectedPosition(), 0); |
| } |
| |
| @Test |
| public void testRestoreIndexAndAddItemsSelect1() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.horizontal_item); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 4); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPosition(1); |
| } |
| |
| }); |
| assertEquals(mGridView.getSelectedPosition(), 1); |
| final SparseArray<Parcelable> states = new SparseArray<>(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.saveHierarchyState(states); |
| mGridView.setAdapter(null); |
| } |
| |
| }); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.restoreHierarchyState(states); |
| mActivity.attachToNewAdapter(new int[0]); |
| mActivity.addItems(0, new int[]{100, 100, 100, 100}); |
| } |
| |
| }); |
| assertEquals(mGridView.getSelectedPosition(), 1); |
| } |
| |
| @Test |
| public void testRestoreStateAfterAdapterChange() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.selectable_text_view); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{50, 50, 50, 50}); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setSelectedPosition(1); |
| mGridView.setSaveChildrenPolicy(VerticalGridView.SAVE_ALL_CHILD); |
| } |
| |
| }); |
| assertEquals(mGridView.getSelectedPosition(), 1); |
| final SparseArray<Parcelable> states = new SparseArray<>(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| Selection.setSelection((Spannable) (((TextView) mGridView.getChildAt(0)) |
| .getText()), 1, 2); |
| Selection.setSelection((Spannable) (((TextView) mGridView.getChildAt(1)) |
| .getText()), 0, 1); |
| mGridView.saveHierarchyState(states); |
| mGridView.setAdapter(null); |
| } |
| |
| }); |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.restoreHierarchyState(states); |
| mActivity.attachToNewAdapter(new int[]{50, 50, 50, 50}); |
| } |
| |
| }); |
| assertEquals(mGridView.getSelectedPosition(), 1); |
| assertEquals(1, ((TextView) mGridView.getChildAt(0)).getSelectionStart()); |
| assertEquals(2, ((TextView) mGridView.getChildAt(0)).getSelectionEnd()); |
| assertEquals(0, ((TextView) mGridView.getChildAt(1)).getSelectionStart()); |
| assertEquals(1, ((TextView) mGridView.getChildAt(1)).getSelectionEnd()); |
| } |
| |
| @Test |
| public void test27766012() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.horizontal_item); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| // set remove animator two seconds |
| mGridView.getItemAnimator().setRemoveDuration(2000); |
| final View view = mGridView.getChildAt(1); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| view.requestFocus(); |
| } |
| }); |
| assertTrue(view.hasFocus()); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(0, 2); |
| } |
| |
| }); |
| // wait one second, removing second view is still attached to parent |
| Thread.sleep(1000); |
| assertSame(view.getParent(), mGridView); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| // refocus to the removed item and do a focus search. |
| view.requestFocus(); |
| view.focusSearch(View.FOCUS_UP); |
| } |
| |
| }); |
| } |
| |
| @Test |
| public void testBug27258366() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.horizontal_item); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| // move item1 500 pixels right, when focus is on item1, default focus finder will pick |
| // item0 and item2 for the best match of focusSearch(FOCUS_LEFT). The grid widget |
| // must override default addFocusables(), not to add item0 or item2. |
| mActivity.mAdapterListener = new GridActivity.AdapterListener() { |
| @Override |
| public void onBind(RecyclerView.ViewHolder vh, int position) { |
| if (position == 1) { |
| vh.itemView.setPaddingRelative(500, 0, 0, 0); |
| } else { |
| vh.itemView.setPaddingRelative(0, 0, 0, 0); |
| } |
| } |
| }; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyDataSetChanged(); |
| } |
| }); |
| Thread.sleep(100); |
| |
| final ViewGroup secondChild = (ViewGroup) mGridView.getChildAt(1); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| secondChild.requestFocus(); |
| } |
| }); |
| sendKey(KeyEvent.KEYCODE_DPAD_LEFT); |
| Thread.sleep(100); |
| final View button = mActivity.findViewById(R.id.button); |
| assertTrue(button.isFocused()); |
| } |
| |
| @Test |
| public void testUpdateHeightScrollHorizontal() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 30); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, false); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE_SECONDARY, true); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int childTop = mGridView.getChildAt(0).getTop(); |
| // scroll to end, all children's top should not change. |
| scrollToEnd(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < mGridView.getChildCount(); i++) { |
| assertEquals(childTop, mGridView.getChildAt(i).getTop()); |
| } |
| } |
| }); |
| // sanity check last child has focus with a larger height. |
| assertTrue(mGridView.getChildAt(0).getHeight() |
| < mGridView.getChildAt(mGridView.getChildCount() - 1).getHeight()); |
| } |
| |
| @Test |
| public void testUpdateWidthScrollHorizontal() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 30); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, true); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE_SECONDARY, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int childTop = mGridView.getChildAt(0).getTop(); |
| // scroll to end, all children's top should not change. |
| scrollToEnd(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < mGridView.getChildCount(); i++) { |
| assertEquals(childTop, mGridView.getChildAt(i).getTop()); |
| } |
| } |
| }); |
| // sanity check last child has focus with a larger width. |
| assertTrue(mGridView.getChildAt(0).getWidth() |
| < mGridView.getChildAt(mGridView.getChildCount() - 1).getWidth()); |
| if (mGridView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { |
| assertEquals(mGridView.getPaddingLeft(), |
| mGridView.getChildAt(mGridView.getChildCount() - 1).getLeft()); |
| } else { |
| assertEquals(mGridView.getWidth() - mGridView.getPaddingRight(), |
| mGridView.getChildAt(mGridView.getChildCount() - 1).getRight()); |
| } |
| } |
| |
| @Test |
| public void testUpdateWidthScrollHorizontalRtl() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear_rtl); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 30); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, true); |
| intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE_SECONDARY, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| final int childTop = mGridView.getChildAt(0).getTop(); |
| // scroll to end, all children's top should not change. |
| scrollToEnd(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < mGridView.getChildCount(); i++) { |
| assertEquals(childTop, mGridView.getChildAt(i).getTop()); |
| } |
| } |
| }); |
| // sanity check last child has focus with a larger width. |
| assertTrue(mGridView.getChildAt(0).getWidth() |
| < mGridView.getChildAt(mGridView.getChildCount() - 1).getWidth()); |
| assertEquals(mGridView.getPaddingLeft(), |
| mGridView.getChildAt(mGridView.getChildCount() - 1).getLeft()); |
| } |
| |
| @Test |
| public void testAccessibility() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| assertTrue(0 == mGridView.getSelectedPosition()); |
| |
| final RecyclerViewAccessibilityDelegate delegateCompat = mGridView |
| .getCompatAccessibilityDelegate(); |
| final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| assertTrue("test sanity", info.isScrollable()); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.performAccessibilityAction(mGridView, |
| AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD, null); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| int selectedPosition1 = mGridView.getSelectedPosition(); |
| assertTrue(0 < selectedPosition1); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| assertTrue("test sanity", info.isScrollable()); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.performAccessibilityAction(mGridView, |
| AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD, null); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| int selectedPosition2 = mGridView.getSelectedPosition(); |
| assertTrue(selectedPosition2 < selectedPosition1); |
| } |
| |
| @Test |
| public void testAccessibilityScrollForwardHalfVisible() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.item_button_at_bottom); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{}); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| int height = mGridView.getHeight() - mGridView.getPaddingTop() |
| - mGridView.getPaddingBottom(); |
| final int childHeight = height - mGridView.getVerticalSpacing() - 100; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffset(100); |
| mGridView.setWindowAlignmentOffsetPercent(BaseGridView |
| .WINDOW_ALIGN_OFFSET_PERCENT_DISABLED); |
| mGridView.setItemAlignmentOffset(0); |
| mGridView.setItemAlignmentOffsetPercent(BaseGridView |
| .ITEM_ALIGN_OFFSET_PERCENT_DISABLED); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, new int[]{childHeight, childHeight}); |
| } |
| }); |
| waitForItemAnimation(); |
| setSelectedPosition(0); |
| |
| final RecyclerViewAccessibilityDelegate delegateCompat = mGridView |
| .getCompatAccessibilityDelegate(); |
| final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| assertTrue("test sanity", info.isScrollable()); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.performAccessibilityAction(mGridView, |
| AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD, null); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(1, mGridView.getSelectedPosition()); |
| } |
| |
| // Temporarily disabled due to b/110377468 |
| // @Test |
| public void testAccessibilityBug77292190() throws Throwable { |
| Intent intent = new Intent(); |
| final int numItems = 1000; |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.item_full_width); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| setSelectedPosition(0); |
| |
| final RecyclerViewAccessibilityDelegate delegateCompat = mGridView |
| .getCompatAccessibilityDelegate(); |
| final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| if (Build.VERSION.SDK_INT >= 21) { |
| assertFalse(hasAction(info, |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_UP)); |
| assertTrue(hasAction(info, |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_DOWN)); |
| } else { |
| assertFalse(hasAction(info, AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD)); |
| assertTrue(hasAction(info, AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD)); |
| } |
| |
| setSelectedPosition(numItems - 1); |
| final AccessibilityNodeInfoCompat info2 = AccessibilityNodeInfoCompat.obtain(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info2); |
| } |
| }); |
| if (Build.VERSION.SDK_INT >= 21) { |
| assertTrue(hasAction(info2, |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_UP)); |
| assertFalse(hasAction(info2, |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_DOWN)); |
| } else { |
| assertTrue(hasAction(info2, AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD)); |
| assertFalse(hasAction(info2, AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD)); |
| } |
| } |
| |
| @Test |
| public void testAccessibilityWhenScrollDisabled() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.item_button_at_bottom); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| setSelectedPosition(0); |
| |
| final RecyclerViewAccessibilityDelegate delegateCompat = mGridView |
| .getCompatAccessibilityDelegate(); |
| final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| mGridView.setScrollEnabled(false); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < 100; i++) { |
| assertTrue(delegateCompat.performAccessibilityAction(mGridView, |
| AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD, null)); |
| } |
| } |
| }); |
| assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState()); |
| } |
| private boolean hasAction(AccessibilityNodeInfoCompat info, Object action) { |
| if (Build.VERSION.SDK_INT >= 21) { |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat convertedAction = |
| (AccessibilityNodeInfoCompat.AccessibilityActionCompat) action; |
| List<AccessibilityNodeInfoCompat.AccessibilityActionCompat> actions = |
| info.getActionList(); |
| for (int i = 0; i < actions.size(); i++) { |
| if (actions.get(i).getId() == convertedAction.getId()) { |
| return true; |
| } |
| } |
| return false; |
| } else { |
| int convertedAction = (int) action; |
| return ((info.getActions() & convertedAction) != 0); |
| } |
| } |
| |
| private void setUpActivityForScrollingTest(final boolean isRTL, boolean isHorizontal, |
| int numChildViews, boolean isSiblingViewVisible) throws Throwable { |
| Intent intent = new Intent(); |
| int layout; |
| if (isHorizontal) { |
| layout = isRTL ? R.layout.horizontal_linear_rtl : R.layout.horizontal_linear; |
| } else { |
| layout = R.layout.vertical_linear; |
| } |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, layout); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.item_button_at_bottom); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{}); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = isHorizontal ? BaseGridView.HORIZONTAL : BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| final int offset = (isSiblingViewVisible ? 2 : 1) * (isHorizontal |
| ? mGridView.getHorizontalSpacing() : mGridView.getVerticalSpacing()); |
| final int childSize = (isHorizontal ? mGridView.getWidth() : mGridView.getHeight()) |
| - offset - (isHorizontal ? 2 * mGridView.getHorizontalSpacing() : |
| mGridView.getVerticalSpacing()); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (isRTL) { |
| mGridView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); |
| } |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffset(offset); |
| mGridView.setWindowAlignmentOffsetPercent(BaseGridView |
| .WINDOW_ALIGN_OFFSET_PERCENT_DISABLED); |
| mGridView.setItemAlignmentOffset(0); |
| mGridView.setItemAlignmentOffsetPercent(BaseGridView |
| .ITEM_ALIGN_OFFSET_PERCENT_DISABLED); |
| } |
| }); |
| final int[] widthArrays = new int[numChildViews]; |
| Arrays.fill(widthArrays, childSize); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, widthArrays); |
| } |
| }); |
| } |
| |
| private void testScrollingAction(boolean isRTL, boolean isHorizontal) throws Throwable { |
| waitForItemAnimation(); |
| setSelectedPosition(1); |
| final RecyclerViewAccessibilityDelegate delegateCompat = mGridView |
| .getCompatAccessibilityDelegate(); |
| final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| // We are currently focusing on item 1, calculating the direction to get me to item 0 |
| final AccessibilityNodeInfoCompat.AccessibilityActionCompat itemZeroDirection; |
| if (isHorizontal) { |
| itemZeroDirection = isRTL |
| ? AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_RIGHT : |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_LEFT; |
| } else { |
| itemZeroDirection = |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_UP; |
| } |
| final int translatedItemZeroDirection = AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD; |
| |
| assertTrue("test sanity", info.isScrollable()); |
| if (Build.VERSION.SDK_INT >= 23) { |
| assertTrue("test sanity", hasAction(info, itemZeroDirection)); |
| } else { |
| assertTrue("test sanity", hasAction(info, translatedItemZeroDirection)); |
| } |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (Build.VERSION.SDK_INT >= 23) { |
| delegateCompat.performAccessibilityAction(mGridView, itemZeroDirection.getId(), |
| null); |
| } else { |
| delegateCompat.performAccessibilityAction(mGridView, |
| translatedItemZeroDirection, null); |
| } |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| setSelectedPosition(0); |
| // We are at item 0, calculate the direction that lead us to the item 1 |
| final AccessibilityNodeInfoCompat.AccessibilityActionCompat itemOneDirection; |
| if (isHorizontal) { |
| itemOneDirection = isRTL |
| ? AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_LEFT |
| : AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_RIGHT; |
| } else { |
| itemOneDirection = |
| AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_DOWN; |
| } |
| final int translatedItemOneDirection = AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD; |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| if (Build.VERSION.SDK_INT >= 23) { |
| assertTrue("test sanity", hasAction(info, itemOneDirection)); |
| } else { |
| assertTrue("test sanity", hasAction(info, translatedItemOneDirection)); |
| } |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (Build.VERSION.SDK_INT >= 23) { |
| delegateCompat.performAccessibilityAction(mGridView, itemOneDirection.getId(), |
| null); |
| } else { |
| delegateCompat.performAccessibilityAction(mGridView, translatedItemOneDirection, |
| null); |
| } |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(1, mGridView.getSelectedPosition()); |
| } |
| |
| // Temporarily disabled due to b/110377468 |
| // @Test |
| public void testAccessibilityRespondToLeftRightInvisible() throws Throwable { |
| boolean isRTL = false; |
| boolean isHorizontal = true; |
| setUpActivityForScrollingTest(isRTL, isHorizontal, 2 /* numChild */, |
| false /* next child partially visible */); |
| testScrollingAction(isRTL, isHorizontal); |
| } |
| |
| // Temporarily disabled due to b/110377468 |
| // @Test |
| public void testAccessibilityRespondToLeftRightPartiallyVisible() throws Throwable { |
| boolean isRTL = false; |
| boolean isHorizontal = true; |
| setUpActivityForScrollingTest(isRTL, isHorizontal, 2 /* numChild */, |
| true /* next child partially visible */); |
| testScrollingAction(isRTL, isHorizontal); |
| } |
| |
| // Temporarily disabled due to b/110377468 |
| // @Test |
| public void testAccessibilityRespondToLeftRightRtlInvisible() |
| throws Throwable { |
| boolean isRTL = true; |
| boolean isHorizontal = true; |
| setUpActivityForScrollingTest(isRTL, isHorizontal, 2 /* numChild */, |
| false /* next child partially visible */); |
| testScrollingAction(isRTL, isHorizontal); |
| } |
| |
| // Temporarily disabled due to b/110377468 |
| // @Test |
| public void testAccessibilityRespondToLeftRightRtlPartiallyVisible() throws Throwable { |
| boolean isRTL = true; |
| boolean isHorizontal = true; |
| setUpActivityForScrollingTest(isRTL, isHorizontal, 2 /* numChild */, |
| true /* next child partially visible */); |
| testScrollingAction(isRTL, isHorizontal); |
| } |
| |
| // Temporarily disabled due to b/110377468 |
| // @Test |
| public void testAccessibilityRespondToScrollUpDownActionInvisible() throws Throwable { |
| boolean isRTL = false; |
| boolean isHorizontal = false; |
| setUpActivityForScrollingTest(isRTL, isHorizontal, 2 /* numChild */, |
| false /* next child partially visible */); |
| testScrollingAction(isRTL, isHorizontal); |
| } |
| |
| // Temporarily disabled due to b/110377468 |
| // @Test |
| public void testAccessibilityRespondToScrollUpDownActionPartiallyVisible() throws Throwable { |
| boolean isRTL = false; |
| boolean isHorizontal = false; |
| setUpActivityForScrollingTest(isRTL, isHorizontal, 2 /* numChild */, |
| true /* next child partially visible */); |
| testScrollingAction(isRTL, isHorizontal); |
| } |
| |
| @Test |
| public void testAccessibilityScrollBackwardHalfVisible() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.item_button_at_top); |
| intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{}); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| initActivity(intent); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| int height = mGridView.getHeight() - mGridView.getPaddingTop() |
| - mGridView.getPaddingBottom(); |
| final int childHeight = height - mGridView.getVerticalSpacing() - 100; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffset(100); |
| mGridView.setWindowAlignmentOffsetPercent(BaseGridView |
| .WINDOW_ALIGN_OFFSET_PERCENT_DISABLED); |
| mGridView.setItemAlignmentOffset(0); |
| mGridView.setItemAlignmentOffsetPercent(BaseGridView |
| .ITEM_ALIGN_OFFSET_PERCENT_DISABLED); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.addItems(0, new int[]{childHeight, childHeight}); |
| } |
| }); |
| waitForItemAnimation(); |
| setSelectedPosition(1); |
| |
| final RecyclerViewAccessibilityDelegate delegateCompat = mGridView |
| .getCompatAccessibilityDelegate(); |
| final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info); |
| } |
| }); |
| assertTrue("test sanity", info.isScrollable()); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| delegateCompat.performAccessibilityAction(mGridView, |
| AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD, null); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| } |
| |
| void slideInAndWaitIdle() throws Throwable { |
| slideInAndWaitIdle(5000); |
| } |
| |
| void slideInAndWaitIdle(long timeout) throws Throwable { |
| // animateIn() would reset position |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateIn(); |
| } |
| }); |
| PollingCheck.waitFor(timeout, new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return !mGridView.getLayoutManager().isSmoothScrolling() |
| && mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| } |
| |
| @Test |
| public void testAnimateOutBlockScrollTo() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateOut(); |
| } |
| }); |
| // wait until sliding out. |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop(); |
| } |
| }); |
| // scrollToPosition() should not affect slideOut status |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.scrollToPosition(0); |
| } |
| }); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| assertTrue("First view slided Out", mGridView.getChildAt(0).getTop() |
| >= mGridView.getHeight()); |
| |
| slideInAndWaitIdle(); |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| } |
| |
| @Test |
| public void testAnimateOutBlockSmoothScrolling() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| int[] items = new int[30]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateOut(); |
| } |
| }); |
| // wait until sliding out. |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop(); |
| } |
| }); |
| // smoothScrollToPosition() should not affect slideOut status |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.smoothScrollToPosition(29); |
| } |
| }); |
| PollingCheck.waitFor(10000, new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| assertTrue("First view slided Out", mGridView.getChildAt(0).getTop() |
| >= mGridView.getHeight()); |
| |
| slideInAndWaitIdle(); |
| View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1); |
| assertSame("Scrolled to last child", |
| mGridView.findViewHolderForAdapterPosition(29).itemView, lastChild); |
| } |
| |
| @Test |
| public void testAnimateOutBlockLongScrollTo() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| int[] items = new int[30]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateOut(); |
| } |
| }); |
| // wait until sliding out. |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop(); |
| } |
| }); |
| // smoothScrollToPosition() should not affect slideOut status |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.scrollToPosition(29); |
| } |
| }); |
| PollingCheck.waitFor(10000, new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| assertTrue("First view slided Out", mGridView.getChildAt(0).getTop() |
| >= mGridView.getHeight()); |
| |
| slideInAndWaitIdle(); |
| View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1); |
| assertSame("Scrolled to last child", |
| mGridView.findViewHolderForAdapterPosition(29).itemView, lastChild); |
| } |
| |
| @FlakyTest |
| @Test |
| public void testAnimateOutBlockLayout() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateOut(); |
| } |
| }); |
| // wait until sliding out. |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop(); |
| } |
| }); |
| // change adapter should not affect slideOut status |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.changeItem(0, 200); |
| } |
| }); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| assertTrue("First view slided Out", mGridView.getChildAt(0).getTop() |
| >= mGridView.getHeight()); |
| assertEquals("onLayout suppressed during slide out", 300, |
| mGridView.getChildAt(0).getHeight()); |
| |
| slideInAndWaitIdle(); |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| // size of item should be updated immediately after slide in animation finishes: |
| PollingCheck.waitFor(1000, new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return 200 == mGridView.getChildAt(0).getHeight(); |
| } |
| }); |
| } |
| |
| @Test |
| public void testAnimateOutBlockFocusChange() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateOut(); |
| mActivity.findViewById(R.id.button).requestFocus(); |
| } |
| }); |
| assertTrue(mActivity.findViewById(R.id.button).hasFocus()); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop(); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.requestFocus(); |
| } |
| }); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| assertTrue("First view slided Out", mGridView.getChildAt(0).getTop() |
| >= mGridView.getHeight()); |
| |
| slideInAndWaitIdle(); |
| assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(), |
| mGridView.getChildAt(0).getTop()); |
| } |
| |
| @Test |
| public void testHorizontalAnimateOutBlockScrollTo() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding left", mGridView.getPaddingLeft(), |
| mGridView.getChildAt(0).getLeft()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateOut(); |
| } |
| }); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getChildAt(0).getLeft() > mGridView.getPaddingLeft(); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.scrollToPosition(0); |
| } |
| }); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| |
| assertTrue("First view is slided out", mGridView.getChildAt(0).getLeft() |
| > mGridView.getWidth()); |
| |
| slideInAndWaitIdle(); |
| assertEquals("First view is aligned with padding left", mGridView.getPaddingLeft(), |
| mGridView.getChildAt(0).getLeft()); |
| |
| } |
| |
| @Test |
| public void testHorizontalAnimateOutRtl() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.horizontal_linear_rtl); |
| int[] items = new int[100]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| assertEquals("First view is aligned with padding right", |
| mGridView.getWidth() - mGridView.getPaddingRight(), |
| mGridView.getChildAt(0).getRight()); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.animateOut(); |
| } |
| }); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getChildAt(0).getRight() |
| < mGridView.getWidth() - mGridView.getPaddingRight(); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.smoothScrollToPosition(0); |
| } |
| }); |
| PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { |
| @Override |
| public boolean canProceed() { |
| return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE; |
| } |
| }); |
| |
| assertTrue("First view is slided out", mGridView.getChildAt(0).getRight() < 0); |
| |
| slideInAndWaitIdle(); |
| assertEquals("First view is aligned with padding right", |
| mGridView.getWidth() - mGridView.getPaddingRight(), |
| mGridView.getChildAt(0).getRight()); |
| } |
| |
| @Test |
| public void testSmoothScrollerOutRange() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, |
| R.layout.vertical_linear_with_button_onleft); |
| intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true); |
| int[] items = new int[30]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 680; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| final View button = mActivity.findViewById(R.id.button); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| public void run() { |
| button.requestFocus(); |
| } |
| }); |
| |
| mGridView.setSelectedPositionSmooth(0); |
| waitForScrollIdle(mVerifyLayout); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| public void run() { |
| mGridView.setSelectedPositionSmooth(120); |
| } |
| }); |
| waitForScrollIdle(mVerifyLayout); |
| assertTrue(button.hasFocus()); |
| int key; |
| if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) { |
| key = KeyEvent.KEYCODE_DPAD_LEFT; |
| } else { |
| key = KeyEvent.KEYCODE_DPAD_RIGHT; |
| } |
| sendKey(key); |
| // the GridView should has focus in its children |
| assertTrue(mGridView.hasFocus()); |
| assertFalse(mGridView.isFocused()); |
| assertEquals(29, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testRemoveLastItemWithStableId() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, true); |
| int[] items = new int[1]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 680; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setRemoveDuration(2000); |
| mActivity.removeItems(0, 1, false); |
| mGridView.getAdapter().notifyDataSetChanged(); |
| } |
| }); |
| Thread.sleep(500); |
| assertEquals(-1, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testUpdateAndSelect1() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyDataSetChanged(); |
| mGridView.setSelectedPosition(1); |
| } |
| }); |
| waitOneUiCycle(); |
| assertEquals(1, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testUpdateAndSelect2() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getAdapter().notifyDataSetChanged(); |
| mGridView.setSelectedPosition(50); |
| } |
| }); |
| waitOneUiCycle(); |
| assertEquals(50, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testUpdateAndSelect3() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, false); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| int[] newItems = new int[100]; |
| for (int i = 0; i < newItems.length; i++) { |
| newItems[i] = mActivity.mItemLengths[0]; |
| } |
| mActivity.addItems(0, newItems, false); |
| mGridView.getAdapter().notifyDataSetChanged(); |
| mGridView.setSelectedPosition(50); |
| } |
| }); |
| waitOneUiCycle(); |
| assertEquals(50, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testFocusedPositonAfterRemoved1() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| final int[] items = new int[2]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| setSelectedPosition(1); |
| assertEquals(1, mGridView.getSelectedPosition()); |
| |
| final int[] newItems = new int[3]; |
| for (int i = 0; i < newItems.length; i++) { |
| newItems[i] = 300; |
| } |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(0, 2, true); |
| mActivity.addItems(0, newItems, true); |
| } |
| }); |
| assertEquals(0, mGridView.getSelectedPosition()); |
| } |
| |
| @Test |
| public void testFocusedPositonAfterRemoved2() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| final int[] items = new int[2]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| setSelectedPosition(1); |
| assertEquals(1, mGridView.getSelectedPosition()); |
| |
| final int[] newItems = new int[3]; |
| for (int i = 0; i < newItems.length; i++) { |
| newItems[i] = 300; |
| } |
| performAndWaitForAnimation(new Runnable() { |
| @Override |
| public void run() { |
| mActivity.removeItems(1, 1, true); |
| mActivity.addItems(1, newItems, true); |
| } |
| }); |
| assertEquals(1, mGridView.getSelectedPosition()); |
| } |
| |
| static void assertNoCollectionItemInfo(AccessibilityNodeInfoCompat info) { |
| AccessibilityNodeInfoCompat.CollectionItemInfoCompat nodeInfoCompat = |
| info.getCollectionItemInfo(); |
| if (nodeInfoCompat == null) { |
| return; |
| } |
| assertTrue(nodeInfoCompat.getRowIndex() < 0); |
| assertTrue(nodeInfoCompat.getColumnIndex() < 0); |
| } |
| |
| /** |
| * This test would need talkback on. |
| */ |
| @Test |
| public void testAccessibilityOfItemsBeingPushedOut() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| final int lastPos = mGridView.getChildAdapterPosition( |
| mGridView.getChildAt(mGridView.getChildCount() - 1)); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getLayoutManager().setItemPrefetchEnabled(false); |
| } |
| }); |
| final int numItemsToPushOut = mNumRows; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| // set longer enough so that accessibility service will initialize node |
| // within setImportantForAccessibility(). |
| mGridView.getItemAnimator().setRemoveDuration(2000); |
| mGridView.getItemAnimator().setAddDuration(2000); |
| final int[] newItems = new int[numItemsToPushOut]; |
| final int newItemValue = mActivity.mItemLengths[0]; |
| for (int i = 0; i < newItems.length; i++) { |
| newItems[i] = newItemValue; |
| } |
| mActivity.addItems(lastPos - numItemsToPushOut + 1, newItems); |
| } |
| }); |
| waitForItemAnimation(); |
| } |
| |
| /** |
| * This test simulates talkback by calling setImportanceForAccessibility at end of animation |
| */ |
| @Test |
| public void simulatesAccessibilityOfItemsBeingPushedOut() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| final HashSet<View> moveAnimationViews = new HashSet(); |
| mActivity.mImportantForAccessibilityListener = |
| new GridActivity.ImportantForAccessibilityListener() { |
| RecyclerView.LayoutManager mLM = mGridView.getLayoutManager(); |
| @Override |
| public void onImportantForAccessibilityChanged(View view, int newValue) { |
| // simulates talkack, having setImportantForAccessibility to call |
| // onInitializeAccessibilityNodeInfoForItem() for the DISAPPEARING items. |
| if (moveAnimationViews.contains(view)) { |
| AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); |
| mLM.onInitializeAccessibilityNodeInfoForItem( |
| null, null, view, info); |
| } |
| } |
| }; |
| final int lastPos = mGridView.getChildAdapterPosition( |
| mGridView.getChildAt(mGridView.getChildCount() - 1)); |
| final int numItemsToPushOut = mNumRows; |
| for (int i = 0; i < numItemsToPushOut; i++) { |
| moveAnimationViews.add( |
| mGridView.getChildAt(mGridView.getChildCount() - 1 - i)); |
| } |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setItemAnimator(new DefaultItemAnimator() { |
| @Override |
| public void onMoveFinished(RecyclerView.ViewHolder item) { |
| moveAnimationViews.remove(item.itemView); |
| } |
| }); |
| mGridView.getLayoutManager().setItemPrefetchEnabled(false); |
| } |
| }); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| final int[] newItems = new int[numItemsToPushOut]; |
| final int newItemValue = mActivity.mItemLengths[0] + 1; |
| for (int i = 0; i < newItems.length; i++) { |
| newItems[i] = newItemValue; |
| } |
| mActivity.addItems(lastPos - numItemsToPushOut + 1, newItems); |
| } |
| }); |
| while (moveAnimationViews.size() != 0) { |
| Thread.sleep(100); |
| } |
| } |
| |
| @Test |
| public void testAccessibilityNodeInfoOnRemovedFirstItem() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 6); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| final View lastView = mGridView.findViewHolderForAdapterPosition(0).itemView; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setRemoveDuration(20000); |
| mActivity.removeItems(0, 1); |
| } |
| }); |
| waitForItemAnimationStart(); |
| AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(lastView); |
| mGridView.getLayoutManager().onInitializeAccessibilityNodeInfoForItem(null, null, |
| lastView, info); |
| assertNoCollectionItemInfo(info); |
| } |
| |
| @Test |
| public void testAccessibilityNodeInfoOnRemovedLastItem() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid); |
| intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 6); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 3; |
| |
| initActivity(intent); |
| |
| final View lastView = mGridView.findViewHolderForAdapterPosition(5).itemView; |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.getItemAnimator().setRemoveDuration(20000); |
| mActivity.removeItems(5, 1); |
| } |
| }); |
| waitForItemAnimationStart(); |
| AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(lastView); |
| mGridView.getLayoutManager().onInitializeAccessibilityNodeInfoForItem(null, null, |
| lastView, info); |
| assertNoCollectionItemInfo(info); |
| } |
| |
| static class FiveViewTypesProvider implements ViewTypeProvider { |
| |
| @Override |
| public int getViewType(int position) { |
| switch (position) { |
| case 0: |
| return 0; |
| case 1: |
| return 1; |
| case 2: |
| return 2; |
| case 3: |
| return 3; |
| case 4: |
| return 4; |
| } |
| return 199; |
| } |
| } |
| |
| // Used by testItemAlignmentVertical() testItemAlignmentHorizontal() |
| static class ItemAlignmentWithPaddingFacetProvider implements |
| ItemAlignmentFacetProvider { |
| final ItemAlignmentFacet mFacet0; |
| final ItemAlignmentFacet mFacet1; |
| final ItemAlignmentFacet mFacet2; |
| final ItemAlignmentFacet mFacet3; |
| final ItemAlignmentFacet mFacet4; |
| |
| ItemAlignmentWithPaddingFacetProvider() { |
| ItemAlignmentFacet.ItemAlignmentDef[] defs; |
| mFacet0 = new ItemAlignmentFacet(); |
| defs = new ItemAlignmentFacet.ItemAlignmentDef[1]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t1); |
| defs[0].setItemAlignmentOffsetPercent(0); |
| defs[0].setItemAlignmentOffsetWithPadding(false); |
| mFacet0.setAlignmentDefs(defs); |
| mFacet1 = new ItemAlignmentFacet(); |
| defs = new ItemAlignmentFacet.ItemAlignmentDef[1]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t1); |
| defs[0].setItemAlignmentOffsetPercent(0); |
| defs[0].setItemAlignmentOffsetWithPadding(true); |
| mFacet1.setAlignmentDefs(defs); |
| mFacet2 = new ItemAlignmentFacet(); |
| defs = new ItemAlignmentFacet.ItemAlignmentDef[1]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t2); |
| defs[0].setItemAlignmentOffsetPercent(100); |
| defs[0].setItemAlignmentOffsetWithPadding(true); |
| mFacet2.setAlignmentDefs(defs); |
| mFacet3 = new ItemAlignmentFacet(); |
| defs = new ItemAlignmentFacet.ItemAlignmentDef[1]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t2); |
| defs[0].setItemAlignmentOffsetPercent(50); |
| defs[0].setItemAlignmentOffsetWithPadding(true); |
| mFacet3.setAlignmentDefs(defs); |
| mFacet4 = new ItemAlignmentFacet(); |
| defs = new ItemAlignmentFacet.ItemAlignmentDef[1]; |
| defs[0] = new ItemAlignmentFacet.ItemAlignmentDef(); |
| defs[0].setItemAlignmentViewId(R.id.t2); |
| defs[0].setItemAlignmentOffsetPercent(50); |
| defs[0].setItemAlignmentOffsetWithPadding(false); |
| mFacet4.setAlignmentDefs(defs); |
| } |
| |
| @Override |
| public ItemAlignmentFacet getItemAlignmentFacet(int viewType) { |
| switch (viewType) { |
| case 0: |
| return mFacet0; |
| case 1: |
| return mFacet1; |
| case 2: |
| return mFacet2; |
| case 3: |
| return mFacet3; |
| case 4: |
| return mFacet4; |
| } |
| return null; |
| } |
| } |
| |
| @Test |
| public void testItemAlignmentVertical() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout2); |
| int[] items = new int[5]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS, |
| FiveViewTypesProvider.class.getName()); |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS, |
| ItemAlignmentWithPaddingFacetProvider.class.getName()); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffsetPercent(50); |
| mGridView.setWindowAlignmentOffset(0); |
| } |
| }); |
| waitForLayout(); |
| |
| final float windowAlignCenter = mGridView.getHeight() / 2f; |
| Rect rect = new Rect(); |
| View textView; |
| |
| // test 1: does not include padding |
| textView = mGridView.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.t1); |
| rect.set(0, 0, textView.getWidth(), textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.top, DELTA); |
| |
| // test 2: including low padding |
| setSelectedPosition(1); |
| textView = mGridView.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.t1); |
| assertTrue(textView.getPaddingTop() > 0); |
| rect.set(0, textView.getPaddingTop(), textView.getWidth(), textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.top, DELTA); |
| |
| // test 3: including high padding |
| setSelectedPosition(2); |
| textView = mGridView.findViewHolderForAdapterPosition(2).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingBottom() > 0); |
| rect.set(0, 0, textView.getWidth(), |
| textView.getHeight() - textView.getPaddingBottom()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.bottom, DELTA); |
| |
| // test 4: including padding will be ignored if offsetPercent is not 0 or 100 |
| setSelectedPosition(3); |
| textView = mGridView.findViewHolderForAdapterPosition(3).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingTop() != textView.getPaddingBottom()); |
| rect.set(0, 0, textView.getWidth(), textView.getHeight() / 2); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.bottom, DELTA); |
| |
| // test 5: does not include padding |
| setSelectedPosition(4); |
| textView = mGridView.findViewHolderForAdapterPosition(4).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingTop() != textView.getPaddingBottom()); |
| rect.set(0, 0, textView.getWidth(), textView.getHeight() / 2); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.bottom, DELTA); |
| } |
| |
| @Test |
| public void testItemAlignmentHorizontal() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout3); |
| int[] items = new int[5]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS, |
| FiveViewTypesProvider.class.getName()); |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS, |
| ItemAlignmentWithPaddingFacetProvider.class.getName()); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffsetPercent(50); |
| mGridView.setWindowAlignmentOffset(0); |
| } |
| }); |
| waitForLayout(); |
| |
| final float windowAlignCenter = mGridView.getWidth() / 2f; |
| Rect rect = new Rect(); |
| View textView; |
| |
| // test 1: does not include padding |
| textView = mGridView.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.t1); |
| rect.set(0, 0, textView.getWidth(), textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.left, DELTA); |
| |
| // test 2: including low padding |
| setSelectedPosition(1); |
| textView = mGridView.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.t1); |
| assertTrue(textView.getPaddingLeft() > 0); |
| rect.set(textView.getPaddingLeft(), 0, textView.getWidth(), textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.left, DELTA); |
| |
| // test 3: including high padding |
| setSelectedPosition(2); |
| textView = mGridView.findViewHolderForAdapterPosition(2).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingRight() > 0); |
| rect.set(0, 0, textView.getWidth() - textView.getPaddingRight(), |
| textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.right, DELTA); |
| |
| // test 4: including padding will be ignored if offsetPercent is not 0 or 100 |
| setSelectedPosition(3); |
| textView = mGridView.findViewHolderForAdapterPosition(3).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingLeft() != textView.getPaddingRight()); |
| rect.set(0, 0, textView.getWidth() / 2, textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.right, DELTA); |
| |
| // test 5: does not include padding |
| setSelectedPosition(4); |
| textView = mGridView.findViewHolderForAdapterPosition(4).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingLeft() != textView.getPaddingRight()); |
| rect.set(0, 0, textView.getWidth() / 2, textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.right, DELTA); |
| } |
| |
| @Test |
| public void testItemAlignmentHorizontalRtl() throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear); |
| intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout3); |
| int[] items = new int[5]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 300; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS, |
| FiveViewTypesProvider.class.getName()); |
| intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS, |
| ItemAlignmentWithPaddingFacetProvider.class.getName()); |
| mOrientation = BaseGridView.VERTICAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| mGridView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); |
| mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE); |
| mGridView.setWindowAlignmentOffsetPercent(50); |
| mGridView.setWindowAlignmentOffset(0); |
| } |
| }); |
| waitForLayout(); |
| |
| final float windowAlignCenter = mGridView.getWidth() / 2f; |
| Rect rect = new Rect(); |
| View textView; |
| |
| // test 1: does not include padding |
| textView = mGridView.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.t1); |
| rect.set(0, 0, textView.getWidth(), textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.right, DELTA); |
| |
| // test 2: including low padding |
| setSelectedPosition(1); |
| textView = mGridView.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.t1); |
| assertTrue(textView.getPaddingRight() > 0); |
| rect.set(0, 0, textView.getWidth() - textView.getPaddingRight(), |
| textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.right, DELTA); |
| |
| // test 3: including high padding |
| setSelectedPosition(2); |
| textView = mGridView.findViewHolderForAdapterPosition(2).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingLeft() > 0); |
| rect.set(textView.getPaddingLeft(), 0, textView.getWidth(), |
| textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.left, DELTA); |
| |
| // test 4: including padding will be ignored if offsetPercent is not 0 or 100 |
| setSelectedPosition(3); |
| textView = mGridView.findViewHolderForAdapterPosition(3).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingLeft() != textView.getPaddingRight()); |
| rect.set(0, 0, textView.getWidth() / 2, textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.right, DELTA); |
| |
| // test 5: does not include padding |
| setSelectedPosition(4); |
| textView = mGridView.findViewHolderForAdapterPosition(4).itemView.findViewById(R.id.t2); |
| assertTrue(textView.getPaddingLeft() != textView.getPaddingRight()); |
| rect.set(0, 0, textView.getWidth() / 2, textView.getHeight()); |
| mGridView.offsetDescendantRectToMyCoords(textView, rect); |
| assertEquals(windowAlignCenter, rect.right, DELTA); |
| } |
| |
| enum ItemLocation { |
| ITEM_AT_LOW, |
| ITEM_AT_KEY_LINE, |
| ITEM_AT_HIGH |
| }; |
| |
| static class ItemAt { |
| final int mScrollPosition; |
| final int mPosition; |
| final ItemLocation mLocation; |
| |
| ItemAt(int scrollPosition, int position, ItemLocation loc) { |
| mScrollPosition = scrollPosition; |
| mPosition = position; |
| mLocation = loc; |
| } |
| |
| ItemAt(int position, ItemLocation loc) { |
| mScrollPosition = position; |
| mPosition = position; |
| mLocation = loc; |
| } |
| } |
| |
| /** |
| * When scroll to position, item at position is expected at given location. |
| */ |
| static ItemAt itemAt(int position, ItemLocation location) { |
| return new ItemAt(position, location); |
| } |
| |
| /** |
| * When scroll to scrollPosition, item at position is expected at given location. |
| */ |
| static ItemAt itemAt(int scrollPosition, int position, ItemLocation location) { |
| return new ItemAt(scrollPosition, position, location); |
| } |
| |
| void prepareKeyLineTest(int numItems) throws Throwable { |
| Intent intent = new Intent(); |
| intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear); |
| int[] items = new int[numItems]; |
| for (int i = 0; i < items.length; i++) { |
| items[i] = 32; |
| } |
| intent.putExtra(GridActivity.EXTRA_ITEMS, items); |
| intent.putExtra(GridActivity.EXTRA_STAGGERED, false); |
| mOrientation = BaseGridView.HORIZONTAL; |
| mNumRows = 1; |
| |
| initActivity(intent); |
| } |
| |
| public void testPreferKeyLine(final int windowAlignment, |
| final boolean preferKeyLineOverLow, |
| final boolean preferKeyLineOverHigh, |
| ItemLocation assertFirstItemLocation, |
| ItemLocation assertLastItemLocation) throws Throwable { |
| testPreferKeyLine(windowAlignment, preferKeyLineOverLow, preferKeyLineOverHigh, |
| itemAt(0, assertFirstItemLocation), |
| itemAt(mActivity.mNumItems - 1, assertLastItemLocation)); |
| } |
| |
| public void testPreferKeyLine(final int windowAlignment, |
| final boolean preferKeyLineOverLow, |
| final boolean preferKeyLineOverHigh, |
| ItemLocation assertFirstItemLocation, |
| ItemAt assertLastItemLocation) throws Throwable { |
| testPreferKeyLine(windowAlignment, preferKeyLineOverLow, preferKeyLineOverHigh, |
| itemAt(0, assertFirstItemLocation), |
| assertLastItemLocation); |
| } |
| |
| public void testPreferKeyLine(final int windowAlignment, |
| final boolean preferKeyLineOverLow, |
| final boolean preferKeyLineOverHigh, |
| ItemAt assertFirstItemLocation, |
| ItemLocation assertLastItemLocation) throws Throwable { |
| testPreferKeyLine(windowAlignment, preferKeyLineOverLow, preferKeyLineOverHigh, |
| assertFirstItemLocation, |
| itemAt(mActivity.mNumItems - 1, assertLastItemLocation)); |
| } |
| |
| public void testPreferKeyLine(final int windowAlignment, |
| final boolean preferKeyLineOverLow, |
| final boolean preferKeyLineOverHigh, |
| ItemAt assertFirstItemLocation, |
| ItemAt assertLastItemLocation) throws Throwable { |
| TestPreferKeyLineOptions options = new TestPreferKeyLineOptions(); |
| options.mAssertItemLocations = new ItemAt[] {assertFirstItemLocation, |
| assertLastItemLocation}; |
| options.mPreferKeyLineOverLow = preferKeyLineOverLow; |
| options.mPreferKeyLineOverHigh = preferKeyLineOverHigh; |
| options.mWindowAlignment = windowAlignment; |
| |
| options.mRtl = false; |
| testPreferKeyLine(options); |
| |
| options.mRtl = true; |
| testPreferKeyLine(options); |
| } |
| |
| static class TestPreferKeyLineOptions { |
| int mWindowAlignment; |
| boolean mPreferKeyLineOverLow; |
| boolean mPreferKeyLineOverHigh; |
| ItemAt[] mAssertItemLocations; |
| boolean mRtl; |
| } |
| |
| public void testPreferKeyLine(final TestPreferKeyLineOptions options) throws Throwable { |
| startWaitLayout(); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| if (options.mRtl) { |
| mGridView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); |
| } else { |
| mGridView.setLayoutDirection(View.LAYOUT_DIRECTION_LTR); |
| } |
| mGridView.setWindowAlignment(options.mWindowAlignment); |
| mGridView.setWindowAlignmentOffsetPercent(50); |
| mGridView.setWindowAlignmentOffset(0); |
| mGridView.setWindowAlignmentPreferKeyLineOverLowEdge(options.mPreferKeyLineOverLow); |
| mGridView.setWindowAlignmentPreferKeyLineOverHighEdge( |
| options.mPreferKeyLineOverHigh); |
| } |
| }); |
| waitForLayout(); |
| |
| final int paddingStart = mGridView.getPaddingStart(); |
| final int paddingEnd = mGridView.getPaddingEnd(); |
| final int windowAlignCenter = mGridView.getWidth() / 2; |
| |
| for (int i = 0; i < options.mAssertItemLocations.length; i++) { |
| ItemAt assertItemLocation = options.mAssertItemLocations[i]; |
| setSelectedPosition(assertItemLocation.mScrollPosition); |
| View view = mGridView.findViewHolderForAdapterPosition(assertItemLocation.mPosition) |
| .itemView; |
| switch (assertItemLocation.mLocation) { |
| case ITEM_AT_LOW: |
| if (options.mRtl) { |
| assertEquals(mGridView.getWidth() - paddingStart, view.getRight()); |
| } else { |
| assertEquals(paddingStart, view.getLeft()); |
| } |
| break; |
| case ITEM_AT_HIGH: |
| if (options.mRtl) { |
| assertEquals(paddingEnd, view.getLeft()); |
| } else { |
| assertEquals(mGridView.getWidth() - paddingEnd, view.getRight()); |
| } |
| break; |
| case ITEM_AT_KEY_LINE: |
| assertEquals(windowAlignCenter, (view.getLeft() + view.getRight()) / 2, DELTA); |
| break; |
| } |
| } |
| } |
| |
| @Test |
| public void testPreferKeyLine1() throws Throwable { |
| prepareKeyLineTest(1); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, false, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, true, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, false, |
| ItemLocation.ITEM_AT_HIGH, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, false, |
| ItemLocation.ITEM_AT_HIGH, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, false, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, true, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| } |
| |
| @Test |
| public void testPreferKeyLine2() throws Throwable { |
| prepareKeyLineTest(2); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, false, |
| ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, true, |
| ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, false, |
| itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE), |
| itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, true, |
| itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE), |
| itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE)); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, false, |
| itemAt(0, 1, ItemLocation.ITEM_AT_HIGH), |
| itemAt(1, 1, ItemLocation.ITEM_AT_HIGH)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, true, |
| itemAt(0, 0, ItemLocation.ITEM_AT_KEY_LINE), |
| itemAt(1, 0, ItemLocation.ITEM_AT_KEY_LINE)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, false, |
| itemAt(0, 1, ItemLocation.ITEM_AT_HIGH), |
| itemAt(1, 1, ItemLocation.ITEM_AT_HIGH)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, true, |
| itemAt(0, 0, ItemLocation.ITEM_AT_KEY_LINE), |
| itemAt(1, 0, ItemLocation.ITEM_AT_KEY_LINE)); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, false, |
| ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, true, |
| ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, false, |
| itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE), |
| itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE)); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, true, |
| itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE), |
| itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE)); |
| } |
| |
| @Test |
| public void testPreferKeyLine10000() throws Throwable { |
| prepareKeyLineTest(10000); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, false, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, true, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, false, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, true, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, false, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, true, |
| ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH); |
| |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, false, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, true, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, false, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH); |
| testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, true, |
| ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH); |
| } |
| } |