1062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu/*
2062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * Copyright (C) 2015 The Android Open Source Project
3062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu *
4062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * Licensed under the Apache License, Version 2.0 (the "License");
5062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * you may not use this file except in compliance with the License.
6062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * You may obtain a copy of the License at
7062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu *
8062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu *      http://www.apache.org/licenses/LICENSE-2.0
9062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu *
10062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * Unless required by applicable law or agreed to in writing, software
11062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * distributed under the License is distributed on an "AS IS" BASIS,
12062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * See the License for the specific language governing permissions and
14062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu * limitations under the License.
15062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu */
16062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gupackage android.support.v17.leanback.widget;
17062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
183103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static org.junit.Assert.assertEquals;
193103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static org.junit.Assert.assertFalse;
203103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static org.junit.Assert.assertNotNull;
213103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static org.junit.Assert.assertNotSame;
22c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Guimport static org.junit.Assert.assertNull;
233103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static org.junit.Assert.assertSame;
243103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static org.junit.Assert.assertTrue;
2521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Guimport static org.mockito.Mockito.any;
2621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Guimport static org.mockito.Mockito.mock;
2721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Guimport static org.mockito.Mockito.timeout;
2821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Guimport static org.mockito.Mockito.verify;
2921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
305509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.content.Intent;
315509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.graphics.Canvas;
325509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.graphics.Color;
335509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.graphics.Rect;
345509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.graphics.drawable.ColorDrawable;
35b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Guimport android.os.Build;
365509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.os.Parcelable;
373103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.support.test.InstrumentationRegistry;
3835232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikasimport android.support.test.filters.LargeTest;
39b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Guimport android.support.test.filters.SdkSuppress;
4006dd2b62f48746fbb1447b171db882d0a458368eDake Guimport android.support.test.rule.ActivityTestRule;
4106dd2b62f48746fbb1447b171db882d0a458368eDake Guimport android.support.test.runner.AndroidJUnit4;
427d7bf9541e0203ec67df0fe53367e2c126355b9esusnataimport android.support.v17.leanback.test.R;
438e06d698aa47dfdea344d2529f2879489eb4610fDake Guimport android.support.v17.leanback.testutils.PollingCheck;
445509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
45e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Guimport android.support.v7.widget.DefaultItemAnimator;
465509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.support.v7.widget.RecyclerView;
475509e275a04396bfb16b3a217c5392a864398174Dake Guimport android.support.v7.widget.RecyclerViewAccessibilityDelegate;
483bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Guimport android.text.Selection;
493bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Guimport android.text.Spannable;
5089ded73522265e09a03fd04f4ffccef7118bdedbDake Guimport android.util.DisplayMetrics;
513bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Guimport android.util.SparseArray;
5200e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Guimport android.util.SparseIntArray;
5389ded73522265e09a03fd04f4ffccef7118bdedbDake Guimport android.util.TypedValue;
54062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Guimport android.view.KeyEvent;
55062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Guimport android.view.View;
56062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Guimport android.view.ViewGroup;
57c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Guimport android.widget.TextView;
58d1cab1b54104d55407335c5d649398635822fffdDake Gu
5921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Guimport org.junit.After;
6006dd2b62f48746fbb1447b171db882d0a458368eDake Guimport org.junit.Rule;
6106dd2b62f48746fbb1447b171db882d0a458368eDake Guimport org.junit.Test;
6206dd2b62f48746fbb1447b171db882d0a458368eDake Guimport org.junit.rules.TestName;
633103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport org.junit.runner.RunWith;
6406dd2b62f48746fbb1447b171db882d0a458368eDake Gu
653103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport java.util.ArrayList;
663103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport java.util.Arrays;
673103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport java.util.Comparator;
683103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport java.util.HashMap;
69e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Guimport java.util.HashSet;
7006dd2b62f48746fbb1447b171db882d0a458368eDake Gu
7135232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikas@LargeTest
7206dd2b62f48746fbb1447b171db882d0a458368eDake Gu@RunWith(AndroidJUnit4.class)
7306dd2b62f48746fbb1447b171db882d0a458368eDake Gupublic class GridWidgetTest {
74062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
7593b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu    private static final float DELTA = 1f;
76f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    private static final boolean HUMAN_DELAY = false;
777538845719cd1e588185ce9ae60320377862ef8dDake Gu    private static final long WAIT_FOR_SCROLL_IDLE_TIMEOUT_MS = 60000;
7821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    private static final int WAIT_FOR_LAYOUT_PASS_TIMEOUT_MS = 2000;
796d65d10a40b33e52a365610cb299771178a56824Dake Gu    private static final int WAIT_FOR_ITEM_ANIMATION_FINISH_TIMEOUT_MS = 6000;
80f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu
8142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    protected ActivityTestRule<GridActivity> mActivityTestRule;
82062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    protected GridActivity mActivity;
83062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    protected BaseGridView mGridView;
8485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    protected GridLayoutManager mLayoutManager;
8521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    private GridLayoutManager.OnLayoutCompleteListener mWaitLayoutListener;
86062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    protected int mOrientation;
87247741d74797105ba4f6d2834ec56dab32c14644Dake Gu    protected int mNumRows;
8821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    protected int[] mRemovedItems;
89062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
90062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    private final Comparator<View> mRowSortComparator = new Comparator<View>() {
91e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas        @Override
92062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu        public int compare(View lhs, View rhs) {
93062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu            if (mOrientation == BaseGridView.HORIZONTAL) {
94062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu                return lhs.getLeft() - rhs.getLeft();
95062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu            } else {
96062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu                return lhs.getTop() - rhs.getTop();
97062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu            }
98062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu        };
99062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    };
100062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
101062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    /**
102062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu     * Verify margins between items on same row are same.
103062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu     */
104062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    private final Runnable mVerifyLayout = new Runnable() {
105062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu        @Override
106062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu        public void run() {
107e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            verifyMargin();
108062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu        }
109062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    };
110062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
11106dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Rule public TestName testName = new TestName();
11206dd2b62f48746fbb1447b171db882d0a458368eDake Gu
11306dd2b62f48746fbb1447b171db882d0a458368eDake Gu    public static void sendKey(int keyCode) {
11406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keyCode);
11506dd2b62f48746fbb1447b171db882d0a458368eDake Gu    }
11606dd2b62f48746fbb1447b171db882d0a458368eDake Gu
11706dd2b62f48746fbb1447b171db882d0a458368eDake Gu    public static void sendRepeatedKeys(int repeats, int keyCode) {
11806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        for (int i = 0; i < repeats; i++) {
11906dd2b62f48746fbb1447b171db882d0a458368eDake Gu            InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keyCode);
12006dd2b62f48746fbb1447b171db882d0a458368eDake Gu        }
121062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    }
122062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
123f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    private void humanDelay(int delay) throws InterruptedException {
124f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        if (HUMAN_DELAY) Thread.sleep(delay);
125f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    }
126f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    /**
127f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu     * Change size of the Adapter and notifyDataSetChanged.
128f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu     */
129f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    private void changeArraySize(final int size) throws Throwable {
13021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
131e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
132f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu            public void run() {
133f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu                mActivity.changeArraySize(size);
134f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu            }
135f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        });
136f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    }
137f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu
138580515488b23ac8a39795d11aef985c0f05c467eDake Gu    static String dumpGridView(BaseGridView gridView) {
139580515488b23ac8a39795d11aef985c0f05c467eDake Gu        return "findFocus:" + gridView.getRootView().findFocus()
140580515488b23ac8a39795d11aef985c0f05c467eDake Gu                + " isLayoutRequested:" + gridView.isLayoutRequested()
141580515488b23ac8a39795d11aef985c0f05c467eDake Gu                + " selectedPosition:" + gridView.getSelectedPosition()
142580515488b23ac8a39795d11aef985c0f05c467eDake Gu                + " adapter.itemCount:" + gridView.getAdapter().getItemCount()
143580515488b23ac8a39795d11aef985c0f05c467eDake Gu                + " itemAnimator.isRunning:" + gridView.getItemAnimator().isRunning()
144580515488b23ac8a39795d11aef985c0f05c467eDake Gu                + " scrollState:" + gridView.getScrollState();
145580515488b23ac8a39795d11aef985c0f05c467eDake Gu    }
146580515488b23ac8a39795d11aef985c0f05c467eDake Gu
147f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    /**
148f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu     * Change selected position.
149f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu     */
150f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    private void setSelectedPosition(final int position, final int scrollExtra) throws Throwable {
151bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        startWaitLayout();
15242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
153e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
154f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu            public void run() {
155f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu                mGridView.setSelectedPosition(position, scrollExtra);
156f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu            }
157f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        });
158bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        waitForLayout(false);
159bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    }
160bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
161bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    private void setSelectedPosition(final int position) throws Throwable {
162bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(position, 0);
163f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu    }
164f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu
165b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    private void setSelectedPositionSmooth(final int position) throws Throwable {
166b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
167b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            @Override
168b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            public void run() {
169b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                mGridView.setSelectedPositionSmooth(position);
170b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            }
171b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        });
172b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
173e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    /**
174a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu     * Scrolls using given key.
175a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu     */
176a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu    protected void scroll(int key, Runnable verify) throws Throwable {
177a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        do {
178a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            if (verify != null) {
17942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas                mActivityTestRule.runOnUiThread(verify);
180a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            }
181a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            sendRepeatedKeys(10, key);
182a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            try {
1838c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                Thread.sleep(300);
184a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            } catch (InterruptedException ex) {
185a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu                break;
186a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            }
1873103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        } while (mGridView.getLayoutManager().isSmoothScrolling()
1883103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                || mGridView.getScrollState() != BaseGridView.SCROLL_STATE_IDLE);
189a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu    }
190a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu
191a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu    protected void scrollToBegin(Runnable verify) throws Throwable {
192a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        int key;
193b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        // first move to first column/row
194b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        if (mOrientation == BaseGridView.HORIZONTAL) {
195b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            key = KeyEvent.KEYCODE_DPAD_UP;
196b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        } else {
197b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
198b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu                key = KeyEvent.KEYCODE_DPAD_RIGHT;
199b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            } else {
200b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu                key = KeyEvent.KEYCODE_DPAD_LEFT;
201b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            }
202b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        }
203b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        scroll(key, null);
204a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        if (mOrientation == BaseGridView.HORIZONTAL) {
205a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
206a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu                key = KeyEvent.KEYCODE_DPAD_RIGHT;
207a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            } else {
208a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu                key = KeyEvent.KEYCODE_DPAD_LEFT;
209a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            }
210a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        } else {
211a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            key = KeyEvent.KEYCODE_DPAD_UP;
212a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        }
213a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scroll(key, verify);
214a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu    }
215a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu
216a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu    protected void scrollToEnd(Runnable verify) throws Throwable {
217a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        int key;
218b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        // first move to first column/row
219b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        if (mOrientation == BaseGridView.HORIZONTAL) {
220b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            key = KeyEvent.KEYCODE_DPAD_UP;
221b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        } else {
222b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
223b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu                key = KeyEvent.KEYCODE_DPAD_RIGHT;
224b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            } else {
225b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu                key = KeyEvent.KEYCODE_DPAD_LEFT;
226b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            }
227b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        }
228b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        scroll(key, null);
229a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        if (mOrientation == BaseGridView.HORIZONTAL) {
230a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
231a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu                key = KeyEvent.KEYCODE_DPAD_LEFT;
232a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            } else {
233a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu                key = KeyEvent.KEYCODE_DPAD_RIGHT;
234a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            }
235a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        } else {
236a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu            key = KeyEvent.KEYCODE_DPAD_DOWN;
237a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        }
238a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scroll(key, verify);
239a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu    }
240a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu
241a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu    /**
242e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu     * Group and sort children by their position on each row (HORIZONTAL) or column(VERTICAL).
243e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu     */
244e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    protected View[][] sortByRows() {
245e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        final HashMap<Integer, ArrayList<View>> rows = new HashMap<Integer, ArrayList<View>>();
246abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas        ArrayList<Integer> rowLocations = new ArrayList<>();
247e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        for (int i = 0; i < mGridView.getChildCount(); i++) {
248e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            View v = mGridView.getChildAt(i);
249e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            int rowLocation;
250e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            if (mOrientation == BaseGridView.HORIZONTAL) {
251e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                rowLocation = v.getTop();
252e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            } else {
2533103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                rowLocation = mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL
2543103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        ? v.getRight() : v.getLeft();
255e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            }
256e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            ArrayList<View> views = rows.get(rowLocation);
257e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            if (views == null) {
258e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                views = new ArrayList<View>();
259e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                rows.put(rowLocation, views);
260c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                rowLocations.add(rowLocation);
261e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            }
262e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            views.add(v);
263e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        }
264c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        Object[] sortedLocations = rowLocations.toArray();
265c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        Arrays.sort(sortedLocations);
266c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        if (mNumRows != rows.size()) {
267c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            assertEquals("Dump Views by rows "+rows, mNumRows, rows.size());
268c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        }
269e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        View[][] sorted = new View[rows.size()][];
270c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        for (int i = 0; i < rowLocations.size(); i++) {
271c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            Integer rowLocation = rowLocations.get(i);
272c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            ArrayList<View> arr = rows.get(rowLocation);
273e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            View[] views = arr.toArray(new View[arr.size()]);
274e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            Arrays.sort(views, mRowSortComparator);
275c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            sorted[i] = views;
276e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        }
277e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        return sorted;
278e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    }
279e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
280e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    protected void verifyMargin() {
281e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        View[][] sorted = sortByRows();
282e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        for (int row = 0; row < sorted.length; row++) {
283e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            View[] views = sorted[row];
284e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            int margin = -1;
285e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            for (int i = 1; i < views.length; i++) {
286e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                if (mOrientation == BaseGridView.HORIZONTAL) {
287492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu                    assertEquals(mGridView.getHorizontalMargin(),
288492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu                            views[i].getLeft() - views[i - 1].getRight());
289e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                } else {
290492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu                    assertEquals(mGridView.getVerticalMargin(),
291492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu                            views[i].getTop() - views[i - 1].getBottom());
292e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                }
293e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            }
294e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        }
295e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    }
296e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
297e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    protected void verifyBeginAligned() {
298e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        View[][] sorted = sortByRows();
299e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        int alignedLocation = 0;
300e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        if (mOrientation == BaseGridView.HORIZONTAL) {
301e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
302e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                for (int i = 0; i < sorted.length; i++) {
303e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    if (i == 0) {
304e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                        alignedLocation = sorted[i][sorted[i].length - 1].getRight();
305e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    } else {
306e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                        assertEquals(alignedLocation, sorted[i][sorted[i].length - 1].getRight());
307e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    }
308e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                }
309e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            } else {
310e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                for (int i = 0; i < sorted.length; i++) {
311e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    if (i == 0) {
312e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                        alignedLocation = sorted[i][0].getLeft();
313e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    } else {
314e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                        assertEquals(alignedLocation, sorted[i][0].getLeft());
315e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    }
316e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                }
317e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            }
318e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        } else {
319e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            for (int i = 0; i < sorted.length; i++) {
320e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                if (i == 0) {
321e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    alignedLocation = sorted[i][0].getTop();
322e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                } else {
323e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                    assertEquals(alignedLocation, sorted[i][0].getTop());
324e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu                }
325e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu            }
326e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        }
327e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    }
328e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
329c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu    protected int[] getEndEdges() {
330c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        View[][] sorted = sortByRows();
331c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        int[] edges = new int[sorted.length];
332c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        if (mOrientation == BaseGridView.HORIZONTAL) {
333c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
334c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                for (int i = 0; i < sorted.length; i++) {
335c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                    edges[i] = sorted[i][0].getLeft();
336c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                }
337c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            } else {
338c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                for (int i = 0; i < sorted.length; i++) {
339c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                    edges[i] = sorted[i][sorted[i].length - 1].getRight();
340c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                }
341c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            }
342c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        } else {
343c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            for (int i = 0; i < sorted.length; i++) {
344c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                edges[i] = sorted[i][sorted[i].length - 1].getBottom();
345c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            }
346c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        }
347c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        return edges;
348c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu    }
349c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
350c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu    protected void verifyEdgesSame(int[] edges, int[] edges2) {
351c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        assertEquals(edges.length, edges2.length);
352c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        for (int i = 0; i < edges.length; i++) {
353c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu            assertEquals(edges[i], edges2[i]);
354c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        }
355c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu    }
356c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
35785df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    protected void verifyBoundCount(int count) {
35885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        if (mActivity.getBoundCount() != count) {
35985df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu            StringBuffer b = new StringBuffer();
36085df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu            b.append("ItemsLength: ");
36185df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu            for (int i = 0; i < mActivity.mItemLengths.length; i++) {
36285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                b.append(mActivity.mItemLengths[i]).append(",");
36385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu            }
36485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu            assertEquals("Bound count does not match, ItemsLengths: "+ b,
36585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                    count, mActivity.getBoundCount());
36685df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        }
36785df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    }
36885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
3698c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    private static int getCenterY(View v) {
3708c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        return (v.getTop() + v.getBottom())/2;
3718c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    }
372062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
3738c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    private static int getCenterX(View v) {
3748c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        return (v.getLeft() + v.getRight())/2;
3758c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    }
3768c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
37742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    private void initActivity(Intent intent) throws Throwable {
37842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule = new ActivityTestRule<GridActivity>(GridActivity.class, false, false);
37942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivity = mActivityTestRule.launchActivity(intent);
38042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
381e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas                @Override
3828c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                public void run() {
38306dd2b62f48746fbb1447b171db882d0a458368eDake Gu                    mActivity.setTitle(testName.getMethodName());
3848c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                }
3858c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            });
38642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        Thread.sleep(1000);
3878c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        mGridView = mActivity.mGridView;
38821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mLayoutManager = (GridLayoutManager) mGridView.getLayoutManager();
38921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    }
39021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
39121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    @After
39221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    public void clearTest() {
39321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mWaitLayoutListener = null;
39421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mLayoutManager = null;
39521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mGridView = null;
39621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mActivity = null;
39721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mActivityTestRule = null;
39821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    }
39921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
40021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    /**
40121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     * Must be called before waitForLayout() to prepare layout listener.
40221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     */
40321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    protected void startWaitLayout() {
40421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        if (mWaitLayoutListener != null) {
40521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            throw new IllegalStateException("startWaitLayout() already called");
40621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        }
40721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        if (mLayoutManager.mLayoutCompleteListener != null) {
40821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            throw new IllegalStateException("Cannot startWaitLayout()");
40921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        }
41021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mWaitLayoutListener = mLayoutManager.mLayoutCompleteListener =
41121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mock(GridLayoutManager.OnLayoutCompleteListener.class);
41221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    }
41321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
41421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    /**
41521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     * wait layout to be called and remove the listener.
41621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     */
41721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    protected void waitForLayout() {
418bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        waitForLayout(true);
419bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    }
420bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
421bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    /**
422bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu     * wait layout to be called and remove the listener.
423bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu     * @param force True if always wait regardless if layout requested
424bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu     */
425bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    protected void waitForLayout(boolean force) {
42621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        if (mWaitLayoutListener == null) {
42721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            throw new IllegalStateException("startWaitLayout() not called");
42821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        }
42921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        if (mWaitLayoutListener != mLayoutManager.mLayoutCompleteListener) {
43021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            throw new IllegalStateException("layout listener inconistent");
43121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        }
43221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        try {
433bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            if (force || mGridView.isLayoutRequested()) {
434bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                verify(mWaitLayoutListener, timeout(WAIT_FOR_LAYOUT_PASS_TIMEOUT_MS).atLeastOnce())
435bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                        .onLayoutCompleted(any(RecyclerView.State.class));
436bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            }
43721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        } finally {
43821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            mWaitLayoutListener = null;
43921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            mLayoutManager.mLayoutCompleteListener = null;
44021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        }
44121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    }
44221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
44321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    /**
44421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     * If currently running animator, wait for it to finish, otherwise return immediately.
44521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     * To wait the ItemAnimator start, you can use waitForLayout() to make sure layout pass has
44621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     * processed adapter change.
44721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     */
448134b0891c25facf14c53ef939846010284025ca9Dake Gu    protected void waitForItemAnimation(int timeoutMs) throws Throwable {
449134b0891c25facf14c53ef939846010284025ca9Dake Gu        final RecyclerView.ItemAnimator.ItemAnimatorFinishedListener listener = mock(
45021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                RecyclerView.ItemAnimator.ItemAnimatorFinishedListener.class);
451134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
452134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
453134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
454134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.getItemAnimator().isRunning(listener);
455134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
456134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
457134b0891c25facf14c53ef939846010284025ca9Dake Gu        verify(listener, timeout(timeoutMs).atLeastOnce()).onAnimationsFinished();
45821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    }
45921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
460134b0891c25facf14c53ef939846010284025ca9Dake Gu    protected void waitForItemAnimation() throws Throwable {
461e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        waitForItemAnimation(WAIT_FOR_ITEM_ANIMATION_FINISH_TIMEOUT_MS);
462e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    }
463e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
464e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    /**
465e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu     * wait animation start
466e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu     */
467e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    protected void waitForItemAnimationStart() throws Throwable {
468e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        long totalWait = 0;
469e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        while (!mGridView.getItemAnimator().isRunning()) {
470e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            Thread.sleep(10);
471e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            if ((totalWait += 10) > WAIT_FOR_ITEM_ANIMATION_FINISH_TIMEOUT_MS) {
472e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                throw new RuntimeException("waitForItemAnimationStart Timeout");
473e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
474e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        }
475e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    }
476e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
47721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    /**
47821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     * Run task in UI thread and wait for layout and ItemAnimator finishes.
47921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     */
48021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    protected void performAndWaitForAnimation(Runnable task) throws Throwable {
48121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        startWaitLayout();
48221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        mActivityTestRule.runOnUiThread(task);
48321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForLayout();
48421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForItemAnimation();
48521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    }
48621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
48721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    protected void waitForScrollIdle() throws Throwable {
48821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(null);
48921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    }
49021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu
49121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    /**
49221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     * Wait for grid view stop scroll and optionally verify state of grid view.
49321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu     */
49421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu    protected void waitForScrollIdle(Runnable verify) throws Throwable {
49521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        Thread.sleep(100);
49621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        int total = 0;
49721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        while (mGridView.getLayoutManager().isSmoothScrolling()
49821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                || mGridView.getScrollState() != BaseGridView.SCROLL_STATE_IDLE) {
49921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            if ((total += 100) >= WAIT_FOR_SCROLL_IDLE_TIMEOUT_MS) {
50021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                throw new RuntimeException("waitForScrollIdle Timeout");
50121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
50221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            try {
50321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                Thread.sleep(100);
50421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            } catch (InterruptedException ex) {
50521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                break;
50621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
50721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            if (verify != null) {
50821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mActivityTestRule.runOnUiThread(verify);
50921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
51021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        }
5118c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    }
5128c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
51306dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
5148c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    public void testThreeRowHorizontalBasic() throws Throwable {
51506dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
516247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid);
517e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100);
5188c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
519247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
520247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mNumRows = 3;
521062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
522a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
523e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
524a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToBegin(mVerifyLayout);
525062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
526e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        verifyBeginAligned();
527062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu    }
528062f7f7667bce6e9bf4814d0bb5344fe518ed89eDake Gu
5295509e275a04396bfb16b3a217c5392a864398174Dake Gu    static class DividerDecoration extends RecyclerView.ItemDecoration {
5305509e275a04396bfb16b3a217c5392a864398174Dake Gu
5315509e275a04396bfb16b3a217c5392a864398174Dake Gu        private ColorDrawable mTopDivider;
5325509e275a04396bfb16b3a217c5392a864398174Dake Gu        private ColorDrawable mBottomDivider;
5335509e275a04396bfb16b3a217c5392a864398174Dake Gu        private int mLeftOffset;
5345509e275a04396bfb16b3a217c5392a864398174Dake Gu        private int mRightOffset;
5355509e275a04396bfb16b3a217c5392a864398174Dake Gu        private int mTopOffset;
5365509e275a04396bfb16b3a217c5392a864398174Dake Gu        private int mBottomOffset;
5375509e275a04396bfb16b3a217c5392a864398174Dake Gu
5385509e275a04396bfb16b3a217c5392a864398174Dake Gu        DividerDecoration(int leftOffset, int topOffset, int rightOffset, int bottomOffset) {
5395509e275a04396bfb16b3a217c5392a864398174Dake Gu            mLeftOffset = leftOffset;
5405509e275a04396bfb16b3a217c5392a864398174Dake Gu            mTopOffset = topOffset;
5415509e275a04396bfb16b3a217c5392a864398174Dake Gu            mRightOffset = rightOffset;
5425509e275a04396bfb16b3a217c5392a864398174Dake Gu            mBottomOffset = bottomOffset;
5435509e275a04396bfb16b3a217c5392a864398174Dake Gu        }
5445509e275a04396bfb16b3a217c5392a864398174Dake Gu
5455509e275a04396bfb16b3a217c5392a864398174Dake Gu        @Override
5465509e275a04396bfb16b3a217c5392a864398174Dake Gu        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
5475509e275a04396bfb16b3a217c5392a864398174Dake Gu            if (mTopDivider == null) {
5485509e275a04396bfb16b3a217c5392a864398174Dake Gu                mTopDivider = new ColorDrawable(Color.RED);
5495509e275a04396bfb16b3a217c5392a864398174Dake Gu            }
5505509e275a04396bfb16b3a217c5392a864398174Dake Gu            if (mBottomDivider == null) {
5515509e275a04396bfb16b3a217c5392a864398174Dake Gu                mBottomDivider = new ColorDrawable(Color.BLUE);
5525509e275a04396bfb16b3a217c5392a864398174Dake Gu            }
5535509e275a04396bfb16b3a217c5392a864398174Dake Gu            final int childCount = parent.getChildCount();
5545509e275a04396bfb16b3a217c5392a864398174Dake Gu            final int width = parent.getWidth();
5555509e275a04396bfb16b3a217c5392a864398174Dake Gu            for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) {
5565509e275a04396bfb16b3a217c5392a864398174Dake Gu                final View view = parent.getChildAt(childViewIndex);
5575509e275a04396bfb16b3a217c5392a864398174Dake Gu                mTopDivider.setBounds(0, (int) view.getY() - mTopOffset, width, (int) view.getY());
5585509e275a04396bfb16b3a217c5392a864398174Dake Gu                mTopDivider.draw(c);
5595509e275a04396bfb16b3a217c5392a864398174Dake Gu                mBottomDivider.setBounds(0, (int) view.getY() + view.getHeight(), width,
5605509e275a04396bfb16b3a217c5392a864398174Dake Gu                        (int) view.getY() + view.getHeight() + mBottomOffset);
5615509e275a04396bfb16b3a217c5392a864398174Dake Gu                mBottomDivider.draw(c);
5625509e275a04396bfb16b3a217c5392a864398174Dake Gu            }
5635509e275a04396bfb16b3a217c5392a864398174Dake Gu        }
5645509e275a04396bfb16b3a217c5392a864398174Dake Gu
5655509e275a04396bfb16b3a217c5392a864398174Dake Gu        @Override
5665509e275a04396bfb16b3a217c5392a864398174Dake Gu        public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
5675509e275a04396bfb16b3a217c5392a864398174Dake Gu                                   RecyclerView.State state) {
5685509e275a04396bfb16b3a217c5392a864398174Dake Gu            outRect.left = mLeftOffset;
5695509e275a04396bfb16b3a217c5392a864398174Dake Gu            outRect.top = mTopOffset;
5705509e275a04396bfb16b3a217c5392a864398174Dake Gu            outRect.right = mRightOffset;
5715509e275a04396bfb16b3a217c5392a864398174Dake Gu            outRect.bottom = mBottomOffset;
5725509e275a04396bfb16b3a217c5392a864398174Dake Gu        }
5735509e275a04396bfb16b3a217c5392a864398174Dake Gu    }
5745509e275a04396bfb16b3a217c5392a864398174Dake Gu
57506dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
5765509e275a04396bfb16b3a217c5392a864398174Dake Gu    public void testItemDecorationAndMargins() throws Throwable {
5775509e275a04396bfb16b3a217c5392a864398174Dake Gu
5785509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int leftMargin = 3;
5795509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int topMargin = 4;
5805509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int rightMargin = 7;
5815509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int bottomMargin = 8;
5825509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int itemHeight = 100;
5835509e275a04396bfb16b3a217c5392a864398174Dake Gu
58406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
5855509e275a04396bfb16b3a217c5392a864398174Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
5865509e275a04396bfb16b3a217c5392a864398174Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{itemHeight, itemHeight, itemHeight});
5875509e275a04396bfb16b3a217c5392a864398174Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_MARGINS,
5885509e275a04396bfb16b3a217c5392a864398174Dake Gu                new int[]{leftMargin, topMargin, rightMargin, bottomMargin});
5895509e275a04396bfb16b3a217c5392a864398174Dake Gu        initActivity(intent);
5905509e275a04396bfb16b3a217c5392a864398174Dake Gu        mOrientation = BaseGridView.VERTICAL;
5915509e275a04396bfb16b3a217c5392a864398174Dake Gu        mNumRows = 1;
5925509e275a04396bfb16b3a217c5392a864398174Dake Gu
5935509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int paddingLeft = mGridView.getPaddingLeft();
5945509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int paddingTop = mGridView.getPaddingTop();
5955509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int verticalSpace = mGridView.getVerticalMargin();
5965509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int decorationLeft = 17;
5975509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int decorationTop = 1;
5985509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int decorationRight = 19;
5995509e275a04396bfb16b3a217c5392a864398174Dake Gu        final int decorationBottom = 2;
6005509e275a04396bfb16b3a217c5392a864398174Dake Gu
60121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
602e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
6035509e275a04396bfb16b3a217c5392a864398174Dake Gu            public void run() {
6045509e275a04396bfb16b3a217c5392a864398174Dake Gu                mGridView.addItemDecoration(new DividerDecoration(decorationLeft, decorationTop,
6055509e275a04396bfb16b3a217c5392a864398174Dake Gu                        decorationRight, decorationBottom));
6065509e275a04396bfb16b3a217c5392a864398174Dake Gu            }
6075509e275a04396bfb16b3a217c5392a864398174Dake Gu        });
6085509e275a04396bfb16b3a217c5392a864398174Dake Gu
6095509e275a04396bfb16b3a217c5392a864398174Dake Gu        View child0 = mGridView.getChildAt(0);
6105509e275a04396bfb16b3a217c5392a864398174Dake Gu        View child1 = mGridView.getChildAt(1);
6115509e275a04396bfb16b3a217c5392a864398174Dake Gu        View child2 = mGridView.getChildAt(2);
6125509e275a04396bfb16b3a217c5392a864398174Dake Gu
6135509e275a04396bfb16b3a217c5392a864398174Dake Gu        assertEquals(itemHeight, child0.getBottom() - child0.getTop());
6145509e275a04396bfb16b3a217c5392a864398174Dake Gu
6155509e275a04396bfb16b3a217c5392a864398174Dake Gu        // verify left margins
6165509e275a04396bfb16b3a217c5392a864398174Dake Gu        assertEquals(paddingLeft + leftMargin + decorationLeft, child0.getLeft());
6175509e275a04396bfb16b3a217c5392a864398174Dake Gu        assertEquals(paddingLeft + leftMargin + decorationLeft, child1.getLeft());
6185509e275a04396bfb16b3a217c5392a864398174Dake Gu        assertEquals(paddingLeft + leftMargin + decorationLeft, child2.getLeft());
6195509e275a04396bfb16b3a217c5392a864398174Dake Gu        // verify top bottom margins and decoration offset
6205509e275a04396bfb16b3a217c5392a864398174Dake Gu        assertEquals(paddingTop + topMargin + decorationTop, child0.getTop());
6215509e275a04396bfb16b3a217c5392a864398174Dake Gu        assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin,
6225509e275a04396bfb16b3a217c5392a864398174Dake Gu                child1.getTop() - child0.getBottom());
6235509e275a04396bfb16b3a217c5392a864398174Dake Gu        assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin,
6245509e275a04396bfb16b3a217c5392a864398174Dake Gu                child2.getTop() - child1.getBottom());
6255509e275a04396bfb16b3a217c5392a864398174Dake Gu
6265509e275a04396bfb16b3a217c5392a864398174Dake Gu    }
6275509e275a04396bfb16b3a217c5392a864398174Dake Gu
628b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
62906dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
630e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu    public void testItemDecorationAndMarginsAndOpticalBounds() throws Throwable {
631e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int leftMargin = 3;
632e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int topMargin = 4;
633e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int rightMargin = 7;
634e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int bottomMargin = 8;
635e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int itemHeight = 100;
636e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int ninePatchDrawableResourceId = R.drawable.lb_card_shadow_focused;
637e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
63806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
639e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
640e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{itemHeight, itemHeight, itemHeight});
641e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout);
642e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_MARGINS,
643e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                new int[]{leftMargin, topMargin, rightMargin, bottomMargin});
644e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        intent.putExtra(GridActivity.EXTRA_NINEPATCH_SHADOW, ninePatchDrawableResourceId);
645e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        initActivity(intent);
646e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        mOrientation = BaseGridView.VERTICAL;
647e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        mNumRows = 1;
648e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
649e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int paddingLeft = mGridView.getPaddingLeft();
650e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int paddingTop = mGridView.getPaddingTop();
651e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int verticalSpace = mGridView.getVerticalMargin();
652e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int decorationLeft = 17;
653e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int decorationTop = 1;
654e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int decorationRight = 19;
655e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int decorationBottom = 2;
656e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
657e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final Rect opticalPaddings = new Rect();
658b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        mGridView.getResources().getDrawable(ninePatchDrawableResourceId)
659b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu                .getPadding(opticalPaddings);
660e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int opticalInsetsLeft = opticalPaddings.left;
661e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int opticalInsetsTop = opticalPaddings.top;
662e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int opticalInsetsRight = opticalPaddings.right;
663e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        final int opticalInsetsBottom = opticalPaddings.bottom;
664e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertTrue(opticalInsetsLeft > 0);
665e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertTrue(opticalInsetsTop > 0);
666e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertTrue(opticalInsetsRight > 0);
667e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertTrue(opticalInsetsBottom > 0);
668e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
66921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
670e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
671e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu            public void run() {
672e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                mGridView.addItemDecoration(new DividerDecoration(decorationLeft, decorationTop,
673e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                        decorationRight, decorationBottom));
674e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu            }
675e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        });
676e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
677e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        View child0 = mGridView.getChildAt(0);
678e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        View child1 = mGridView.getChildAt(1);
679e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        View child2 = mGridView.getChildAt(2);
680e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
681e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertEquals(itemHeight + opticalInsetsTop + opticalInsetsBottom,
682e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                child0.getBottom() - child0.getTop());
683e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
684e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        // verify left margins decoration and optical insets
685e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertEquals(paddingLeft + leftMargin + decorationLeft - opticalInsetsLeft,
686e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                child0.getLeft());
687e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertEquals(paddingLeft + leftMargin + decorationLeft - opticalInsetsLeft,
688e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                child1.getLeft());
689e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertEquals(paddingLeft + leftMargin + decorationLeft - opticalInsetsLeft,
690e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                child2.getLeft());
691e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        // verify top bottom margins decoration offset and optical insets
692e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertEquals(paddingTop + topMargin + decorationTop, child0.getTop() + opticalInsetsTop);
693e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin,
694e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                (child1.getTop() + opticalInsetsTop) - (child0.getBottom() - opticalInsetsBottom));
695e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu        assertEquals(bottomMargin + decorationBottom + verticalSpace + decorationTop + topMargin,
696e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu                (child2.getTop() + opticalInsetsTop) - (child1.getBottom() - opticalInsetsBottom));
697e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
698e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu    }
699e2443a93fcb82151f5290b89617b34b69442fdd3Dake Gu
70006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
701e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    public void testThreeColumnVerticalBasic() throws Throwable {
702e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
70306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
704247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_grid);
705e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
7068c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
707247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mOrientation = BaseGridView.VERTICAL;
708247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mNumRows = 3;
709e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
710a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
711e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
712a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToBegin(mVerifyLayout);
71385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
71485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        verifyBeginAligned();
71585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    }
71685df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
71706dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
71885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    public void testRedundantAppendRemove() throws Throwable {
71906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
720247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
721247741d74797105ba4f6d2834ec56dab32c14644Dake Gu                R.layout.vertical_grid_testredundantappendremove);
72285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{
72385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                149,177,128,234,227,187,163,223,146,210,228,148,227,193,182,197,177,142,225,207,
72485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                157,171,209,204,187,184,123,221,197,153,202,179,193,214,226,173,225,143,188,159,
72585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                139,193,233,143,227,203,222,124,228,223,164,131,228,126,211,160,165,152,235,184,
72685df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                155,224,149,181,171,229,200,234,177,130,164,172,188,139,132,203,179,220,147,131,
72785df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                226,127,230,239,183,203,206,227,123,170,239,234,200,149,237,204,160,133,202,234,
72885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                173,122,139,149,151,153,216,231,121,145,227,153,186,174,223,180,123,215,206,216,
72985df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                239,222,219,207,193,218,140,133,171,153,183,132,233,138,159,174,189,171,143,128,
73085df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                152,222,141,202,224,190,134,120,181,231,230,136,132,224,136,210,207,150,128,183,
73185df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                221,194,179,220,126,221,137,205,223,193,172,132,226,209,133,191,227,127,159,171,
73285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                180,149,237,177,194,207,170,202,161,144,147,199,205,186,164,140,193,203,224,129});
7338c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
734247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mOrientation = BaseGridView.VERTICAL;
735247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mNumRows = 3;
73685df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
737a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
73885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
739a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToBegin(mVerifyLayout);
740e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu
741e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu        verifyBeginAligned();
742e7ead88853562603f76b92189a828ba14d5c4bcbDake Gu    }
74385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
74406dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
74585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    public void testRedundantAppendRemove2() throws Throwable {
74606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
747247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
748247741d74797105ba4f6d2834ec56dab32c14644Dake Gu                R.layout.horizontal_grid_testredundantappendremove2);
74985df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{
75085df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                318,333,199,224,246,273,269,289,340,313,265,306,349,269,185,282,257,354,316,252,
75185df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                237,290,283,343,196,313,290,343,191,262,342,228,343,349,251,203,226,305,265,213,
75285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                216,333,295,188,187,281,288,311,244,232,224,332,290,181,267,276,226,261,335,355,
75385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                225,217,219,183,234,285,257,304,182,250,244,223,257,219,342,185,347,205,302,315,
75485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                299,309,292,237,192,309,228,250,347,227,337,298,299,185,185,331,223,284,265,351});
7558c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
756247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
757247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mNumRows = 3;
75885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        mLayoutManager = (GridLayoutManager) mGridView.getLayoutManager();
75985df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
76085df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        // test append without staggered result cache
761a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
76285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
763c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        int[] endEdges = getEndEdges();
76485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
765a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToBegin(mVerifyLayout);
76685df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
76785df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        verifyBeginAligned();
76885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
76985df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        // now test append with staggered result cache
770f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(3);
77185df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        assertEquals("Staggerd cache should be kept as is when no item size change",
77285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu                100, ((StaggeredGrid) mLayoutManager.mGrid).mLocations.size());
77385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
774f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(100);
77585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
776a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
777c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
778c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        // we should get same aligned end edges
779c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        int[] endEdges2 = getEndEdges();
780c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        verifyEdgesSame(endEdges, endEdges2);
78185df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    }
78285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
783e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri
784e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri    @Test
785e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri    public void testLayoutWhenAViewIsInvalidated() throws Throwable {
786e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        Intent intent = new Intent();
787e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
788b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000);
789b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, true);
790b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
791e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        mNumRows = 1;
792e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        initActivity(intent);
793e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        mOrientation = BaseGridView.VERTICAL;
794e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        waitOneUiCycle();
795e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri
796b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        // push views to cache.
797e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        mActivityTestRule.runOnUiThread(new Runnable() {
798e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri            @Override
799e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri            public void run() {
800b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu                mActivity.mItemLengths[0] = mActivity.mItemLengths[0] * 3;
801b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu                mActivity.mGridView.getAdapter().notifyItemChanged(0);
802e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri            }
803e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        });
804b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        waitForItemAnimation();
805b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu
806b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        // notifyDataSetChange will mark the cached views FLAG_INVALID
807b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
808b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu            @Override
809b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu            public void run() {
810b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu                mActivity.mGridView.getAdapter().notifyDataSetChanged();
811b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu            }
812b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        });
813b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        waitForItemAnimation();
814e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri
815b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        // Cached views will be added in prelayout with FLAG_INVALID, in post layout we should
816b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        // handle it properly
817e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        mActivityTestRule.runOnUiThread(new Runnable() {
818e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri            @Override
819e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri            public void run() {
820b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu                mActivity.mItemLengths[0] = mActivity.mItemLengths[0] / 3;
821b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu                mActivity.mGridView.getAdapter().notifyItemChanged(0);
822e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri            }
823e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri        });
824b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu
825b39fea5dfc74a6f7c9bb6d7c8bd2d8d04a8b9778Dake Gu        waitForItemAnimation();
826e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri    }
827e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri
8284a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu    @Test
8294a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu    public void testWrongInsertViewIndexInFastRelayout() throws Throwable {
8304a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        Intent intent = new Intent();
8314a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
8324a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2);
8334a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
8344a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        mNumRows = 1;
8354a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        initActivity(intent);
8364a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        mOrientation = BaseGridView.VERTICAL;
8374a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu
8384a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        // removing two children, they will be hidden views as first 2 children of RV.
8394a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
8404a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            @Override
8414a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            public void run() {
8424a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu                mGridView.getItemAnimator().setRemoveDuration(2000);
8434a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu                mActivity.removeItems(0, 2);
8444a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            }
8454a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        });
8464a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        waitForItemAnimationStart();
8474a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu
8484a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        // add three views and notify change of the first item.
8494a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        startWaitLayout();
8504a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
8514a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            @Override
8524a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            public void run() {
8534a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu                mActivity.addItems(0, new int[]{161, 161, 161});
8544a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            }
8554a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        });
8564a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        waitForLayout();
8574a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        startWaitLayout();
8584a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
8594a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            @Override
8604a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            public void run() {
8614a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu                mGridView.getAdapter().notifyItemChanged(0);
8624a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu            }
8634a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        });
8644a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        waitForLayout();
8654a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        // after layout, the viewholder should still be the first child of LayoutManager.
8664a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu        assertEquals(0, mGridView.getChildAdapterPosition(
8674a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu                mGridView.getLayoutManager().getChildAt(0)));
8684a28bc44a3a3b0494fa790206f72de013b5bdedeDake Gu    }
869e79b22a10835076150c04e96c52d8342b3af8409Keyvan Amiri
8703d079d099a4426538d5f532f947771991c7c7703Dake Gu    @Test
8713d079d099a4426538d5f532f947771991c7c7703Dake Gu    public void testMoveIntoPrelayoutItems() throws Throwable {
8723d079d099a4426538d5f532f947771991c7c7703Dake Gu        Intent intent = new Intent();
8733d079d099a4426538d5f532f947771991c7c7703Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
8743d079d099a4426538d5f532f947771991c7c7703Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000);
8753d079d099a4426538d5f532f947771991c7c7703Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
8763d079d099a4426538d5f532f947771991c7c7703Dake Gu        mNumRows = 1;
8773d079d099a4426538d5f532f947771991c7c7703Dake Gu        initActivity(intent);
8783d079d099a4426538d5f532f947771991c7c7703Dake Gu        mOrientation = BaseGridView.VERTICAL;
8793d079d099a4426538d5f532f947771991c7c7703Dake Gu
8803d079d099a4426538d5f532f947771991c7c7703Dake Gu        final int lastItemPos = mGridView.getChildCount() - 1;
8813d079d099a4426538d5f532f947771991c7c7703Dake Gu        assertTrue(mGridView.getChildCount() >= 4);
8823d079d099a4426538d5f532f947771991c7c7703Dake Gu        // notify change of 3 items, so prelayout will layout extra 3 items, then move an item
8833d079d099a4426538d5f532f947771991c7c7703Dake Gu        // into the extra layout range. Post layout's fastRelayout() should handle this properly.
8843d079d099a4426538d5f532f947771991c7c7703Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
8853d079d099a4426538d5f532f947771991c7c7703Dake Gu            @Override
8863d079d099a4426538d5f532f947771991c7c7703Dake Gu            public void run() {
8873d079d099a4426538d5f532f947771991c7c7703Dake Gu                mGridView.getAdapter().notifyItemChanged(lastItemPos - 3);
8883d079d099a4426538d5f532f947771991c7c7703Dake Gu                mGridView.getAdapter().notifyItemChanged(lastItemPos - 2);
8893d079d099a4426538d5f532f947771991c7c7703Dake Gu                mGridView.getAdapter().notifyItemChanged(lastItemPos - 1);
8903d079d099a4426538d5f532f947771991c7c7703Dake Gu                mActivity.moveItem(900, lastItemPos + 2, true);
8913d079d099a4426538d5f532f947771991c7c7703Dake Gu            }
8923d079d099a4426538d5f532f947771991c7c7703Dake Gu        });
8933d079d099a4426538d5f532f947771991c7c7703Dake Gu        waitForItemAnimation();
8943d079d099a4426538d5f532f947771991c7c7703Dake Gu    }
8953d079d099a4426538d5f532f947771991c7c7703Dake Gu
8963d079d099a4426538d5f532f947771991c7c7703Dake Gu    @Test
8973d079d099a4426538d5f532f947771991c7c7703Dake Gu    public void testMoveIntoPrelayoutItems2() throws Throwable {
8983d079d099a4426538d5f532f947771991c7c7703Dake Gu        Intent intent = new Intent();
8993d079d099a4426538d5f532f947771991c7c7703Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
9003d079d099a4426538d5f532f947771991c7c7703Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000);
9013d079d099a4426538d5f532f947771991c7c7703Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
9023d079d099a4426538d5f532f947771991c7c7703Dake Gu        mNumRows = 1;
9033d079d099a4426538d5f532f947771991c7c7703Dake Gu        initActivity(intent);
9043d079d099a4426538d5f532f947771991c7c7703Dake Gu        mOrientation = BaseGridView.VERTICAL;
9053d079d099a4426538d5f532f947771991c7c7703Dake Gu
9063d079d099a4426538d5f532f947771991c7c7703Dake Gu        setSelectedPosition(999);
9073d079d099a4426538d5f532f947771991c7c7703Dake Gu        final int firstItemPos = mGridView.getChildAdapterPosition(mGridView.getChildAt(0));
9083d079d099a4426538d5f532f947771991c7c7703Dake Gu        assertTrue(mGridView.getChildCount() >= 4);
9093d079d099a4426538d5f532f947771991c7c7703Dake Gu        // notify change of 3 items, so prelayout will layout extra 3 items, then move an item
9103d079d099a4426538d5f532f947771991c7c7703Dake Gu        // into the extra layout range. Post layout's fastRelayout() should handle this properly.
9113d079d099a4426538d5f532f947771991c7c7703Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
9123d079d099a4426538d5f532f947771991c7c7703Dake Gu            @Override
9133d079d099a4426538d5f532f947771991c7c7703Dake Gu            public void run() {
9143d079d099a4426538d5f532f947771991c7c7703Dake Gu                mGridView.getAdapter().notifyItemChanged(firstItemPos + 1);
9153d079d099a4426538d5f532f947771991c7c7703Dake Gu                mGridView.getAdapter().notifyItemChanged(firstItemPos + 2);
9163d079d099a4426538d5f532f947771991c7c7703Dake Gu                mGridView.getAdapter().notifyItemChanged(firstItemPos + 3);
9173d079d099a4426538d5f532f947771991c7c7703Dake Gu                mActivity.moveItem(0, firstItemPos - 2, true);
9183d079d099a4426538d5f532f947771991c7c7703Dake Gu            }
9193d079d099a4426538d5f532f947771991c7c7703Dake Gu        });
9203d079d099a4426538d5f532f947771991c7c7703Dake Gu        waitForItemAnimation();
9213d079d099a4426538d5f532f947771991c7c7703Dake Gu    }
9223d079d099a4426538d5f532f947771991c7c7703Dake Gu
923134b0891c25facf14c53ef939846010284025ca9Dake Gu    void preparePredictiveLayout() throws Throwable {
924134b0891c25facf14c53ef939846010284025ca9Dake Gu        Intent intent = new Intent();
925ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear);
926134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100);
927134b0891c25facf14c53ef939846010284025ca9Dake Gu        initActivity(intent);
928134b0891c25facf14c53ef939846010284025ca9Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
929134b0891c25facf14c53ef939846010284025ca9Dake Gu        mNumRows = 1;
930134b0891c25facf14c53ef939846010284025ca9Dake Gu
931134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
932134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
933134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
934134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.getItemAnimator().setAddDuration(1000);
935134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.getItemAnimator().setRemoveDuration(1000);
936134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.getItemAnimator().setMoveDuration(1000);
937134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.getItemAnimator().setChangeDuration(1000);
938134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.setSelectedPositionSmooth(50);
939134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
940134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
941134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle(mVerifyLayout);
942134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
943134b0891c25facf14c53ef939846010284025ca9Dake Gu
944134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
945134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testPredictiveLayoutAdd1() throws Throwable {
946134b0891c25facf14c53ef939846010284025ca9Dake Gu        preparePredictiveLayout();
947134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
948134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
949134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
950134b0891c25facf14c53ef939846010284025ca9Dake Gu                mActivity.addItems(51, new int[]{300, 300, 300, 300});
951134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
952134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
953134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimationStart();
9546d65d10a40b33e52a365610cb299771178a56824Dake Gu        waitForItemAnimation();
955134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(50, mGridView.getSelectedPosition());
956134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState());
957134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
958134b0891c25facf14c53ef939846010284025ca9Dake Gu
959134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
960134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testPredictiveLayoutAdd2() throws Throwable {
961134b0891c25facf14c53ef939846010284025ca9Dake Gu        preparePredictiveLayout();
962134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
963134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
964134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
965134b0891c25facf14c53ef939846010284025ca9Dake Gu                mActivity.addItems(50, new int[]{300, 300, 300, 300});
966134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
967134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
968134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimationStart();
9696d65d10a40b33e52a365610cb299771178a56824Dake Gu        waitForItemAnimation();
970134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(54, mGridView.getSelectedPosition());
971134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState());
972134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
973134b0891c25facf14c53ef939846010284025ca9Dake Gu
974134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
975134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testPredictiveLayoutRemove1() throws Throwable {
976134b0891c25facf14c53ef939846010284025ca9Dake Gu        preparePredictiveLayout();
977134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
978134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
979134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
980134b0891c25facf14c53ef939846010284025ca9Dake Gu                mActivity.removeItems(51, 3);
981134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
982134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
983134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimationStart();
9846d65d10a40b33e52a365610cb299771178a56824Dake Gu        waitForItemAnimation();
985134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(50, mGridView.getSelectedPosition());
986134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState());
987134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
988134b0891c25facf14c53ef939846010284025ca9Dake Gu
989134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
990134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testPredictiveLayoutRemove2() throws Throwable {
991134b0891c25facf14c53ef939846010284025ca9Dake Gu        preparePredictiveLayout();
992134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
993134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
994134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
9952447d5ed8f4396fc6d1271df7f00ddf150bb5d41Dake Gu                mActivity.removeItems(47, 3);
996134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
997134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
998134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimationStart();
9996d65d10a40b33e52a365610cb299771178a56824Dake Gu        waitForItemAnimation();
1000134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(47, mGridView.getSelectedPosition());
1001134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState());
1002134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
1003134b0891c25facf14c53ef939846010284025ca9Dake Gu
1004134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
1005134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testPredictiveLayoutRemove3() throws Throwable {
1006134b0891c25facf14c53ef939846010284025ca9Dake Gu        preparePredictiveLayout();
1007134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1008134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1009134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1010134b0891c25facf14c53ef939846010284025ca9Dake Gu                mActivity.removeItems(0, 51);
1011134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1012134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1013134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimationStart();
10146d65d10a40b33e52a365610cb299771178a56824Dake Gu        waitForItemAnimation();
1015134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(0, mGridView.getSelectedPosition());
1016134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(RecyclerView.SCROLL_STATE_IDLE, mGridView.getScrollState());
1017134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
1018134b0891c25facf14c53ef939846010284025ca9Dake Gu
1019134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
1020ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu    public void testPredictiveOnMeasureWrapContent() throws Throwable {
1021ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        Intent intent = new Intent();
1022ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1023ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                R.layout.horizontal_linear_wrap_content);
1024ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        int count = 50;
1025ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, count);
1026ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        initActivity(intent);
1027ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1028ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        mNumRows = 1;
1029ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu
1030ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        waitForScrollIdle(mVerifyLayout);
1031ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1032ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            @Override
1033ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            public void run() {
1034ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                mGridView.setHasFixedSize(false);
1035ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            }
1036ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        });
1037ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu
1038ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        for (int i = 0; i < 30; i++) {
1039ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            final int oldCount = count;
1040ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            final int newCount = i;
1041ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            mActivityTestRule.runOnUiThread(new Runnable() {
1042ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                @Override
1043ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                public void run() {
1044ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                    if (oldCount > 0) {
1045ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                        mActivity.removeItems(0, oldCount);
1046ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                    }
1047ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                    if (newCount > 0) {
1048ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                        int[] newItems = new int[newCount];
1049ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                        for (int i = 0; i < newCount; i++) {
1050ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                            newItems[i] = 400;
1051ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                        }
1052ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                        mActivity.addItems(0, newItems);
1053ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                    }
1054ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu                }
1055ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            });
1056ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            waitForItemAnimationStart();
1057ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            waitForItemAnimation();
1058ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu            count = newCount;
1059ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu        }
1060ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu
1061ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu    }
1062ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu
1063ff5d512149869cd9e26c627d8bc6894297da0368Dake Gu    @Test
1064134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testPredictiveLayoutRemove4() throws Throwable {
1065134b0891c25facf14c53ef939846010284025ca9Dake Gu        Intent intent = new Intent();
1066134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1067134b0891c25facf14c53ef939846010284025ca9Dake Gu                R.layout.horizontal_grid);
1068134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
1069134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
1070134b0891c25facf14c53ef939846010284025ca9Dake Gu        initActivity(intent);
1071134b0891c25facf14c53ef939846010284025ca9Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1072134b0891c25facf14c53ef939846010284025ca9Dake Gu        mNumRows = 3;
1073134b0891c25facf14c53ef939846010284025ca9Dake Gu
1074134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1075134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1076134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1077134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.setSelectedPositionSmooth(50);
1078134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1079134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1080134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
1081134b0891c25facf14c53ef939846010284025ca9Dake Gu        performAndWaitForAnimation(new Runnable() {
1082134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1083134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1084134b0891c25facf14c53ef939846010284025ca9Dake Gu                mActivity.removeItems(0, 49);
1085134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1086134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1087134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(1, mGridView.getSelectedPosition());
1088134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
1089134b0891c25facf14c53ef939846010284025ca9Dake Gu
1090134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
1091134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testPredictiveLayoutRemove5() throws Throwable {
1092134b0891c25facf14c53ef939846010284025ca9Dake Gu        Intent intent = new Intent();
1093134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1094134b0891c25facf14c53ef939846010284025ca9Dake Gu                R.layout.horizontal_grid);
1095134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
1096134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, true);
1097134b0891c25facf14c53ef939846010284025ca9Dake Gu        initActivity(intent);
1098134b0891c25facf14c53ef939846010284025ca9Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1099134b0891c25facf14c53ef939846010284025ca9Dake Gu        mNumRows = 3;
1100134b0891c25facf14c53ef939846010284025ca9Dake Gu
1101134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1102134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1103134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1104134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.setSelectedPositionSmooth(50);
1105134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1106134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1107134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
1108134b0891c25facf14c53ef939846010284025ca9Dake Gu        performAndWaitForAnimation(new Runnable() {
1109134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1110134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1111134b0891c25facf14c53ef939846010284025ca9Dake Gu                mActivity.removeItems(50, 40);
1112134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1113134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1114134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(50, mGridView.getSelectedPosition());
1115134b0891c25facf14c53ef939846010284025ca9Dake Gu        scrollToBegin(mVerifyLayout);
1116134b0891c25facf14c53ef939846010284025ca9Dake Gu        verifyBeginAligned();
1117134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
1118134b0891c25facf14c53ef939846010284025ca9Dake Gu
1119c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    void waitOneUiCycle() throws Throwable {
1120c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1121c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1122c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1123c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1124c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1125c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    }
1126c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1127c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    @Test
1128c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    public void testDontPruneMovingItem() throws Throwable {
1129c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        Intent intent = new Intent();
1130c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear);
1131c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
1132c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000);
1133c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        initActivity(intent);
1134c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mOrientation = BaseGridView.HORIZONTAL;
1135c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mNumRows = 1;
1136c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1137c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1138c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1139c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1140c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.getItemAnimator().setMoveDuration(2000);
1141c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.setSelectedPosition(50);
1142c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1143c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1144c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitForScrollIdle();
1145c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        final ArrayList<RecyclerView.ViewHolder> moveViewHolders = new ArrayList();
1146c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        for (int i = 51;; i++) {
1147c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            RecyclerView.ViewHolder vh = mGridView.findViewHolderForAdapterPosition(i);
1148c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            if (vh == null) {
1149c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                break;
1150c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1151c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            moveViewHolders.add(vh);
1152c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        }
1153c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1154c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1155c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1156c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1157c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                // add a lot of items, so we will push everything to right of 51 out side window
1158c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                int[] lots_items = new int[1000];
1159c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                for (int i = 0; i < lots_items.length; i++) {
1160c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                    lots_items[i] = 300;
1161c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                }
1162c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mActivity.addItems(51, lots_items);
1163c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1164c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1165c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitOneUiCycle();
1166c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        // run a scroll pass, the scroll pass should not remove the animating views even they are
1167c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        // outside visible areas.
1168c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1169c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1170c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1171c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.scrollBy(-3, 0);
1172c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1173c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1174c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitOneUiCycle();
1175c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        for (int i = 0; i < moveViewHolders.size(); i++) {
1176c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            assertSame(mGridView, moveViewHolders.get(i).itemView.getParent());
1177c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        }
1178c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    }
1179c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1180c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    @Test
1181c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    public void testMoveItemToTheRight() throws Throwable {
1182c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        Intent intent = new Intent();
1183c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear);
1184c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
1185c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000);
1186c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        initActivity(intent);
1187c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mOrientation = BaseGridView.HORIZONTAL;
1188c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mNumRows = 1;
1189c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1190c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1191c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1192c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1193c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.getItemAnimator().setAddDuration(2000);
1194c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.getItemAnimator().setMoveDuration(2000);
1195c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.setSelectedPosition(50);
1196c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1197c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1198c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitForScrollIdle();
1199c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        RecyclerView.ViewHolder moveViewHolder = mGridView.findViewHolderForAdapterPosition(51);
1200c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1201c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        int lastPos = mGridView.getChildAdapterPosition(mGridView.getChildAt(
1202c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.getChildCount() - 1));
1203c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1204c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1205c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1206c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mActivity.moveItem(51, 1000, true);
1207c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1208c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1209c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        final ArrayList<View> moveInViewHolders = new ArrayList();
1210c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitForItemAnimationStart();
1211c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1212c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1213c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1214c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                for (int i = 0; i < mGridView.getLayoutManager().getChildCount(); i++) {
1215c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                    View v = mGridView.getLayoutManager().getChildAt(i);
12162447d5ed8f4396fc6d1271df7f00ddf150bb5d41Dake Gu                    if (mGridView.getChildAdapterPosition(v) >= 51) {
1217c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                        moveInViewHolders.add(v);
1218c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                    }
1219c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                }
1220c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1221c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1222c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitOneUiCycle();
1223c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertTrue("prelayout should layout extra items to slide in",
1224c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                moveInViewHolders.size() > lastPos - 51);
1225c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        // run a scroll pass, the scroll pass should not remove the animating views even they are
1226c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        // outside visible areas.
1227c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1228c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1229c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1230c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.scrollBy(-3, 0);
1231c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1232c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1233c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitOneUiCycle();
1234c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        for (int i = 0; i < moveInViewHolders.size(); i++) {
1235c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            assertSame(mGridView, moveInViewHolders.get(i).getParent());
1236c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        }
1237c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertSame(mGridView, moveViewHolder.itemView.getParent());
1238c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertFalse(moveViewHolder.isRecyclable());
1239c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitForItemAnimation();
1240c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertNull(moveViewHolder.itemView.getParent());
1241c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertTrue(moveViewHolder.isRecyclable());
1242c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    }
1243c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1244c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    @Test
1245c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    public void testMoveItemToTheLeft() throws Throwable {
1246c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        Intent intent = new Intent();
1247c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear);
1248c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
1249c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000);
1250c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        initActivity(intent);
1251c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mOrientation = BaseGridView.HORIZONTAL;
1252c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mNumRows = 1;
1253c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1254c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1255c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1256c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1257c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.getItemAnimator().setAddDuration(2000);
1258c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.getItemAnimator().setMoveDuration(2000);
1259c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.setSelectedPosition(1500);
1260c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1261c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1262c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitForScrollIdle();
1263c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        RecyclerView.ViewHolder moveViewHolder = mGridView.findViewHolderForAdapterPosition(1499);
1264c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1265c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        int firstPos = mGridView.getChildAdapterPosition(mGridView.getChildAt(0));
1266c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1267c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1268c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1269c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mActivity.moveItem(1499, 1, true);
1270c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1271c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1272c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        final ArrayList<View> moveInViewHolders = new ArrayList();
1273c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitForItemAnimationStart();
1274c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1275c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1276c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1277c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                for (int i = 0; i < mGridView.getLayoutManager().getChildCount(); i++) {
1278c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                    View v = mGridView.getLayoutManager().getChildAt(i);
12792447d5ed8f4396fc6d1271df7f00ddf150bb5d41Dake Gu                    if (mGridView.getChildAdapterPosition(v) <= 1499) {
1280c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                        moveInViewHolders.add(v);
1281c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                    }
1282c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                }
1283c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1284c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1285c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitOneUiCycle();
1286c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertTrue("prelayout should layout extra items to slide in ",
1287c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                moveInViewHolders.size() > 1499 - firstPos);
1288c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        // run a scroll pass, the scroll pass should not remove the animating views even they are
1289c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        // outside visible areas.
1290c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1291c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            @Override
1292c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            public void run() {
1293c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu                mGridView.scrollBy(3, 0);
1294c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            }
1295c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        });
1296c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitOneUiCycle();
1297c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        for (int i = 0; i < moveInViewHolders.size(); i++) {
1298c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu            assertSame(mGridView, moveInViewHolders.get(i).getParent());
1299c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        }
1300c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertSame(mGridView, moveViewHolder.itemView.getParent());
1301c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertFalse(moveViewHolder.isRecyclable());
1302c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        waitForItemAnimation();
1303c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertNull(moveViewHolder.itemView.getParent());
1304c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu        assertTrue(moveViewHolder.isRecyclable());
1305c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu    }
1306c50aca4940c8ae508393278aa7a9c77a3f93f87dDake Gu
1307134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
1308134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testContinuousSwapForward() throws Throwable {
1309134b0891c25facf14c53ef939846010284025ca9Dake Gu        Intent intent = new Intent();
1310134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1311134b0891c25facf14c53ef939846010284025ca9Dake Gu                R.layout.horizontal_linear);
1312134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
1313134b0891c25facf14c53ef939846010284025ca9Dake Gu        initActivity(intent);
1314134b0891c25facf14c53ef939846010284025ca9Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1315134b0891c25facf14c53ef939846010284025ca9Dake Gu        mNumRows = 1;
1316134b0891c25facf14c53ef939846010284025ca9Dake Gu
1317134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1318134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1319134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1320134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.setSelectedPositionSmooth(150);
1321134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1322134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1323134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle(mVerifyLayout);
1324134b0891c25facf14c53ef939846010284025ca9Dake Gu        for (int i = 150; i < 199; i++) {
1325134b0891c25facf14c53ef939846010284025ca9Dake Gu            final int swapIndex = i;
1326134b0891c25facf14c53ef939846010284025ca9Dake Gu            mActivityTestRule.runOnUiThread(new Runnable() {
1327134b0891c25facf14c53ef939846010284025ca9Dake Gu                @Override
1328134b0891c25facf14c53ef939846010284025ca9Dake Gu                public void run() {
1329134b0891c25facf14c53ef939846010284025ca9Dake Gu                    mActivity.swap(swapIndex, swapIndex + 1);
1330134b0891c25facf14c53ef939846010284025ca9Dake Gu                }
1331134b0891c25facf14c53ef939846010284025ca9Dake Gu            });
1332134b0891c25facf14c53ef939846010284025ca9Dake Gu            Thread.sleep(10);
1333134b0891c25facf14c53ef939846010284025ca9Dake Gu        }
1334134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimation();
1335134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(199, mGridView.getSelectedPosition());
1336134b0891c25facf14c53ef939846010284025ca9Dake Gu        // check if ItemAnimation finishes at aligned positions:
1337134b0891c25facf14c53ef939846010284025ca9Dake Gu        int leftEdge = mGridView.getLayoutManager().findViewByPosition(199).getLeft();
1338134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1339134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1340134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1341134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.requestLayout();
1342134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1343134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1344134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
1345134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(leftEdge, mGridView.getLayoutManager().findViewByPosition(199).getLeft());
1346134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
1347134b0891c25facf14c53ef939846010284025ca9Dake Gu
1348134b0891c25facf14c53ef939846010284025ca9Dake Gu    @Test
1349134b0891c25facf14c53ef939846010284025ca9Dake Gu    public void testContinuousSwapBackward() throws Throwable {
1350134b0891c25facf14c53ef939846010284025ca9Dake Gu        Intent intent = new Intent();
1351134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1352134b0891c25facf14c53ef939846010284025ca9Dake Gu                R.layout.horizontal_linear);
1353134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
1354134b0891c25facf14c53ef939846010284025ca9Dake Gu        initActivity(intent);
1355134b0891c25facf14c53ef939846010284025ca9Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1356134b0891c25facf14c53ef939846010284025ca9Dake Gu        mNumRows = 1;
1357134b0891c25facf14c53ef939846010284025ca9Dake Gu
1358134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1359134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1360134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1361134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.setSelectedPositionSmooth(50);
1362134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1363134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1364134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle(mVerifyLayout);
1365134b0891c25facf14c53ef939846010284025ca9Dake Gu        for (int i = 50; i > 0; i--) {
1366134b0891c25facf14c53ef939846010284025ca9Dake Gu            final int swapIndex = i;
1367134b0891c25facf14c53ef939846010284025ca9Dake Gu            mActivityTestRule.runOnUiThread(new Runnable() {
1368134b0891c25facf14c53ef939846010284025ca9Dake Gu                @Override
1369134b0891c25facf14c53ef939846010284025ca9Dake Gu                public void run() {
1370134b0891c25facf14c53ef939846010284025ca9Dake Gu                    mActivity.swap(swapIndex, swapIndex - 1);
1371134b0891c25facf14c53ef939846010284025ca9Dake Gu                }
1372134b0891c25facf14c53ef939846010284025ca9Dake Gu            });
1373134b0891c25facf14c53ef939846010284025ca9Dake Gu            Thread.sleep(10);
1374134b0891c25facf14c53ef939846010284025ca9Dake Gu        }
1375134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimation();
1376134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(0, mGridView.getSelectedPosition());
1377134b0891c25facf14c53ef939846010284025ca9Dake Gu        // check if ItemAnimation finishes at aligned positions:
1378134b0891c25facf14c53ef939846010284025ca9Dake Gu        int leftEdge = mGridView.getLayoutManager().findViewByPosition(0).getLeft();
1379134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1380134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1381134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1382134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.requestLayout();
1383134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1384134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1385134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
1386134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(leftEdge, mGridView.getLayoutManager().findViewByPosition(0).getLeft());
1387134b0891c25facf14c53ef939846010284025ca9Dake Gu    }
1388134b0891c25facf14c53ef939846010284025ca9Dake Gu
138906dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
1390bb1f461f210836de67bc68980409c5112889299aDake Gu    public void testSwapAfterScroll() throws Throwable {
1391bb1f461f210836de67bc68980409c5112889299aDake Gu        Intent intent = new Intent();
1392bb1f461f210836de67bc68980409c5112889299aDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1393bb1f461f210836de67bc68980409c5112889299aDake Gu                R.layout.horizontal_linear);
1394bb1f461f210836de67bc68980409c5112889299aDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
1395bb1f461f210836de67bc68980409c5112889299aDake Gu        initActivity(intent);
1396bb1f461f210836de67bc68980409c5112889299aDake Gu        mOrientation = BaseGridView.HORIZONTAL;
1397bb1f461f210836de67bc68980409c5112889299aDake Gu        mNumRows = 1;
1398bb1f461f210836de67bc68980409c5112889299aDake Gu
1399bb1f461f210836de67bc68980409c5112889299aDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1400bb1f461f210836de67bc68980409c5112889299aDake Gu            @Override
1401bb1f461f210836de67bc68980409c5112889299aDake Gu            public void run() {
1402bb1f461f210836de67bc68980409c5112889299aDake Gu                mGridView.getItemAnimator().setMoveDuration(1000);
1403bb1f461f210836de67bc68980409c5112889299aDake Gu                mGridView.setSelectedPositionSmooth(150);
1404bb1f461f210836de67bc68980409c5112889299aDake Gu            }
1405bb1f461f210836de67bc68980409c5112889299aDake Gu        });
1406bb1f461f210836de67bc68980409c5112889299aDake Gu        waitForScrollIdle();
1407bb1f461f210836de67bc68980409c5112889299aDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1408bb1f461f210836de67bc68980409c5112889299aDake Gu            @Override
1409bb1f461f210836de67bc68980409c5112889299aDake Gu            public void run() {
1410bb1f461f210836de67bc68980409c5112889299aDake Gu                mGridView.setSelectedPositionSmooth(151);
1411bb1f461f210836de67bc68980409c5112889299aDake Gu            }
1412bb1f461f210836de67bc68980409c5112889299aDake Gu        });
1413bb1f461f210836de67bc68980409c5112889299aDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1414bb1f461f210836de67bc68980409c5112889299aDake Gu            @Override
1415bb1f461f210836de67bc68980409c5112889299aDake Gu            public void run() {
1416bb1f461f210836de67bc68980409c5112889299aDake Gu                // we want to swap and select new target which is at 150 before swap
1417bb1f461f210836de67bc68980409c5112889299aDake Gu                mGridView.setSelectedPositionSmooth(150);
1418bb1f461f210836de67bc68980409c5112889299aDake Gu                mActivity.swap(150, 151);
1419bb1f461f210836de67bc68980409c5112889299aDake Gu            }
1420bb1f461f210836de67bc68980409c5112889299aDake Gu        });
1421bb1f461f210836de67bc68980409c5112889299aDake Gu        waitForItemAnimation();
1422bb1f461f210836de67bc68980409c5112889299aDake Gu        waitForScrollIdle();
1423bb1f461f210836de67bc68980409c5112889299aDake Gu        assertEquals(151, mGridView.getSelectedPosition());
1424bb1f461f210836de67bc68980409c5112889299aDake Gu        // check if ItemAnimation finishes at aligned positions:
1425bb1f461f210836de67bc68980409c5112889299aDake Gu        int leftEdge = mGridView.getLayoutManager().findViewByPosition(151).getLeft();
1426bb1f461f210836de67bc68980409c5112889299aDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1427bb1f461f210836de67bc68980409c5112889299aDake Gu            @Override
1428bb1f461f210836de67bc68980409c5112889299aDake Gu            public void run() {
1429bb1f461f210836de67bc68980409c5112889299aDake Gu                mGridView.requestLayout();
1430bb1f461f210836de67bc68980409c5112889299aDake Gu            }
1431bb1f461f210836de67bc68980409c5112889299aDake Gu        });
1432bb1f461f210836de67bc68980409c5112889299aDake Gu        waitForScrollIdle();
1433bb1f461f210836de67bc68980409c5112889299aDake Gu        assertEquals(leftEdge, mGridView.getLayoutManager().findViewByPosition(151).getLeft());
1434bb1f461f210836de67bc68980409c5112889299aDake Gu    }
1435bb1f461f210836de67bc68980409c5112889299aDake Gu
1436bb1f461f210836de67bc68980409c5112889299aDake Gu    @Test
1437c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu    public void testItemMovedHorizontal() throws Throwable {
143806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
1439247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1440247741d74797105ba4f6d2834ec56dab32c14644Dake Gu                R.layout.horizontal_grid);
144185df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
14428c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
1443247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1444247741d74797105ba4f6d2834ec56dab32c14644Dake Gu        mNumRows = 3;
144585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
1446134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1447134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1448134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1449134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.setSelectedPositionSmooth(150);
1450134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1451134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
145285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        waitForScrollIdle(mVerifyLayout);
145321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
145421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
145521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            public void run() {
145621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mActivity.swap(150, 152);
145721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
145821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        });
145942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(mVerifyLayout);
146085df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
1461a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToBegin(mVerifyLayout);
146285df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
146385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu        verifyBeginAligned();
146485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu    }
146585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu
146606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
14672bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu    public void testItemMovedHorizontalRtl() throws Throwable {
14682bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        Intent intent = new Intent();
14692bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
14702bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu                R.layout.horizontal_linear_rtl);
14712bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
14722bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, new int[] {40, 40, 40});
14732bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        initActivity(intent);
14742bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        mOrientation = BaseGridView.HORIZONTAL;
14752bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        mNumRows = 1;
14762bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu
14772bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        performAndWaitForAnimation(new Runnable() {
14782bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu            @Override
14792bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu            public void run() {
14802bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu                mActivity.moveItem(0, 1, true);
14812bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu            }
14822bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        });
14832bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu        assertEquals(mGridView.getWidth() - mGridView.getPaddingRight(),
14842bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu                mGridView.findViewHolderForAdapterPosition(0).itemView.getRight());
14852bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu    }
14862bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu
14872bafb2b6c1aae65b6e2169a3ecc5962858e0a4fdDake Gu    @Test
1488b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testScrollSecondaryCannotScroll() throws Throwable {
1489b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        Intent intent = new Intent();
1490b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1491b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                R.layout.horizontal_grid);
1492b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
1493b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000);
1494b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        initActivity(intent);
1495b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1496b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mNumRows = 3;
1497b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int topPadding = 2;
1498b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int bottomPadding = 2;
1499b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int height = mGridView.getHeight();
1500b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int spacing = 2;
1501b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int rowHeight = (height - topPadding - bottomPadding) / 4 - spacing;
1502b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final HorizontalGridView horizontalGridView = (HorizontalGridView) mGridView;
1503b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
1504b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        startWaitLayout();
1505b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1506b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            @Override
1507b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            public void run() {
1508b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setPadding(0, topPadding, 0, bottomPadding);
1509b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setItemSpacing(spacing);
1510b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setNumRows(mNumRows);
1511b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setRowHeight(rowHeight);
1512b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            }
1513b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        });
1514b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        waitForLayout();
1515b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // navigate vertically in first column, first row should always be aligned to top padding
1516b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        for (int i = 0; i < 3; i++) {
1517b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            setSelectedPosition(i);
1518b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(0).itemView
1519b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                    .getTop());
1520b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        }
1521b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // navigate vertically in 100th column, first row should always be aligned to top padding
1522b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        for (int i = 300; i < 301; i++) {
1523b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            setSelectedPosition(i);
1524b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(300).itemView
1525b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                    .getTop());
1526b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        }
1527b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
1528b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
1529b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    @Test
1530b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testScrollSecondaryNeedScroll() throws Throwable {
1531b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        Intent intent = new Intent();
1532b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1533b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                R.layout.horizontal_grid);
1534b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
1535b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2000);
1536b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        initActivity(intent);
1537b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1538b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // test a lot of rows so we have to scroll vertically to reach
1539b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mNumRows = 9;
1540b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int topPadding = 2;
1541b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int bottomPadding = 2;
1542b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int height = mGridView.getHeight();
1543b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int spacing = 2;
1544b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int rowHeight = (height - topPadding - bottomPadding) / 4 - spacing;
1545b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final HorizontalGridView horizontalGridView = (HorizontalGridView) mGridView;
1546b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
1547b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        startWaitLayout();
1548b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1549b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            @Override
1550b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            public void run() {
1551b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setPadding(0, topPadding, 0, bottomPadding);
1552b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setItemSpacing(spacing);
1553b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setNumRows(mNumRows);
1554b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                horizontalGridView.setRowHeight(rowHeight);
1555b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            }
1556b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        });
1557b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        waitForLayout();
1558b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        View view;
1559b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // first row should be aligned to top padding
1560b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        setSelectedPosition(0);
1561b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(0).itemView.getTop());
1562b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // middle row should be aligned to keyline (1/2 of screen height)
1563b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        setSelectedPosition(4);
1564b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        view = mGridView.findViewHolderForAdapterPosition(4).itemView;
1565b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        assertEquals(height / 2, (view.getTop() + view.getBottom()) / 2);
1566b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // last row should be aligned to bottom padding.
1567b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        setSelectedPosition(8);
1568b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        view = mGridView.findViewHolderForAdapterPosition(8).itemView;
1569b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        assertEquals(height, view.getTop() + rowHeight + bottomPadding);
1570b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        setSelectedPositionSmooth(4);
1571b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        waitForScrollIdle();
1572b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // middle row should be aligned to keyline (1/2 of screen height)
1573b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        setSelectedPosition(4);
1574b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        view = mGridView.findViewHolderForAdapterPosition(4).itemView;
1575b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        assertEquals(height / 2, (view.getTop() + view.getBottom()) / 2);
1576b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        // first row should be aligned to top padding
1577b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        setSelectedPositionSmooth(0);
1578b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        waitForScrollIdle();
1579b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        assertEquals(topPadding, mGridView.findViewHolderForAdapterPosition(0).itemView.getTop());
1580b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
1581b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
1582b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    @Test
1583c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu    public void testItemMovedVertical() throws Throwable {
1584c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
158506dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
1586c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1587c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu                R.layout.vertical_grid);
1588c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
15898c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
1590c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        mOrientation = BaseGridView.VERTICAL;
1591c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        mNumRows = 3;
1592c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
1593c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        mGridView.setSelectedPositionSmooth(150);
1594c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        waitForScrollIdle(mVerifyLayout);
159521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
159621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
159721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            public void run() {
159821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mActivity.swap(150, 152);
159921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
160021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        });
160142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(mVerifyLayout);
1602c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
16037ee22537e201c3d6b5de2908aecc4b0cc59a05c2Dake Gu        scrollToEnd(mVerifyLayout);
1604a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToBegin(mVerifyLayout);
1605c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
1606c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu        verifyBeginAligned();
1607c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu    }
1608c755c85c3596bb00f30f7941bac3860a9dc91d7aDake Gu
160906dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
1610af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu    public void testAddLastItemHorizontal() throws Throwable {
1611af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1612af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        Intent intent = new Intent();
1613af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1614af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                R.layout.horizontal_linear);
1615af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50);
1616af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        initActivity(intent);
1617af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        mOrientation = BaseGridView.HORIZONTAL;
1618af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        mNumRows = 1;
1619af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1620af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        mActivityTestRule.runOnUiThread(
1621af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                new Runnable() {
1622af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                    @Override
1623af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                    public void run() {
1624af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                        mGridView.setSelectedPositionSmooth(49);
1625af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                    }
1626af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                }
1627af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        );
1628af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        waitForScrollIdle(mVerifyLayout);
1629af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        performAndWaitForAnimation(new Runnable() {
1630af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu            @Override
1631af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu            public void run() {
1632af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                mActivity.addItems(50, new int[]{150});
1633af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu            }
1634af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        });
1635af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1636af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        // assert new added item aligned to right edge
1637af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        assertEquals(mGridView.getWidth() - mGridView.getPaddingRight(),
1638af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                mGridView.getLayoutManager().findViewByPosition(50).getRight());
1639af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu    }
1640af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1641af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu    @Test
1642af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu    public void testAddMultipleLastItemsHorizontal() throws Throwable {
1643af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1644af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        Intent intent = new Intent();
1645af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1646af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                R.layout.horizontal_linear);
1647af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50);
1648af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        initActivity(intent);
1649af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        mOrientation = BaseGridView.HORIZONTAL;
1650af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        mNumRows = 1;
1651af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1652af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        mActivityTestRule.runOnUiThread(
1653af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                new Runnable() {
1654af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                    @Override
1655af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                    public void run() {
1656af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                        mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_BOTH_EDGE);
1657af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                        mGridView.setWindowAlignmentOffsetPercent(50);
1658af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                        mGridView.setSelectedPositionSmooth(49);
1659af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                    }
1660af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                }
1661af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        );
1662af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        waitForScrollIdle(mVerifyLayout);
1663af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        performAndWaitForAnimation(new Runnable() {
1664af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu            @Override
1665af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu            public void run() {
1666af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                mActivity.addItems(50, new int[]{150, 150, 150, 150, 150, 150, 150, 150, 150,
1667af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu                        150, 150, 150, 150, 150});
1668af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu            }
1669af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        });
1670af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1671af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        // The focused item will be at center of window
1672af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        View view = mGridView.getLayoutManager().findViewByPosition(49);
1673af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu        assertEquals(mGridView.getWidth() / 2, (view.getLeft() + view.getRight()) / 2);
1674af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu    }
1675af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu
1676af3606dbd00dd77a2b0d0950edf203247509ad4cDake Gu    @Test
1677ede7fd3c91008fb042c736240534d0d87234f112Dake Gu    public void testItemAddRemoveHorizontal() throws Throwable {
1678ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
167906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
1680ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1681ede7fd3c91008fb042c736240534d0d87234f112Dake Gu                R.layout.horizontal_grid);
1682ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
16838c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
1684ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
1685ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        mNumRows = 3;
1686ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
1687a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
1688ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        int[] endEdges = getEndEdges();
1689ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
1690ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        mGridView.setSelectedPositionSmooth(150);
1691ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        waitForScrollIdle(mVerifyLayout);
169221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
169321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
169421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            public void run() {
169521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mRemovedItems = mActivity.removeItems(151, 4);
169621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
169721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        });
1698ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
1699a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
1700ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        mGridView.setSelectedPositionSmooth(150);
1701ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        waitForScrollIdle(mVerifyLayout);
1702ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
170321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
170421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
170521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            public void run() {
170621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mActivity.addItems(151, mRemovedItems);
170721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
170821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        });
1709a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToEnd(mVerifyLayout);
1710ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
1711ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        // we should get same aligned end edges
1712ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        int[] endEdges2 = getEndEdges();
1713ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        verifyEdgesSame(endEdges, endEdges2);
1714ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
1715a3c24a53034f1effc24b2d01328d63d96ad2ac7cDake Gu        scrollToBegin(mVerifyLayout);
1716ede7fd3c91008fb042c736240534d0d87234f112Dake Gu        verifyBeginAligned();
1717ede7fd3c91008fb042c736240534d0d87234f112Dake Gu    }
1718ede7fd3c91008fb042c736240534d0d87234f112Dake Gu
171906dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
172034914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu    public void testSetSelectedPositionDetached() throws Throwable {
172134914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu
172206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
172334914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
172434914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                R.layout.horizontal_linear);
172534914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50);
172634914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        initActivity(intent);
172734914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
172834914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        mNumRows = 1;
172934914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu
173034914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        final int focusToIndex = 49;
173134914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        final ViewGroup parent = (ViewGroup) mGridView.getParent();
173242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1733e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
173434914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            public void run() {
173534914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                parent.removeView(mGridView);
173634914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            }
173734914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        });
173842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1739e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
174034914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            public void run() {
174134914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                mGridView.setSelectedPositionSmooth(focusToIndex);
174234914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            }
174334914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        });
174442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1745e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
174634914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            public void run() {
174734914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                parent.addView(mGridView);
174834914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                mGridView.requestFocus();
174934914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            }
175034914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        });
175134914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        waitForScrollIdle();
175234914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        assertEquals(mGridView.getSelectedPosition(), focusToIndex);
175334914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(focusToIndex).hasFocus());
175434914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu
175534914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        final int focusToIndex2 = 0;
175642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1757e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
175834914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            public void run() {
175934914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                parent.removeView(mGridView);
176034914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            }
176134914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        });
176242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1763e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
176434914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            public void run() {
176534914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                mGridView.setSelectedPosition(focusToIndex2);
176634914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            }
176734914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        });
176842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1769e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
177034914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            public void run() {
177134914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                parent.addView(mGridView);
177234914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu                mGridView.requestFocus();
177334914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu            }
177434914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        });
177534914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        assertEquals(mGridView.getSelectedPosition(), focusToIndex2);
177634914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        waitForScrollIdle();
177734914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(focusToIndex2).hasFocus());
177834914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu    }
177934914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu
178006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
178191feb947412e0521a5f1835553214dcbe03fd362Dake Gu    public void testBug22209986() throws Throwable {
178291feb947412e0521a5f1835553214dcbe03fd362Dake Gu
178306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
178491feb947412e0521a5f1835553214dcbe03fd362Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
178591feb947412e0521a5f1835553214dcbe03fd362Dake Gu                R.layout.horizontal_linear);
178691feb947412e0521a5f1835553214dcbe03fd362Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 50);
178791feb947412e0521a5f1835553214dcbe03fd362Dake Gu        initActivity(intent);
178891feb947412e0521a5f1835553214dcbe03fd362Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
178991feb947412e0521a5f1835553214dcbe03fd362Dake Gu        mNumRows = 1;
179091feb947412e0521a5f1835553214dcbe03fd362Dake Gu
179191feb947412e0521a5f1835553214dcbe03fd362Dake Gu        final int focusToIndex = mGridView.getChildCount() - 1;
179242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1793e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
179491feb947412e0521a5f1835553214dcbe03fd362Dake Gu            public void run() {
179591feb947412e0521a5f1835553214dcbe03fd362Dake Gu                mGridView.setSelectedPositionSmooth(focusToIndex);
179691feb947412e0521a5f1835553214dcbe03fd362Dake Gu            }
179791feb947412e0521a5f1835553214dcbe03fd362Dake Gu        });
179891feb947412e0521a5f1835553214dcbe03fd362Dake Gu
179991feb947412e0521a5f1835553214dcbe03fd362Dake Gu        waitForScrollIdle();
180042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1801e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
180291feb947412e0521a5f1835553214dcbe03fd362Dake Gu            public void run() {
180391feb947412e0521a5f1835553214dcbe03fd362Dake Gu                mGridView.setSelectedPositionSmooth(focusToIndex + 1);
180491feb947412e0521a5f1835553214dcbe03fd362Dake Gu            }
180591feb947412e0521a5f1835553214dcbe03fd362Dake Gu        });
180691feb947412e0521a5f1835553214dcbe03fd362Dake Gu        // let the scroll running for a while and requestLayout during scroll
180791feb947412e0521a5f1835553214dcbe03fd362Dake Gu        Thread.sleep(80);
180842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1809e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
181091feb947412e0521a5f1835553214dcbe03fd362Dake Gu            public void run() {
181191feb947412e0521a5f1835553214dcbe03fd362Dake Gu                assertEquals(mGridView.getScrollState(), BaseGridView.SCROLL_STATE_SETTLING);
181291feb947412e0521a5f1835553214dcbe03fd362Dake Gu                mGridView.requestLayout();
181391feb947412e0521a5f1835553214dcbe03fd362Dake Gu            }
181491feb947412e0521a5f1835553214dcbe03fd362Dake Gu        });
181591feb947412e0521a5f1835553214dcbe03fd362Dake Gu        waitForScrollIdle();
181691feb947412e0521a5f1835553214dcbe03fd362Dake Gu
181791feb947412e0521a5f1835553214dcbe03fd362Dake Gu        int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
181891feb947412e0521a5f1835553214dcbe03fd362Dake Gu
181942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1820e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
182191feb947412e0521a5f1835553214dcbe03fd362Dake Gu            public void run() {
182291feb947412e0521a5f1835553214dcbe03fd362Dake Gu                mGridView.requestLayout();
182391feb947412e0521a5f1835553214dcbe03fd362Dake Gu            }
182491feb947412e0521a5f1835553214dcbe03fd362Dake Gu        });
182591feb947412e0521a5f1835553214dcbe03fd362Dake Gu        waitForScrollIdle();
182691feb947412e0521a5f1835553214dcbe03fd362Dake Gu        assertEquals(leftEdge,
182791feb947412e0521a5f1835553214dcbe03fd362Dake Gu                mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft());
182891feb947412e0521a5f1835553214dcbe03fd362Dake Gu    }
182991feb947412e0521a5f1835553214dcbe03fd362Dake Gu
183089ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    void testScrollAndRemove(int[] itemsLength, int numItems) throws Throwable {
1831ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
183206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
1833ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
1834ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                R.layout.horizontal_linear);
183589ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        if (itemsLength != null) {
183689ded73522265e09a03fd04f4ffccef7118bdedbDake Gu            intent.putExtra(GridActivity.EXTRA_ITEMS, itemsLength);
183789ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        } else {
183889ded73522265e09a03fd04f4ffccef7118bdedbDake Gu            intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
183989ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        }
1840ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        initActivity(intent);
1841ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mOrientation = BaseGridView.HORIZONTAL;
1842ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mNumRows = 1;
1843ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
1844ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        final int focusToIndex = mGridView.getChildCount() - 1;
184542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1846e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
1847ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
1848ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.setSelectedPositionSmooth(focusToIndex);
1849ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
1850ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
1851ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
185221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
185321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
1854ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
1855ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mActivity.removeItems(focusToIndex, 1);
1856ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
1857ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
1858ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
1859bb1f461f210836de67bc68980409c5112889299aDake Gu        waitOneUiCycle();
1860ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        waitForScrollIdle();
1861ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
1862ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
186342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1864e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
1865ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
1866ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.requestLayout();
1867ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
1868ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
1869ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        waitForScrollIdle();
1870ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        assertEquals(leftEdge,
187189ded73522265e09a03fd04f4ffccef7118bdedbDake Gu                mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft(), DELTA);
187289ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    }
187389ded73522265e09a03fd04f4ffccef7118bdedbDake Gu
187489ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    @Test
187589ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    public void testScrollAndRemove() throws Throwable {
187689ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        // test random lengths for 50 items
187789ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        testScrollAndRemove(null, 50);
187889ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    }
187989ded73522265e09a03fd04f4ffccef7118bdedbDake Gu
188089ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    /**
188189ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * This test verifies if scroll limits are ignored when onLayoutChildren compensate remaining
188289ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * scroll distance. b/64931938
188389ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * In the test, second child is long, other children are short.
188489ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * Test scrolls to the long child, and when scrolling, remove the long child. We made it long
188589ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * to have enough remaining scroll distance when the layout pass kicks in.
188689ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * The onLayoutChildren() would compensate the remaining scroll distance, moving all items
188789ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * toward right, which will make the first item's left edge bigger than left padding,
188889ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * which would violate the "scroll limit of left" in a regular scroll case, but
188989ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     * in layout pass, we still honor that scroll request, ignoring the scroll limit.
189089ded73522265e09a03fd04f4ffccef7118bdedbDake Gu     */
189189ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    @Test
189289ded73522265e09a03fd04f4ffccef7118bdedbDake Gu    public void testScrollAndRemoveSample1() throws Throwable {
189389ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        DisplayMetrics dm = InstrumentationRegistry.getInstrumentation().getTargetContext()
189489ded73522265e09a03fd04f4ffccef7118bdedbDake Gu                .getResources().getDisplayMetrics();
189589ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        // screen width for long item and 4DP for other items
189689ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        int longItemLength = dm.widthPixels;
189789ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        int shortItemLength = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm);
189889ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        int[] items = new int[1000];
189989ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        for (int i = 0; i < items.length; i++) {
190089ded73522265e09a03fd04f4ffccef7118bdedbDake Gu            items[i] = shortItemLength;
190189ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        }
190289ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        items[1] = longItemLength;
190389ded73522265e09a03fd04f4ffccef7118bdedbDake Gu        testScrollAndRemove(items, 0);
1904ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu    }
1905ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
190606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
19074927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu    public void testScrollAndInsert() throws Throwable {
19084927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
190906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
19104927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
19114927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                R.layout.vertical_grid);
19124927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        int[] items = new int[1000];
19134927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        for (int i = 0; i < items.length; i++) {
19144927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            items[i] = 300 + (int)(Math.random() * 100);
19154927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        }
19164927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
19174927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, true);
19184927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        mOrientation = BaseGridView.VERTICAL;
19194927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        mNumRows = 3;
19204927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
19214927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        initActivity(intent);
19224927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
192342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1924e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
19254927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            public void run() {
19264927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                mGridView.setSelectedPositionSmooth(150);
19274927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            }
19284927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        });
19294927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        waitForScrollIdle(mVerifyLayout);
19304927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
19314927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        View view =  mGridView.getChildAt(mGridView.getChildCount() - 1);
19324927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        final int focusToIndex = mGridView.getChildAdapterPosition(view);
193342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1934e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
19354927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            public void run() {
19364927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                mGridView.setSelectedPositionSmooth(focusToIndex);
19374927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            }
19384927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        });
19394927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
1940134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
194121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
19424927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            public void run() {
19434927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                int[] newItems = new int[]{300, 300, 300};
19444927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                mActivity.addItems(0, newItems);
19454927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            }
19464927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        });
1947134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
1948134b0891c25facf14c53ef939846010284025ca9Dake Gu        int topEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getTop();
1949134b0891c25facf14c53ef939846010284025ca9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
1950134b0891c25facf14c53ef939846010284025ca9Dake Gu            @Override
1951134b0891c25facf14c53ef939846010284025ca9Dake Gu            public void run() {
1952134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.requestLayout();
1953134b0891c25facf14c53ef939846010284025ca9Dake Gu            }
1954134b0891c25facf14c53ef939846010284025ca9Dake Gu        });
1955134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
1956134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertEquals(topEdge,
1957134b0891c25facf14c53ef939846010284025ca9Dake Gu                mGridView.getLayoutManager().findViewByPosition(focusToIndex).getTop());
19584927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu    }
19594927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
196006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
19614927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu    public void testScrollAndInsertBeforeVisibleItem() throws Throwable {
19624927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
196306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
19644927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
19654927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                R.layout.vertical_grid);
19664927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        int[] items = new int[1000];
19674927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        for (int i = 0; i < items.length; i++) {
19684927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            items[i] = 300 + (int)(Math.random() * 100);
19694927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        }
19704927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
19714927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, true);
19724927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        mOrientation = BaseGridView.VERTICAL;
19734927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        mNumRows = 3;
19744927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
19754927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        initActivity(intent);
19764927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
197742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1978e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
19794927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            public void run() {
19804927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                mGridView.setSelectedPositionSmooth(150);
19814927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            }
19824927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        });
19834927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        waitForScrollIdle(mVerifyLayout);
19844927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
19854927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        View view =  mGridView.getChildAt(mGridView.getChildCount() - 1);
19864927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        final int focusToIndex = mGridView.getChildAdapterPosition(view);
198742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
1988e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
19894927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            public void run() {
19904927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                mGridView.setSelectedPositionSmooth(focusToIndex);
19914927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            }
19924927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        });
19934927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
199421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
199521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
19964927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            public void run() {
19974927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                int[] newItems = new int[]{300, 300, 300};
19984927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu                mActivity.addItems(focusToIndex, newItems);
19994927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu            }
20004927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu        });
20014927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu    }
20024927a3bbd1921aed5da5d276a5d15240b2960faeDake Gu
200306dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
2004ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu    public void testSmoothScrollAndRemove() throws Throwable {
2005ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
200606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2007ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
2008ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                R.layout.horizontal_linear);
2009134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 300);
2010ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        initActivity(intent);
2011ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mOrientation = BaseGridView.HORIZONTAL;
2012ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mNumRows = 1;
2013ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2014134b0891c25facf14c53ef939846010284025ca9Dake Gu        final int focusToIndex = 200;
201542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2016e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2017ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
2018ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.setSelectedPositionSmooth(focusToIndex);
2019ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2020ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
2021ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
202242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2023e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2024ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
2025ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mActivity.removeItems(focusToIndex, 1);
2026ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2027ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
2028ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2029ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        assertTrue("removing the index of not attached child should not affect smooth scroller",
2030ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.getLayoutManager().isSmoothScrolling());
2031ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        waitForScrollIdle();
2032ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
2033ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
203442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2035e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2036ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
2037ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.requestLayout();
2038ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2039ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
2040ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        waitForScrollIdle();
2041ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        assertEquals(leftEdge,
2042ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft());
2043ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu    }
2044ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
204506dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
2046ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu    public void testSmoothScrollAndRemove2() throws Throwable {
2047ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
204806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2049ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
2050ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                R.layout.horizontal_linear);
2051134b0891c25facf14c53ef939846010284025ca9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 300);
2052ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        initActivity(intent);
2053ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mOrientation = BaseGridView.HORIZONTAL;
2054ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mNumRows = 1;
2055ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2056134b0891c25facf14c53ef939846010284025ca9Dake Gu        final int focusToIndex = 200;
205742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2058e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2059ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
2060ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.setSelectedPositionSmooth(focusToIndex);
2061ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2062ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
2063ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
206421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        startWaitLayout();
206542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2066e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2067ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
206821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                final int removeIndex = mGridView.getChildViewHolder(
206921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                        mGridView.getChildAt(mGridView.getChildCount() - 1)).getAdapterPosition();
2070ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mActivity.removeItems(removeIndex, 1);
2071ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2072ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
207321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForLayout();
2074ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2075134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertTrue("removing the index of attached child should not kill smooth scroller",
2076ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.getLayoutManager().isSmoothScrolling());
207721ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForItemAnimation();
2078134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
2079ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
2080ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
208142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2082e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2083ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
2084ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.requestLayout();
2085ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2086ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
2087ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        waitForScrollIdle();
2088ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        assertEquals(leftEdge,
2089ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft());
2090ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu    }
2091ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
209206dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
2093ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu    public void testPendingSmoothScrollAndRemove() throws Throwable {
209406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2095ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
2096ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                R.layout.vertical_linear);
2097ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
2098ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        int[] items = new int[100];
2099ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        for (int i = 0; i < items.length; i++) {
2100ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            items[i] = 630 + (int)(Math.random() * 100);
2101ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        }
2102ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
2103ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, true);
2104ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mOrientation = BaseGridView.VERTICAL;
2105ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mNumRows = 1;
2106ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2107ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        initActivity(intent);
2108ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2109ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        mGridView.setSelectedPositionSmooth(0);
2110ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        waitForScrollIdle(mVerifyLayout);
2111ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        assertTrue(mGridView.getChildAt(0).hasFocus());
2112ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2113ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        // Pressing lots of key to make sure smooth scroller is running
2114134b0891c25facf14c53ef939846010284025ca9Dake Gu        mGridView.mLayoutManager.mMaxPendingMoves = 100;
2115134b0891c25facf14c53ef939846010284025ca9Dake Gu        for (int i = 0; i < 100; i++) {
211606dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
2117ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        }
2118ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2119ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        assertTrue(mGridView.getLayoutManager().isSmoothScrolling());
212021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        startWaitLayout();
212142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2122e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2123ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
212421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                final int removeIndex = mGridView.getChildViewHolder(
212521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                        mGridView.getChildAt(mGridView.getChildCount() - 1)).getAdapterPosition();
2126ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mActivity.removeItems(removeIndex, 1);
2127ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2128ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
212921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForLayout();
2130ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
2131134b0891c25facf14c53ef939846010284025ca9Dake Gu        assertTrue("removing the index of attached child should not kill smooth scroller",
2132ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.getLayoutManager().isSmoothScrolling());
2133ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
213421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForItemAnimation();
2135134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
2136ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        int focusIndex = mGridView.getSelectedPosition();
2137b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        int topEdge = mGridView.getLayoutManager().findViewByPosition(focusIndex).getTop();
2138ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
213942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2140e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2141ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            public void run() {
2142ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu                mGridView.requestLayout();
2143ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu            }
2144ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        });
2145ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu        waitForScrollIdle();
2146b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        assertEquals(topEdge,
2147b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu                mGridView.getLayoutManager().findViewByPosition(focusIndex).getTop());
2148ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu    }
2149ff3b38c570fa25327bb6a9bca1753827d9f9d7fdDake Gu
215006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
21519c56475370d1df940252ff1360b92de50022fff6Dake Gu    public void testFocusToFirstItem() throws Throwable {
21529c56475370d1df940252ff1360b92de50022fff6Dake Gu
215306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
21549c56475370d1df940252ff1360b92de50022fff6Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
21559c56475370d1df940252ff1360b92de50022fff6Dake Gu                R.layout.horizontal_grid);
21569c56475370d1df940252ff1360b92de50022fff6Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 200);
21579c56475370d1df940252ff1360b92de50022fff6Dake Gu        initActivity(intent);
21589c56475370d1df940252ff1360b92de50022fff6Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
21599c56475370d1df940252ff1360b92de50022fff6Dake Gu        mNumRows = 3;
21609c56475370d1df940252ff1360b92de50022fff6Dake Gu
2161b50e46706ac654b071942bd7f6ba059c14c9c29aDake Gu        performAndWaitForAnimation(new Runnable() {
2162e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
216321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            public void run() {
216421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mRemovedItems = mActivity.removeItems(0, 200);
216521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
216621ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        });
21679c56475370d1df940252ff1360b92de50022fff6Dake Gu
2168f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
2169b50e46706ac654b071942bd7f6ba059c14c9c29aDake Gu        performAndWaitForAnimation(new Runnable() {
2170e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
217121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            public void run() {
217221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mActivity.addItems(0, mRemovedItems);
217321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
217421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        });
21759c56475370d1df940252ff1360b92de50022fff6Dake Gu
2176f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
21779c56475370d1df940252ff1360b92de50022fff6Dake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(0).hasFocus());
21789c56475370d1df940252ff1360b92de50022fff6Dake Gu
2179f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(0);
21809c56475370d1df940252ff1360b92de50022fff6Dake Gu
2181f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(200);
21829c56475370d1df940252ff1360b92de50022fff6Dake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(0).hasFocus());
21839c56475370d1df940252ff1360b92de50022fff6Dake Gu    }
21849c56475370d1df940252ff1360b92de50022fff6Dake Gu
218506dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
218677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu    public void testNonFocusableHorizontal() throws Throwable {
218777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int numItems = 200;
218877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int startPos = 45;
218977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int skips = 20;
219077b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int numColumns = 3;
219177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int endPos = startPos + numColumns * (skips + 1);
219277b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
219306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
219477b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
219577b17ebed6d1f8488b150b25e2b6754971480caeDake Gu                R.layout.horizontal_grid);
219677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
219777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
219877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        mOrientation = BaseGridView.HORIZONTAL;
219977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        mNumRows = numColumns;
220077b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        boolean[] focusable = new boolean[numItems];
220177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        for (int i = 0; i < focusable.length; i++) {
220277b17ebed6d1f8488b150b25e2b6754971480caeDake Gu            focusable[i] = true;
220377b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        }
220477b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        for (int i = startPos + mNumRows, j = 0; j < skips; i += mNumRows, j++) {
220577b17ebed6d1f8488b150b25e2b6754971480caeDake Gu            focusable[i] = false;
220677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        }
220777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
22088c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
220977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
221077b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        mGridView.setSelectedPositionSmooth(startPos);
221177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        waitForScrollIdle(mVerifyLayout);
221277b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
221377b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
221406dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_LEFT);
221577b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        } else {
221606dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_RIGHT);
221777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        }
221877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        waitForScrollIdle(mVerifyLayout);
221977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        assertEquals(endPos, mGridView.getSelectedPosition());
222077b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
222177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
222206dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_RIGHT);
222377b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        } else {
222406dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_LEFT);
222577b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        }
222677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        waitForScrollIdle(mVerifyLayout);
222777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        assertEquals(startPos, mGridView.getSelectedPosition());
222877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
222977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu    }
223077b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
223106dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
223289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu    public void testNoInitialFocusable() throws Throwable {
223389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
223406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
223589b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
223689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu                R.layout.horizontal_linear);
223789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        final int numItems = 100;
223889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
223989b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
224089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
224189b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        mNumRows = 1;
224289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        boolean[] focusable = new boolean[numItems];
224389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        final int firstFocusableIndex = 10;
224489b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        for (int i = 0; i < firstFocusableIndex; i++) {
224589b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            focusable[i] = false;
224689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        }
224789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        for (int i = firstFocusableIndex; i < focusable.length; i++) {
224889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            focusable[i] = true;
224989b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        }
225089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
225189b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        initActivity(intent);
225289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        assertTrue(mGridView.isFocused());
225389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
225489b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
225506dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_LEFT);
225689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        } else {
225706dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_RIGHT);
225889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        }
225989b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        waitForScrollIdle(mVerifyLayout);
226089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        assertEquals(firstFocusableIndex, mGridView.getSelectedPosition());
226189b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(firstFocusableIndex).hasFocus());
226289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu    }
226389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
226406dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
226506388129e48b308b25bfd85e6f136db8528d4c62Dake Gu    public void testFocusOutOfEmptyListView() throws Throwable {
226606388129e48b308b25bfd85e6f136db8528d4c62Dake Gu
226706dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
226806388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
226906388129e48b308b25bfd85e6f136db8528d4c62Dake Gu                R.layout.horizontal_linear);
227006388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        final int numItems = 100;
227106388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
227206388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
227306388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
227406388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        mNumRows = 1;
227506388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        initActivity(intent);
227606388129e48b308b25bfd85e6f136db8528d4c62Dake Gu
227706388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        final View horizontalGridView = new HorizontalGridViewEx(mGridView.getContext());
227842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
227906388129e48b308b25bfd85e6f136db8528d4c62Dake Gu            @Override
228006388129e48b308b25bfd85e6f136db8528d4c62Dake Gu            public void run() {
228106388129e48b308b25bfd85e6f136db8528d4c62Dake Gu                horizontalGridView.setFocusable(true);
228206388129e48b308b25bfd85e6f136db8528d4c62Dake Gu                horizontalGridView.setFocusableInTouchMode(true);
228306388129e48b308b25bfd85e6f136db8528d4c62Dake Gu                horizontalGridView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
228406388129e48b308b25bfd85e6f136db8528d4c62Dake Gu                ((ViewGroup) mGridView.getParent()).addView(horizontalGridView, 0);
228506388129e48b308b25bfd85e6f136db8528d4c62Dake Gu                horizontalGridView.requestFocus();
228606388129e48b308b25bfd85e6f136db8528d4c62Dake Gu            }
228706388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        });
228806388129e48b308b25bfd85e6f136db8528d4c62Dake Gu
228906388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        assertTrue(horizontalGridView.isFocused());
229006388129e48b308b25bfd85e6f136db8528d4c62Dake Gu
229106dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
229206388129e48b308b25bfd85e6f136db8528d4c62Dake Gu
229306388129e48b308b25bfd85e6f136db8528d4c62Dake Gu        assertTrue(mGridView.hasFocus());
229406388129e48b308b25bfd85e6f136db8528d4c62Dake Gu    }
229506388129e48b308b25bfd85e6f136db8528d4c62Dake Gu
229606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
229789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu    public void testTransferFocusToChildWhenGainFocus() throws Throwable {
229889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
229906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
230089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
230189b4aed6fcd80f940531e265936ab908a8037f87Dake Gu                R.layout.horizontal_linear);
230289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        final int numItems = 100;
230389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
230489b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
230589b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
230689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        mNumRows = 1;
230789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        boolean[] focusable = new boolean[numItems];
230889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        final int firstFocusableIndex = 1;
230989b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        for (int i = 0; i < firstFocusableIndex; i++) {
231089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            focusable[i] = false;
231189b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        }
231289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        for (int i = firstFocusableIndex; i < focusable.length; i++) {
231389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            focusable[i] = true;
231489b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        }
231589b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
231689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        initActivity(intent);
231789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
231889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        assertEquals(firstFocusableIndex, mGridView.getSelectedPosition());
231989b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(firstFocusableIndex).hasFocus());
232089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu    }
232189b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
232206dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
232389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu    public void testFocusFromSecondChild() throws Throwable {
232489b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
232506dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
232689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
232789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu                R.layout.horizontal_linear);
232889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        final int numItems = 100;
232989b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
233089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
233189b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
233289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        mNumRows = 1;
233389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        boolean[] focusable = new boolean[numItems];
233489b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        for (int i = 0; i < focusable.length; i++) {
233589b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            focusable[i] = false;
233689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        }
233789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
233889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        initActivity(intent);
233989b4aed6fcd80f940531e265936ab908a8037f87Dake Gu
234089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        // switching Adapter to cause a full rebind,  test if it will focus to second item.
2341b50e46706ac654b071942bd7f6ba059c14c9c29aDake Gu        performAndWaitForAnimation(new Runnable() {
234289b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            @Override
234389b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            public void run() {
234489b4aed6fcd80f940531e265936ab908a8037f87Dake Gu                mActivity.mNumItems = numItems;
234589b4aed6fcd80f940531e265936ab908a8037f87Dake Gu                mActivity.mItemFocusables[1] = true;
234689b4aed6fcd80f940531e265936ab908a8037f87Dake Gu                mActivity.rebindToNewAdapter();
234789b4aed6fcd80f940531e265936ab908a8037f87Dake Gu            }
234889b4aed6fcd80f940531e265936ab908a8037f87Dake Gu        });
2349b50e46706ac654b071942bd7f6ba059c14c9c29aDake Gu        assertTrue(mGridView.findViewHolderForAdapterPosition(1).itemView.hasFocus());
235089b4aed6fcd80f940531e265936ab908a8037f87Dake Gu    }
235177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
235206dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
235303eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu    public void removeFocusableItemAndFocusableRecyclerViewGetsFocus() throws Throwable {
235403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        final int numItems = 100;
235503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        final int numColumns = 3;
235603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        final int focusableIndex = 2;
235703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
235803eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        Intent intent = new Intent();
235903eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
236003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                R.layout.vertical_grid);
236103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
236203eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
236303eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        mOrientation = BaseGridView.VERTICAL;
236403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        mNumRows = numColumns;
236503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        boolean[] focusable = new boolean[numItems];
236603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        for (int i = 0; i < focusable.length; i++) {
236703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            focusable[i] = false;
236803eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        }
236903eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        focusable[focusableIndex] = true;
237003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
237103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        initActivity(intent);
237203eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
237303eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
237403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            @Override
237503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            public void run() {
237603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                mGridView.setSelectedPositionSmooth(focusableIndex);
237703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            }
237803eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        });
237903eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        waitForScrollIdle(mVerifyLayout);
238003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        assertEquals(focusableIndex, mGridView.getSelectedPosition());
238103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
238221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
238303eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            @Override
238403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            public void run() {
238503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                mActivity.removeItems(focusableIndex, 1);
238603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            }
238703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        });
2388580515488b23ac8a39795d11aef985c0f05c467eDake Gu        assertTrue(dumpGridView(mGridView), mGridView.isFocused());
238903eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu    }
239003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
239103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu    @Test
239203eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu    public void removeFocusableItemAndUnFocusableRecyclerViewLosesFocus() throws Throwable {
239303eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        final int numItems = 100;
239403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        final int numColumns = 3;
239503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        final int focusableIndex = 2;
239603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
239703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        Intent intent = new Intent();
239803eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
239903eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                R.layout.vertical_grid);
240003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
240103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
240203eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        mOrientation = BaseGridView.VERTICAL;
240303eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        mNumRows = numColumns;
240403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        boolean[] focusable = new boolean[numItems];
240503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        for (int i = 0; i < focusable.length; i++) {
240603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            focusable[i] = false;
240703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        }
240803eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        focusable[focusableIndex] = true;
240903eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
241003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        initActivity(intent);
241103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
241203eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
241303eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            @Override
241403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            public void run() {
241503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                mGridView.setFocusableInTouchMode(false);
241603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                mGridView.setFocusable(false);
241703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                mGridView.setSelectedPositionSmooth(focusableIndex);
241803eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            }
241903eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        });
242003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        waitForScrollIdle(mVerifyLayout);
242103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        assertEquals(focusableIndex, mGridView.getSelectedPosition());
242203eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
242321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
242403eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            @Override
242503eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            public void run() {
242603eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu                mActivity.removeItems(focusableIndex, 1);
242703eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu            }
242803eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu        });
2429580515488b23ac8a39795d11aef985c0f05c467eDake Gu        assertFalse(dumpGridView(mGridView), mGridView.hasFocus());
243003eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu    }
243103eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu
243203eae4e82fccd027e003a8d1544d3e9023404b14Dake Gu    @Test
243377b17ebed6d1f8488b150b25e2b6754971480caeDake Gu    public void testNonFocusableVertical() throws Throwable {
243477b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int numItems = 200;
243577b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int startPos = 44;
243677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int skips = 20;
243777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int numColumns = 3;
243877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        final int endPos = startPos + numColumns * (skips + 1);
243977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
244006dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
244177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
244277b17ebed6d1f8488b150b25e2b6754971480caeDake Gu                R.layout.vertical_grid);
244377b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
244477b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
244577b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        mOrientation = BaseGridView.VERTICAL;
244677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        mNumRows = numColumns;
244777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        boolean[] focusable = new boolean[numItems];
244877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        for (int i = 0; i < focusable.length; i++) {
244977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu            focusable[i] = true;
245077b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        }
245177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        for (int i = startPos + mNumRows, j = 0; j < skips; i += mNumRows, j++) {
245277b17ebed6d1f8488b150b25e2b6754971480caeDake Gu            focusable[i] = false;
245377b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        }
245477b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
24558c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
245677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
245777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        mGridView.setSelectedPositionSmooth(startPos);
245877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        waitForScrollIdle(mVerifyLayout);
245977b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
246006dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
246177b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        waitForScrollIdle(mVerifyLayout);
246277b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        assertEquals(endPos, mGridView.getSelectedPosition());
246377b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
246406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_UP);
246577b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        waitForScrollIdle(mVerifyLayout);
246677b17ebed6d1f8488b150b25e2b6754971480caeDake Gu        assertEquals(startPos, mGridView.getSelectedPosition());
246777b17ebed6d1f8488b150b25e2b6754971480caeDake Gu
246877b17ebed6d1f8488b150b25e2b6754971480caeDake Gu    }
24696b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
247006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
2471173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu    public void testLtrFocusOutStartDisabled() throws Throwable {
2472173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        final int numItems = 200;
2473173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
247406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2475173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_grid_ltr);
2476173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
2477173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
2478173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        mOrientation = BaseGridView.VERTICAL;
2479173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        mNumRows = 1;
2480173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        initActivity(intent);
2481173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
248242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2483173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu            @Override
2484173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu            public void run() {
2485173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu                mGridView.requestFocus();
2486173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu                mGridView.setSelectedPositionSmooth(0);
2487173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu            }
2488173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        });
2489173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        waitForScrollIdle(mVerifyLayout);
2490173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
249106dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_LEFT);
2492173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        waitForScrollIdle(mVerifyLayout);
2493173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        assertTrue(mGridView.hasFocus());
2494173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu    }
2495173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
249606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
2497173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu    public void testRtlFocusOutStartDisabled() throws Throwable {
2498173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        final int numItems = 200;
2499173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
250006dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2501173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_grid_rtl);
2502173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
2503173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
2504173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        mOrientation = BaseGridView.VERTICAL;
2505173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        mNumRows = 1;
2506173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        initActivity(intent);
2507173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
250842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2509173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu            @Override
2510173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu            public void run() {
2511173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu                mGridView.requestFocus();
2512173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu                mGridView.setSelectedPositionSmooth(0);
2513173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu            }
2514173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        });
2515173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        waitForScrollIdle(mVerifyLayout);
2516173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
251706dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_RIGHT);
2518173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        waitForScrollIdle(mVerifyLayout);
2519173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu        assertTrue(mGridView.hasFocus());
2520173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu    }
2521173d79a987bec7d8dc9fd4e7066200d0b9b9842eDake Gu
252206dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
25236b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu    public void testTransferFocusable() throws Throwable {
25246b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        final int numItems = 200;
25256b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        final int numColumns = 3;
25266b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        final int startPos = 1;
25276b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
252806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
25296b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
25306b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu                R.layout.horizontal_grid);
25316b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
25326b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
25336b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        mOrientation = BaseGridView.HORIZONTAL;
25346b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        mNumRows = numColumns;
25356b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        boolean[] focusable = new boolean[numItems];
25366b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        for (int i = 0; i < focusable.length; i++) {
25376b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu            focusable[i] = true;
25386b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        }
25396b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        for (int i = 0; i < startPos; i++) {
25406b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu            focusable[i] = false;
25416b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        }
25426b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
25438c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
25446b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
2545f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(0);
25466b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        assertTrue(mGridView.isFocused());
25476b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
2548f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(numItems);
25496b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(startPos).hasFocus());
25506b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu    }
25516b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
255206dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
25536b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu    public void testTransferFocusable2() throws Throwable {
25546b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        final int numItems = 200;
25556b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        final int numColumns = 3;
2556b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        final int startPos = 3; // make sure view at startPos is in visible area.
25576b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
255806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
25596b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
25606b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu                R.layout.horizontal_grid);
25616b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, numItems);
25626b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, true);
25636b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        mOrientation = BaseGridView.HORIZONTAL;
25646b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        mNumRows = numColumns;
25656b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        boolean[] focusable = new boolean[numItems];
25666b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        for (int i = 0; i < focusable.length; i++) {
25676b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu            focusable[i] = true;
25686b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        }
25696b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        for (int i = 0; i < startPos; i++) {
25706b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu            focusable[i] = false;
25716b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        }
25726b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE, focusable);
25738c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
25746b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
2575b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(startPos).hasFocus());
2576b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu
2577f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(0);
25786b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        assertTrue(mGridView.isFocused());
25796b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu
2580f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        changeArraySize(numItems);
25816b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(startPos).hasFocus());
25826b22c4c875d7a540e705b2b6b65bf52c7a89299aDake Gu    }
2583fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu
258406dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
25858c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    public void testNonFocusableLoseInFastLayout() throws Throwable {
258606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2587fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
2588fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu                R.layout.vertical_linear);
2589fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        int[] items = new int[300];
2590fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        for (int i = 0; i < items.length; i++) {
2591fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu            items[i] = 480;
2592fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        }
2593fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
2594fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
2595fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true);
2596fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        mOrientation = BaseGridView.VERTICAL;
2597fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        mNumRows = 1;
2598fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        int pressDown = 15;
2599fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu
26008c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
2601fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu
2602fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        mGridView.setSelectedPositionSmooth(0);
260321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(mVerifyLayout);
2604fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu
2605fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        for (int i = 0; i < pressDown; i++) {
260606dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
2607fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        }
260821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(mVerifyLayout);
2609fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu        assertFalse(mGridView.isFocused());
2610fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu
2611fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu    }
2612fa5f60106a84a2b475c38cc6b8baa347bbd6ae1dDake Gu
261306dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
261488c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu    public void testFocusableViewAvailable() throws Throwable {
261506dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
261688c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
261788c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                R.layout.vertical_linear);
261888c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 0);
261988c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
262088c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS_FOCUSABLE,
262188c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                new boolean[]{false, false, true, false, false});
262288c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        mOrientation = BaseGridView.VERTICAL;
262388c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        mNumRows = 1;
262488c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu
262588c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        initActivity(intent);
262688c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu
262742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
262888c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu            @Override
262988c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu            public void run() {
263088c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                // RecyclerView does not respect focusable and focusableInTouchMode flag, so
263188c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                // set flags in code.
263288c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                mGridView.setFocusableInTouchMode(false);
263388c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                mGridView.setFocusable(false);
263488c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu            }
263588c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        });
263688c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu
263788c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        assertFalse(mGridView.isFocused());
263888c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu
263988c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        final boolean[] scrolled = new boolean[]{false};
264088c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        mGridView.addOnScrollListener(new RecyclerView.OnScrollListener() {
2641e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
264288c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu            public void onScrolled(RecyclerView recyclerView, int dx, int dy){
264388c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                if (dy > 0) {
264488c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                    scrolled[0] = true;
264588c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu                }
264688c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu            }
264788c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        });
264821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
264921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            @Override
265021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            public void run() {
265121ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu                mActivity.addItems(0, new int[]{200, 300, 500, 500, 200});
265221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu            }
265321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        });
265421ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(mVerifyLayout);
265588c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu
265688c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu        assertFalse("GridView should not be scrolled", scrolled[0]);
265761afde67696f46ecb82eb0a26038c6fbf3383c2cDake Gu        assertTrue(mGridView.getLayoutManager().findViewByPosition(2).hasFocus());
265888c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu
265988c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu    }
266088c1cf67c6437e5e0f386b65b9e79605a111bd03Dake Gu
266106dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
26628c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    public void testSetSelectionWithDelta() throws Throwable {
266306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
26648c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
26658c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                R.layout.vertical_linear);
26668c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 300);
26678c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
26688c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        mOrientation = BaseGridView.VERTICAL;
26698c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        mNumRows = 1;
26708c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
26718c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
26728c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
267342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2674e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
26758c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            public void run() {
26768c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                mGridView.setSelectedPositionSmooth(3);
26778c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            }
26788c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        });
26798c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        waitForScrollIdle(mVerifyLayout);
26808c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top1 = mGridView.getLayoutManager().findViewByPosition(3).getTop();
26818c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
2682f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(1000);
26838c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
26848c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to position with delta
2685f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(3, 100);
26868c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top2 = mGridView.getLayoutManager().findViewByPosition(3).getTop();
26878c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top2);
26888c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
26898c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to same position without delta, it will be reset
2690f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(3, 0);
26918c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top3 = mGridView.getLayoutManager().findViewByPosition(3).getTop();
26928c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1, top3);
26938c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
26948c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll invisible item after last visible item
26958c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        final int lastVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager())
26968c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                .mGrid.getLastVisibleIndex();
2697f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(lastVisiblePos + 1, 100);
26988c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top4 = mGridView.getLayoutManager().findViewByPosition(lastVisiblePos + 1).getTop();
26998c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top4);
27008c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27018c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll invisible item before first visible item
27028c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        final int firstVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager())
27038c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                .mGrid.getFirstVisibleIndex();
2704f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(firstVisiblePos - 1, 100);
27058c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top5 = mGridView.getLayoutManager().findViewByPosition(firstVisiblePos - 1).getTop();
27068c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top5);
27078c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27088c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
2709f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(50, 100);
27108c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top6 = mGridView.getLayoutManager().findViewByPosition(50).getTop();
27118c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top6);
27128c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27138c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
271442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2715e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
27168c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            public void run() {
27178c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                mGridView.setSelectedPositionSmooth(100);
27188c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            }
27198c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        });
27208c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        waitForScrollIdle(mVerifyLayout);
27218c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top7 = mGridView.getLayoutManager().findViewByPosition(100).getTop();
27228c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1, top7);
27238c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27248c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
2725f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(10, 50);
27268c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top8 = mGridView.getLayoutManager().findViewByPosition(10).getTop();
27278c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 50, top8);
27288c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    }
27298c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
273006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
27318c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    public void testSetSelectionWithDeltaInGrid() throws Throwable {
273206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
27338c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
27348c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                R.layout.vertical_grid);
27358c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 500);
27368c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, true);
27378c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        mOrientation = BaseGridView.VERTICAL;
27388c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        mNumRows = 3;
27398c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27408c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
27418c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
274242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2743e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
27448c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            public void run() {
27458c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                mGridView.setSelectedPositionSmooth(10);
27468c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            }
27478c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        });
27488c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        waitForScrollIdle(mVerifyLayout);
27498c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top1 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10));
27508c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
2751f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
27528c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27538c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to position with delta
2754f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(20, 100);
27558c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top2 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20));
27568c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top2);
27578c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27588c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to same position without delta, it will be reset
2759f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(20, 0);
27608c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top3 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20));
27618c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1, top3);
27628c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27638c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll invisible item after last visible item
27648c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        final int lastVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager())
27658c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                .mGrid.getLastVisibleIndex();
2766f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(lastVisiblePos + 1, 100);
27678c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top4 = getCenterY(mGridView.getLayoutManager().findViewByPosition(lastVisiblePos + 1));
27688c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        verifyMargin();
27698c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top4);
27708c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27718c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll invisible item before first visible item
27728c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        final int firstVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager())
27738c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                .mGrid.getFirstVisibleIndex();
2774f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(firstVisiblePos - 1, 100);
27758c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top5 = getCenterY(mGridView.getLayoutManager().findViewByPosition(firstVisiblePos - 1));
27768c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top5);
27778c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27788c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
2779f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(100, 100);
27808c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top6 = getCenterY(mGridView.getLayoutManager().findViewByPosition(100));
27818c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top6);
27828c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27838c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
278442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2785e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
27868c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            public void run() {
27878c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                mGridView.setSelectedPositionSmooth(200);
27888c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            }
27898c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        });
27908c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        waitForScrollIdle(mVerifyLayout);
27918c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        Thread.sleep(500);
27928c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top7 = getCenterY(mGridView.getLayoutManager().findViewByPosition(200));
27938c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1, top7);
27948c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
27958c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
2796f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(10, 50);
27978c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top8 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10));
27988c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 50, top8);
27998c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    }
28008c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28018c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
280206dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
28038c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    public void testSetSelectionWithDeltaInGrid1() throws Throwable {
280406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
28058c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
28068c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                R.layout.vertical_grid);
28078c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, new int[]{
28088c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                193,176,153,141,203,184,232,139,177,206,222,136,132,237,172,137,
28098c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                188,172,163,213,158,219,209,147,133,229,170,197,138,215,188,205,
28108c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                223,192,225,170,195,127,229,229,210,195,134,142,160,139,130,222,
28118c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                150,163,180,176,157,137,234,169,159,167,182,150,224,231,202,236,
28128c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                123,140,181,223,120,185,183,221,123,210,134,158,166,208,149,128,
28138c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                192,214,212,198,133,140,158,133,229,173,226,141,180,128,127,218,
28148c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                192,235,183,213,216,150,143,193,125,141,219,210,195,195,192,191,
28158c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                212,236,157,189,160,220,147,158,220,199,233,231,201,180,168,141,
28168c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                156,204,191,183,190,153,123,210,238,151,139,221,223,200,175,191,
28178c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                132,184,197,204,236,157,230,151,195,219,212,143,172,149,219,184,
28188c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                164,211,132,187,172,142,174,146,127,147,206,238,188,129,199,226,
28198c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                132,220,210,159,235,153,208,182,196,123,180,159,131,135,175,226,
28208c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                127,134,237,211,133,225,132,124,160,226,224,200,173,137,217,169,
28218c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                182,183,176,185,122,168,195,159,172,129,126,129,166,136,149,220,
28228c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                178,191,192,238,180,208,234,154,222,206,239,228,129,140,203,125,
28238c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                214,175,125,169,196,132,234,138,192,142,234,190,215,232,239,122,
28248c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                188,158,128,221,159,237,207,157,232,138,132,214,122,199,121,191,
28258c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                199,209,126,164,175,187,173,186,194,224,191,196,146,208,213,210,
28268c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                164,176,202,213,123,157,179,138,217,129,186,166,237,211,157,130,
28278c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                137,132,171,232,216,239,180,151,137,132,190,133,218,155,171,227,
28288c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                193,147,197,164,120,218,193,154,170,196,138,222,161,235,143,154,
28298c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                192,178,228,195,178,133,203,178,173,206,178,212,136,157,169,124,
28308c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                172,121,128,223,238,125,217,187,184,156,169,215,231,124,210,174,
28318c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                146,226,185,134,223,228,183,182,136,133,199,146,180,233,226,225,
28328c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                174,233,145,235,216,170,192,171,132,132,134,223,233,148,154,162,
28338c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                192,179,197,203,139,197,174,187,135,132,180,136,192,195,124,221,
28348c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                120,189,233,233,146,225,234,163,215,143,132,198,156,205,151,190,
28358c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                204,239,221,229,123,138,134,217,219,136,218,215,167,139,195,125,
28368c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                202,225,178,226,145,208,130,194,228,197,157,215,124,147,174,123,
28378c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                237,140,172,181,161,151,229,216,199,199,179,213,146,122,222,162,
28388c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                139,173,165,150,160,217,207,137,165,175,129,158,134,133,178,199,
28398c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                215,213,122,197
28408c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        });
28418c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, true);
28428c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        mOrientation = BaseGridView.VERTICAL;
28438c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        mNumRows = 3;
28448c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28458c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        initActivity(intent);
28468c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
284742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2848e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
28498c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            public void run() {
28508c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                mGridView.setSelectedPositionSmooth(10);
28518c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            }
28528c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        });
28538c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        waitForScrollIdle(mVerifyLayout);
28548c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top1 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10));
28558c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
2856f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
28578c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28588c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to position with delta
2859f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(20, 100);
28608c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top2 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20));
28618c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top2);
28628c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28638c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to same position without delta, it will be reset
2864f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(20, 0);
28658c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top3 = getCenterY(mGridView.getLayoutManager().findViewByPosition(20));
28668c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1, top3);
28678c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28688c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll invisible item after last visible item
28698c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        final int lastVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager())
28708c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                .mGrid.getLastVisibleIndex();
2871f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(lastVisiblePos + 1, 100);
28728c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top4 = getCenterY(mGridView.getLayoutManager().findViewByPosition(lastVisiblePos + 1));
28738c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        verifyMargin();
28748c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top4);
28758c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28768c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll invisible item before first visible item
28778c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        final int firstVisiblePos = ((GridLayoutManager)mGridView.getLayoutManager())
28788c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                .mGrid.getFirstVisibleIndex();
2879f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(firstVisiblePos - 1, 100);
28808c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top5 = getCenterY(mGridView.getLayoutManager().findViewByPosition(firstVisiblePos - 1));
28818c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top5);
28828c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28838c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
2884f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(100, 100);
28858c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top6 = getCenterY(mGridView.getLayoutManager().findViewByPosition(100));
28868c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 100, top6);
28878c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
28888c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
288942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2890e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
28918c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            public void run() {
28928c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu                mGridView.setSelectedPositionSmooth(200);
28938c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu            }
28948c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        });
28958c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        waitForScrollIdle(mVerifyLayout);
28968c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        Thread.sleep(500);
28978c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top7 = getCenterY(mGridView.getLayoutManager().findViewByPosition(200));
28988c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1, top7);
28998c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu
29008c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        // scroll to invisible item that is far away.
2901f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        setSelectedPosition(10, 50);
29028c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        int top8 = getCenterY(mGridView.getLayoutManager().findViewByPosition(10));
29038c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu        assertEquals(top1 - 50, top8);
29048c5d3b45f6afa838e64e4cf011a385c191d557c6Dake Gu    }
2905f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
290606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
2907f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu    public void testSmoothScrollSelectionEvents() throws Throwable {
290806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2909f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
2910f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu                R.layout.vertical_grid);
2911f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 500);
2912f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
2913f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        mOrientation = BaseGridView.VERTICAL;
2914f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        mNumRows = 3;
2915f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        initActivity(intent);
2916f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
291742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2918e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2919f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            public void run() {
2920f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu                mGridView.setSelectedPositionSmooth(30);
2921f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            }
2922f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        });
2923f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        waitForScrollIdle(mVerifyLayout);
2924f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
2925f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
2926f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        final ArrayList<Integer> selectedPositions = new ArrayList<Integer>();
2927f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        mGridView.setOnChildSelectedListener(new OnChildSelectedListener() {
2928f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            @Override
2929f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
2930f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu                selectedPositions.add(position);
2931f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            }
2932f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        });
2933f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
2934f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        sendRepeatedKeys(10, KeyEvent.KEYCODE_DPAD_UP);
2935f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
2936f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        waitForScrollIdle(mVerifyLayout);
2937f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        // should only get childselected event for item 0 once
2938f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        assertTrue(selectedPositions.size() > 0);
2939f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        assertEquals(0, selectedPositions.get(selectedPositions.size() - 1).intValue());
2940f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        for (int i = selectedPositions.size() - 2; i >= 0; i--) {
2941f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            assertFalse(0 == selectedPositions.get(i).intValue());
2942f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        }
2943f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
2944f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu    }
2945f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
294606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
2947f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu    public void testSmoothScrollSelectionEventsLinear() throws Throwable {
294806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
2949f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
2950f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu                R.layout.vertical_linear);
2951f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 500);
2952f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
2953f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        mOrientation = BaseGridView.VERTICAL;
2954f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        mNumRows = 1;
2955f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        initActivity(intent);
2956f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
295742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2958e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
2959f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            public void run() {
2960f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu                mGridView.setSelectedPositionSmooth(10);
2961f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            }
2962f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        });
2963f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        waitForScrollIdle(mVerifyLayout);
2964f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
2965f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
2966f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        final ArrayList<Integer> selectedPositions = new ArrayList<Integer>();
2967f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        mGridView.setOnChildSelectedListener(new OnChildSelectedListener() {
2968f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            @Override
2969f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
2970f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu                selectedPositions.add(position);
2971f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            }
2972f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        });
2973f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
2974f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        sendRepeatedKeys(10, KeyEvent.KEYCODE_DPAD_UP);
2975f518dc6b5898d16d0b8818ff4d06425b2bb0b3d0Dake Gu        humanDelay(500);
2976f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        waitForScrollIdle(mVerifyLayout);
2977f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        // should only get childselected event for item 0 once
2978f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        assertTrue(selectedPositions.size() > 0);
2979f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        assertEquals(0, selectedPositions.get(selectedPositions.size() - 1).intValue());
2980f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        for (int i = selectedPositions.size() - 2; i >= 0; i--) {
2981f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu            assertFalse(0 == selectedPositions.get(i).intValue());
2982f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu        }
2983f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu
2984f80ef0d6b0b6403f3cd94e7197bc4a39d285280aDake Gu    }
29857538845719cd1e588185ce9ae60320377862ef8dDake Gu
298606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
29877538845719cd1e588185ce9ae60320377862ef8dDake Gu    public void testScrollToNoneExisting() throws Throwable {
298806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
29897538845719cd1e588185ce9ae60320377862ef8dDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
29907538845719cd1e588185ce9ae60320377862ef8dDake Gu                R.layout.vertical_grid);
29917538845719cd1e588185ce9ae60320377862ef8dDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100);
29927538845719cd1e588185ce9ae60320377862ef8dDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
29937538845719cd1e588185ce9ae60320377862ef8dDake Gu        mOrientation = BaseGridView.VERTICAL;
29947538845719cd1e588185ce9ae60320377862ef8dDake Gu        mNumRows = 3;
29957538845719cd1e588185ce9ae60320377862ef8dDake Gu        initActivity(intent);
29967538845719cd1e588185ce9ae60320377862ef8dDake Gu
299742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
2998e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
29997538845719cd1e588185ce9ae60320377862ef8dDake Gu            public void run() {
30007538845719cd1e588185ce9ae60320377862ef8dDake Gu                mGridView.setSelectedPositionSmooth(99);
30017538845719cd1e588185ce9ae60320377862ef8dDake Gu            }
30027538845719cd1e588185ce9ae60320377862ef8dDake Gu        });
30037538845719cd1e588185ce9ae60320377862ef8dDake Gu        waitForScrollIdle(mVerifyLayout);
30047538845719cd1e588185ce9ae60320377862ef8dDake Gu        humanDelay(500);
30057538845719cd1e588185ce9ae60320377862ef8dDake Gu
30067538845719cd1e588185ce9ae60320377862ef8dDake Gu
300742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3008e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
30097538845719cd1e588185ce9ae60320377862ef8dDake Gu            public void run() {
30107538845719cd1e588185ce9ae60320377862ef8dDake Gu                mGridView.setSelectedPositionSmooth(50);
30117538845719cd1e588185ce9ae60320377862ef8dDake Gu            }
30127538845719cd1e588185ce9ae60320377862ef8dDake Gu        });
30137538845719cd1e588185ce9ae60320377862ef8dDake Gu        Thread.sleep(100);
301442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3015e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
30167538845719cd1e588185ce9ae60320377862ef8dDake Gu            public void run() {
30177538845719cd1e588185ce9ae60320377862ef8dDake Gu                mGridView.requestLayout();
30187538845719cd1e588185ce9ae60320377862ef8dDake Gu                mGridView.setSelectedPositionSmooth(0);
30197538845719cd1e588185ce9ae60320377862ef8dDake Gu            }
30207538845719cd1e588185ce9ae60320377862ef8dDake Gu        });
30217538845719cd1e588185ce9ae60320377862ef8dDake Gu        waitForScrollIdle(mVerifyLayout);
30227538845719cd1e588185ce9ae60320377862ef8dDake Gu        humanDelay(500);
30237538845719cd1e588185ce9ae60320377862ef8dDake Gu
30247538845719cd1e588185ce9ae60320377862ef8dDake Gu    }
30257538845719cd1e588185ce9ae60320377862ef8dDake Gu
302606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
30273a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu    public void testSmoothscrollerInterrupted() throws Throwable {
302806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
30293a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
30303a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu                R.layout.vertical_linear);
30313a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
30323a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        int[] items = new int[100];
30333a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        for (int i = 0; i < items.length; i++) {
30343a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu            items[i] = 680;
30353a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        }
30363a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
30373a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
30383a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        mOrientation = BaseGridView.VERTICAL;
30393a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        mNumRows = 1;
30403a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu
30413a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        initActivity(intent);
30423a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu
30433a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        mGridView.setSelectedPositionSmooth(0);
30443a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        waitForScrollIdle(mVerifyLayout);
30453a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        assertTrue(mGridView.getChildAt(0).hasFocus());
30463a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu
30473a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        // Pressing lots of key to make sure smooth scroller is running
30483a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        for (int i = 0; i < 20; i++) {
304906dd2b62f48746fbb1447b171db882d0a458368eDake Gu            sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
30503a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        }
30513103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        while (mGridView.getLayoutManager().isSmoothScrolling()
30523103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                || mGridView.getScrollState() != BaseGridView.SCROLL_STATE_IDLE) {
3053b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            // Repeatedly pressing to make sure pending keys does not drop to zero.
3054b3034c5df0d06f3dbfa466af19b1f014967f3d75Dake Gu            sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
30553a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu        }
30563a7aa9cd68bd39f3a843291817dc209d1d9a45aaDake Gu    }
305757f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu
305806dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3059ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu    public void testSmoothscrollerCancelled() throws Throwable {
306006dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3061ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3062ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu                R.layout.vertical_linear);
3063ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
3064ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        int[] items = new int[100];
3065ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        for (int i = 0; i < items.length; i++) {
3066ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu            items[i] = 680;
3067ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        }
3068ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
3069ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
3070ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        mOrientation = BaseGridView.VERTICAL;
3071ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        mNumRows = 1;
3072ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu
3073ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        initActivity(intent);
3074ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu
3075ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        mGridView.setSelectedPositionSmooth(0);
3076ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        waitForScrollIdle(mVerifyLayout);
3077ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        assertTrue(mGridView.getChildAt(0).hasFocus());
3078ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu
3079ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        int targetPosition = items.length - 1;
3080ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        mGridView.setSelectedPositionSmooth(targetPosition);
308142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3082e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3083ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu            public void run() {
3084ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu                mGridView.stopScroll();
3085ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu            }
3086ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        });
3087134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForScrollIdle();
3088134b0891c25facf14c53ef939846010284025ca9Dake Gu        waitForItemAnimation();
3089ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        assertEquals(mGridView.getSelectedPosition(), targetPosition);
3090ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu        assertSame(mGridView.getLayoutManager().findViewByPosition(targetPosition),
3091ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu                mGridView.findFocus());
3092ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu    }
3093ac6a1a35cff83fdb50d9c8e203f881a54e92e40cDake Gu
309406dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
309557f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu    public void testSetNumRowsAndAddItem() throws Throwable {
309606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
309757f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
309857f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu                R.layout.vertical_linear);
309957f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
310057f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        int[] items = new int[2];
310157f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        for (int i = 0; i < items.length; i++) {
310257f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu            items[i] = 300;
310357f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        }
310457f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
310557f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
310657f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        mOrientation = BaseGridView.VERTICAL;
310757f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        mNumRows = 1;
310857f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu
310957f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        initActivity(intent);
311057f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu
311157f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        mGridView.setSelectedPositionSmooth(0);
311257f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        waitForScrollIdle(mVerifyLayout);
311357f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu
311457f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        mActivity.addItems(items.length, new int[]{300});
311557f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu
311642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3117e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
311857f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu            public void run() {
311957f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu                ((VerticalGridView) mGridView).setNumColumns(2);
312057f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu            }
312157f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        });
312257f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        Thread.sleep(1000);
312357f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu        assertTrue(mGridView.getChildAt(2).getLeft() != mGridView.getChildAt(1).getLeft());
312457f5baa07260dad2a9641e9ceb80567ce2784e9aDake Gu    }
3125c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu
3126c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu
312706dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3128c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu    public void testRequestLayoutBugInLayout() throws Throwable {
312906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3130c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3131c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu                R.layout.vertical_linear);
3132c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout);
3133c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
3134c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        int[] items = new int[100];
3135c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        for (int i = 0; i < items.length; i++) {
3136c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu            items[i] = 300;
3137c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        }
3138c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
3139c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
3140c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        mOrientation = BaseGridView.VERTICAL;
3141c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        mNumRows = 1;
3142c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu
3143c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        initActivity(intent);
3144c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu
314542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3146e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3147c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu            public void run() {
3148c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu                mGridView.setSelectedPositionSmooth(1);
3149c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu            }
3150c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        });
3151c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        waitForScrollIdle(mVerifyLayout);
3152c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu
315306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_UP);
3154c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        waitForScrollIdle(mVerifyLayout);
3155c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu
3156c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu        assertEquals("Line 2", ((TextView) mGridView.findFocus()).getText().toString());
3157c0b265dd2df42b399ba1f959b3dfd14dd14012b5Dake Gu    }
3158492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu
3159492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu
316006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3161492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu    public void testChangeLayoutInChild() throws Throwable {
316206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3163492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3164492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu                R.layout.vertical_linear_wrap_content);
3165492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true);
3166492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        int[] items = new int[2];
3167492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        for (int i = 0; i < items.length; i++) {
3168492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu            items[i] = 300;
3169492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        }
3170492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
3171492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
3172492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        mOrientation = BaseGridView.VERTICAL;
3173492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        mNumRows = 1;
3174492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu
3175492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        initActivity(intent);
3176492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu
317742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3178e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3179492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu            public void run() {
3180492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu                mGridView.setSelectedPositionSmooth(0);
3181492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu            }
3182492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        });
318321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(mVerifyLayout);
3184492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        verifyMargin();
3185492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu
318642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3187e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3188492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu            public void run() {
3189492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu                mGridView.setSelectedPositionSmooth(1);
3190492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu            }
3191492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        });
319221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(mVerifyLayout);
3193492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu        verifyMargin();
3194492506cede17ecee39ce7fa35ee7a347ff31c5baDake Gu    }
31951a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu
319606dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3197e2f2ff730ed20153aa006d655888190763c16d5cDake Gu    public void testWrapContent() throws Throwable {
319806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3199e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3200e2f2ff730ed20153aa006d655888190763c16d5cDake Gu                R.layout.horizontal_grid_wrap);
3201e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        int[] items = new int[200];
3202e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        for (int i = 0; i < items.length; i++) {
3203e2f2ff730ed20153aa006d655888190763c16d5cDake Gu            items[i] = 300;
3204e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        }
3205e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
3206e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        mOrientation = BaseGridView.HORIZONTAL;
3207e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        mNumRows = 1;
3208e2f2ff730ed20153aa006d655888190763c16d5cDake Gu
3209e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        initActivity(intent);
3210e2f2ff730ed20153aa006d655888190763c16d5cDake Gu
321142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3212e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3213e2f2ff730ed20153aa006d655888190763c16d5cDake Gu            public void run() {
3214e2f2ff730ed20153aa006d655888190763c16d5cDake Gu                mActivity.attachToNewAdapter(new int[0]);
3215e2f2ff730ed20153aa006d655888190763c16d5cDake Gu            }
3216e2f2ff730ed20153aa006d655888190763c16d5cDake Gu        });
3217e2f2ff730ed20153aa006d655888190763c16d5cDake Gu
3218e2f2ff730ed20153aa006d655888190763c16d5cDake Gu    }
3219e2f2ff730ed20153aa006d655888190763c16d5cDake Gu
322006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
32211a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu    public void testZeroFixedSecondarySize() throws Throwable {
322206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
32231a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
32241a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu                R.layout.vertical_linear_measured_with_zero);
32251a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        intent.putExtra(GridActivity.EXTRA_SECONDARY_SIZE_ZERO, true);
32261a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        int[] items = new int[2];
32271a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        for (int i = 0; i < items.length; i++) {
32281a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu            items[i] = 0;
32291a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        }
32301a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
32311a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
32321a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        mOrientation = BaseGridView.VERTICAL;
32331a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        mNumRows = 1;
32341a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu
32351a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu        initActivity(intent);
32361a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu
32371a5a2c58890e69b0554a82f22e3c0d1ffb238366Dake Gu    }
32383bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
323906dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
32403bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu    public void testChildStates() throws Throwable {
324106dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
32423bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
32433bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        int[] items = new int[100];
32443bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        for (int i = 0; i < items.length; i++) {
32453bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            items[i] = 200;
32463bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        }
32473bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
32483bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
32493bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true);
32503bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.selectable_text_view);
32513bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        mOrientation = BaseGridView.VERTICAL;
32523bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        mNumRows = 1;
32533bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
32543bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        initActivity(intent);
32553bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        mGridView.setSaveChildrenPolicy(VerticalGridView.SAVE_ALL_CHILD);
32563bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
325761e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        final SparseArray<Parcelable> container = new SparseArray<Parcelable>();
32583bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
32593bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        // 1 Save view states
326042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3261e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
32623bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            public void run() {
32633bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(0))
32643bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                        .getText()), 0, 1);
32653bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(1))
32663bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                        .getText()), 0, 1);
32673bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                mGridView.saveHierarchyState(container);
32683bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            }
32693bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        });
32703bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
32713bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        // 2 Change view states
327242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3273e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
32743bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            public void run() {
32753bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(0))
32763bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                        .getText()), 1, 2);
32773bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(1))
32783bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                        .getText()), 1, 2);
32793bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            }
32803bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        });
32813bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
32823bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        // 3 Detached and re-attached,  should still maintain state of (2)
328342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3284e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
32853bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            public void run() {
32863bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                mGridView.setSelectedPositionSmooth(1);
32873bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            }
32883bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        });
328921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(mVerifyLayout);
32903bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionStart(), 1);
32913bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionEnd(), 2);
32923bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionStart(), 1);
32933bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionEnd(), 2);
32943bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
32953bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        // 4 Recycled and rebound, should load state from (2)
329642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3297e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
32983bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            public void run() {
32993bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                mGridView.setSelectedPositionSmooth(20);
33003bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            }
33013bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        });
33023bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        waitForScrollIdle(mVerifyLayout);
330342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3304e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
33053bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            public void run() {
33063bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu                mGridView.setSelectedPositionSmooth(0);
33073bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu            }
33083bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        });
330921ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForScrollIdle(mVerifyLayout);
33103bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionStart(), 1);
33113bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(0)).getSelectionEnd(), 2);
33123bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionStart(), 1);
33133bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu        assertEquals(((TextView) mGridView.getChildAt(1)).getSelectionEnd(), 2);
33143bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu    }
33153bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
33163bd331ac6fe8ef25a2deb3559b0b5958573c231bDake Gu
331706dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
331861e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu    public void testNoDispatchSaveChildState() throws Throwable {
331906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
332061e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
332161e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        int[] items = new int[100];
332261e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        for (int i = 0; i < items.length; i++) {
332361e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu            items[i] = 200;
332461e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        }
332561e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
332661e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
332761e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.selectable_text_view);
332861e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        mOrientation = BaseGridView.VERTICAL;
332961e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        mNumRows = 1;
333061e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu
333161e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        initActivity(intent);
333261e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        mGridView.setSaveChildrenPolicy(VerticalGridView.SAVE_NO_CHILD);
333361e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu
333461e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        final SparseArray<Parcelable> container = new SparseArray<Parcelable>();
333561e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu
333661e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        // 1. Set text selection, save view states should do nothing on child
333742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3338e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
333961e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu            public void run() {
334061e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                for (int i = 0; i < mGridView.getChildCount(); i++) {
334161e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                    Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(i))
334261e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                            .getText()), 0, 1);
334361e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                }
334461e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                mGridView.saveHierarchyState(container);
334561e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu            }
334661e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        });
334761e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu
334861e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        // 2. clear the text selection
334942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3350e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
335161e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu            public void run() {
335261e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                for (int i = 0; i < mGridView.getChildCount(); i++) {
335361e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                    Selection.removeSelection((Spannable)(((TextView) mGridView.getChildAt(i))
335461e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                            .getText()));
335561e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                }
335661e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu            }
335761e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        });
335861e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu
335961e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        // 3. Restore view states should be a no-op for child
336042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3361e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
336261e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu            public void run() {
336361e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                mGridView.restoreHierarchyState(container);
336461e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                for (int i = 0; i < mGridView.getChildCount(); i++) {
336561e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                    assertEquals(-1, ((TextView) mGridView.getChildAt(i)).getSelectionStart());
336661e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                    assertEquals(-1, ((TextView) mGridView.getChildAt(i)).getSelectionEnd());
336761e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu                }
336861e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu            }
336961e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu        });
337061e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu    }
337161e5a56ed066815e69be7526e3d1bee2d5268d20Dake Gu
337208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
337308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    static interface ViewTypeProvider {
337408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        public int getViewType(int position);
337508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
337608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
337708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    static interface ItemAlignmentFacetProvider {
337808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        public ItemAlignmentFacet getItemAlignmentFacet(int viewType);
337908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
338008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
338108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    static class TwoViewTypesProvider implements ViewTypeProvider {
338208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        static int VIEW_TYPE_FIRST = 1;
338308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        static int VIEW_TYPE_DEFAULT = 0;
338408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        @Override
338508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        public int getViewType(int position) {
338608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            if (position == 0) {
338708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return VIEW_TYPE_FIRST;
338808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            } else {
338908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return VIEW_TYPE_DEFAULT;
339008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            }
339108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
339208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
339308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
339400e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu    static class ChangeableViewTypesProvider implements ViewTypeProvider {
339500e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        static SparseIntArray sViewTypes = new SparseIntArray();
339600e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        @Override
339700e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        public int getViewType(int position) {
339800e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu            return sViewTypes.get(position);
339900e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        }
340000e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        public static void clear() {
340100e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu            sViewTypes.clear();
340200e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        }
340300e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        public static void setViewType(int position, int type) {
340400e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu            sViewTypes.put(position, type);
340500e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        }
340600e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu    }
340700e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu
340808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    static class PositionItemAlignmentFacetProviderForRelativeLayout1
340908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            implements ItemAlignmentFacetProvider {
341008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        ItemAlignmentFacet mMultipleFacet;
341108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
341208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        PositionItemAlignmentFacetProviderForRelativeLayout1() {
341308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            mMultipleFacet = new ItemAlignmentFacet();
341408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            ItemAlignmentFacet.ItemAlignmentDef[] defs =
341508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                    new ItemAlignmentFacet.ItemAlignmentDef[2];
341608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
341708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0].setItemAlignmentViewId(R.id.t1);
341808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1] = new ItemAlignmentFacet.ItemAlignmentDef();
341908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentViewId(R.id.t2);
342008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentOffsetPercent(100);
342108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentOffset(-10);
342208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            mMultipleFacet.setAlignmentDefs(defs);
342308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
342408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
342508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        @Override
342608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        public ItemAlignmentFacet getItemAlignmentFacet(int position) {
342708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            if (position == 0) {
342808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return mMultipleFacet;
342908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            } else {
343008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return null;
343108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            }
343208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
343308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
343408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
343506dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
343608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    public void testMultipleScrollPosition1() throws Throwable {
343706dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
343808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
343908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                R.layout.vertical_linear);
344008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout);
344108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
344208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int[] items = new int[100];
344308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        for (int i = 0; i < items.length; i++) {
344408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            items[i] = 300;
344508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
344608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
344708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
344808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
344908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                TwoViewTypesProvider.class.getName());
345008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        // Set ItemAlignment for each ViewHolder and view type,  ViewHolder should
345108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        // override the view type settings.
345208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS,
345308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                PositionItemAlignmentFacetProviderForRelativeLayout1.class.getName());
345408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_VIEWTYPE_CLASS,
345508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2.class.getName());
345608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        mOrientation = BaseGridView.VERTICAL;
345708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        mNumRows = 1;
345808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
345908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        initActivity(intent);
346008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
346108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        assertEquals("First view is aligned with padding top",
346208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                mGridView.getPaddingTop(), mGridView.getChildAt(0).getTop());
346308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
346406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
346508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        waitForScrollIdle(mVerifyLayout);
346608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
346708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        final View v = mGridView.getChildAt(0);
346808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        View t1 = v.findViewById(R.id.t1);
346908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int t1align = (t1.getTop() + t1.getBottom()) / 2;
347008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        View t2 = v.findViewById(R.id.t2);
347108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int t2align = t2.getBottom() - 10;
347208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        assertEquals("Expected alignment for 2nd textview",
347308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                mGridView.getPaddingTop() - (t2align - t1align),
347408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                v.getTop());
347508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
347608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
347708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    static class PositionItemAlignmentFacetProviderForRelativeLayout2 implements
347808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            ItemAlignmentFacetProvider {
347908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        ItemAlignmentFacet mMultipleFacet;
348008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
348108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        PositionItemAlignmentFacetProviderForRelativeLayout2() {
348208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            mMultipleFacet = new ItemAlignmentFacet();
348308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            ItemAlignmentFacet.ItemAlignmentDef[] defs = new ItemAlignmentFacet.ItemAlignmentDef[2];
348408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
348508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0].setItemAlignmentViewId(R.id.t1);
348608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0].setItemAlignmentOffsetPercent(0);
348708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1] = new ItemAlignmentFacet.ItemAlignmentDef();
348808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentViewId(R.id.t2);
348908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentOffsetPercent(ItemAlignmentFacet.ITEM_ALIGN_OFFSET_PERCENT_DISABLED);
349008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentOffset(-10);
349108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            mMultipleFacet.setAlignmentDefs(defs);
349208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
349308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
349408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        @Override
349508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        public ItemAlignmentFacet getItemAlignmentFacet(int position) {
349608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            if (position == 0) {
349708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return mMultipleFacet;
349808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            } else {
349908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return null;
350008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            }
350108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
350208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
350308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
350406dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
350508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    public void testMultipleScrollPosition2() throws Throwable {
350606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
350708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
350808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout);
350908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
351008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int[] items = new int[100];
351108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        for (int i = 0; i < items.length; i++) {
351208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            items[i] = 300;
351308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
351408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
351508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
351608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
351708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                TwoViewTypesProvider.class.getName());
351808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS,
351908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                PositionItemAlignmentFacetProviderForRelativeLayout2.class.getName());
352008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        mOrientation = BaseGridView.VERTICAL;
352108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        mNumRows = 1;
352208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
352308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        initActivity(intent);
352408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
352508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
352608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                mGridView.getChildAt(0).getTop());
352708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
352806dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
352908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        waitForScrollIdle(mVerifyLayout);
353008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
353108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        final View v = mGridView.getChildAt(0);
353208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        View t1 = v.findViewById(R.id.t1);
353308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int t1align = t1.getTop();
353408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        View t2 = v.findViewById(R.id.t2);
353508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int t2align = t2.getTop() - 10;
353608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        assertEquals("Expected alignment for 2nd textview",
353708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                mGridView.getPaddingTop() - (t2align - t1align), v.getTop());
353808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
353908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
354008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    static class ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2 implements
354108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            ItemAlignmentFacetProvider {
354208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        ItemAlignmentFacet mMultipleFacet;
354308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
354408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2() {
354508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            mMultipleFacet = new ItemAlignmentFacet();
354608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            ItemAlignmentFacet.ItemAlignmentDef[] defs = new ItemAlignmentFacet.ItemAlignmentDef[2];
354708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
354808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0].setItemAlignmentViewId(R.id.t1);
354908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[0].setItemAlignmentOffsetPercent(0);
355008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1] = new ItemAlignmentFacet.ItemAlignmentDef();
355108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentViewId(R.id.t2);
355208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentOffsetPercent(100);
355308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            defs[1].setItemAlignmentOffset(-10);
355408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            mMultipleFacet.setAlignmentDefs(defs);
355508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
355608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
355708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        @Override
355808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        public ItemAlignmentFacet getItemAlignmentFacet(int viewType) {
355908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            if (viewType == TwoViewTypesProvider.VIEW_TYPE_FIRST) {
356008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return mMultipleFacet;
356108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            } else {
356208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                return null;
356308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            }
356408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
356508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
356608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
356706dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
356808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    public void testMultipleScrollPosition3() throws Throwable {
356906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
357008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
357108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout);
357208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
357308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int[] items = new int[100];
357408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        for (int i = 0; i < items.length; i++) {
357508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu            items[i] = 300;
357608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        }
357708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
357808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
357908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
358008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                TwoViewTypesProvider.class.getName());
358108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_VIEWTYPE_CLASS,
358208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                ViewTypePositionItemAlignmentFacetProviderForRelativeLayout2.class.getName());
358308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        mOrientation = BaseGridView.VERTICAL;
358408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        mNumRows = 1;
358508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
358608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        initActivity(intent);
358708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
358808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
358908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                mGridView.getChildAt(0).getTop());
359008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
359106dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
359208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        waitForScrollIdle(mVerifyLayout);
359308c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
359408c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        final View v = mGridView.getChildAt(0);
359508c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        View t1 = v.findViewById(R.id.t1);
359608c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int t1align = t1.getTop();
359708c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        View t2 = v.findViewById(R.id.t2);
359808c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        int t2align = t2.getBottom() - 10;
359908c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu        assertEquals("Expected alignment for 2nd textview",
360008c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu                mGridView.getPaddingTop() - (t2align - t1align), v.getTop());
360108c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu    }
360208c56822b71ab0aa0b9bb03e5fd45e28f6e358b8Dake Gu
360306dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3604db0b1afb71440b79923692d58adee982b5954838Dake Gu    public void testSelectionAndAddItemInOneCycle() throws Throwable {
360506dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3606db0b1afb71440b79923692d58adee982b5954838Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3607db0b1afb71440b79923692d58adee982b5954838Dake Gu                R.layout.vertical_linear);
3608db0b1afb71440b79923692d58adee982b5954838Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 0);
3609db0b1afb71440b79923692d58adee982b5954838Dake Gu        initActivity(intent);
3610db0b1afb71440b79923692d58adee982b5954838Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
3611db0b1afb71440b79923692d58adee982b5954838Dake Gu        mNumRows = 1;
3612db0b1afb71440b79923692d58adee982b5954838Dake Gu
361321ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
3614e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3615db0b1afb71440b79923692d58adee982b5954838Dake Gu            public void run() {
3616db0b1afb71440b79923692d58adee982b5954838Dake Gu                mActivity.addItems(0, new int[]{300, 300});
3617db0b1afb71440b79923692d58adee982b5954838Dake Gu                mGridView.setSelectedPosition(0);
3618db0b1afb71440b79923692d58adee982b5954838Dake Gu            }
3619db0b1afb71440b79923692d58adee982b5954838Dake Gu        });
3620db0b1afb71440b79923692d58adee982b5954838Dake Gu        assertEquals(0, mGridView.getSelectedPosition());
3621db0b1afb71440b79923692d58adee982b5954838Dake Gu    }
3622db0b1afb71440b79923692d58adee982b5954838Dake Gu
362306dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
36247a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu    public void testSelectViewTaskSmoothWithAdapterChange() throws Throwable {
36257a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        testSelectViewTaskWithAdapterChange(true /*smooth*/);
36267a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu    }
36277a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu
362806dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
36297a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu    public void testSelectViewTaskWithAdapterChange() throws Throwable {
36307a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        testSelectViewTaskWithAdapterChange(false /*smooth*/);
36317a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu    }
36327a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu
36337a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu    private void testSelectViewTaskWithAdapterChange(final boolean smooth) throws Throwable {
363406dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
36357a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
36367a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                R.layout.vertical_linear);
36377a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2);
36387a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        initActivity(intent);
36397a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        mOrientation = BaseGridView.HORIZONTAL;
36407a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        mNumRows = 1;
36417a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu
36427a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        final View firstView = mGridView.getLayoutManager().findViewByPosition(0);
36437a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        final View[] selectedViewByTask = new View[1];
36447a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        final ViewHolderTask task = new ViewHolderTask() {
3645e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
36467a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu            public void run(RecyclerView.ViewHolder viewHolder) {
36477a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                selectedViewByTask[0] = viewHolder.itemView;
36487a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu            }
36497a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        };
365021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
3651e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
36527a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu            public void run() {
36537a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                mActivity.removeItems(0, 1);
36547a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                if (smooth) {
36557a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                    mGridView.setSelectedPositionSmooth(0, task);
36567a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                } else {
36577a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                    mGridView.setSelectedPosition(0, task);
36587a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu                }
36597a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu            }
36607a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        });
36617a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        assertEquals(0, mGridView.getSelectedPosition());
36627a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        assertNotNull(selectedViewByTask[0]);
36637a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        assertNotSame(firstView, selectedViewByTask[0]);
36647a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu        assertSame(mGridView.getLayoutManager().findViewByPosition(0), selectedViewByTask[0]);
36657a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu    }
36667a38d7478bb7a0ec2bfc87e50b77c93fe5f66bfeDake Gu
366706dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
366800e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu    public void testNotifyItemTypeChangedSelectionEvent() throws Throwable {
366906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
367000e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
367100e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu                R.layout.vertical_linear);
367200e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
367300e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
367400e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu                ChangeableViewTypesProvider.class.getName());
367500e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        ChangeableViewTypesProvider.clear();
367600e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        initActivity(intent);
367700e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
367800e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        mNumRows = 1;
367900e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu
368000e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        final ArrayList<Integer> selectedLog = new ArrayList<Integer>();
368100e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        mGridView.setOnChildSelectedListener(new OnChildSelectedListener() {
3682e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
368300e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
368400e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu                selectedLog.add(position);
368500e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu            }
368600e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        });
368700e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu
368821ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
3689e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
369000e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu            public void run() {
369100e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu                ChangeableViewTypesProvider.setViewType(0, 1);
369200e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu                mGridView.getAdapter().notifyItemChanged(0, 1);
369300e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu            }
369400e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        });
369500e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        assertEquals(0, mGridView.getSelectedPosition());
369600e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        assertEquals(selectedLog.size(), 1);
369700e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu        assertEquals((int) selectedLog.get(0), 0);
369800e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu    }
369900e05297683e1cc2a5fb25a00632a778b7b5d0e4Dake Gu
370006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3701db0b1afb71440b79923692d58adee982b5954838Dake Gu    public void testSelectionSmoothAndAddItemInOneCycle() throws Throwable {
370206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3703db0b1afb71440b79923692d58adee982b5954838Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3704db0b1afb71440b79923692d58adee982b5954838Dake Gu                R.layout.vertical_linear);
3705db0b1afb71440b79923692d58adee982b5954838Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 0);
3706db0b1afb71440b79923692d58adee982b5954838Dake Gu        initActivity(intent);
3707db0b1afb71440b79923692d58adee982b5954838Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
3708db0b1afb71440b79923692d58adee982b5954838Dake Gu        mNumRows = 1;
3709db0b1afb71440b79923692d58adee982b5954838Dake Gu
371021ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
3711e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3712db0b1afb71440b79923692d58adee982b5954838Dake Gu            public void run() {
3713db0b1afb71440b79923692d58adee982b5954838Dake Gu                mActivity.addItems(0, new int[]{300, 300});
3714db0b1afb71440b79923692d58adee982b5954838Dake Gu                mGridView.setSelectedPositionSmooth(0);
3715db0b1afb71440b79923692d58adee982b5954838Dake Gu            }
3716db0b1afb71440b79923692d58adee982b5954838Dake Gu        });
3717db0b1afb71440b79923692d58adee982b5954838Dake Gu        assertEquals(0, mGridView.getSelectedPosition());
3718db0b1afb71440b79923692d58adee982b5954838Dake Gu    }
371988dea72af6042049560140a70e059820dbb8f746Dake Gu
372006dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
372188dea72af6042049560140a70e059820dbb8f746Dake Gu    public void testExtraLayoutSpace() throws Throwable {
372206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
372388dea72af6042049560140a70e059820dbb8f746Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
372488dea72af6042049560140a70e059820dbb8f746Dake Gu                R.layout.vertical_linear);
372588dea72af6042049560140a70e059820dbb8f746Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000);
372688dea72af6042049560140a70e059820dbb8f746Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
372788dea72af6042049560140a70e059820dbb8f746Dake Gu        initActivity(intent);
372888dea72af6042049560140a70e059820dbb8f746Dake Gu
372988dea72af6042049560140a70e059820dbb8f746Dake Gu        final int windowSize = mGridView.getHeight();
373088dea72af6042049560140a70e059820dbb8f746Dake Gu        final int extraLayoutSize = windowSize;
373188dea72af6042049560140a70e059820dbb8f746Dake Gu        mOrientation = BaseGridView.VERTICAL;
373288dea72af6042049560140a70e059820dbb8f746Dake Gu        mNumRows = 1;
373388dea72af6042049560140a70e059820dbb8f746Dake Gu
373488dea72af6042049560140a70e059820dbb8f746Dake Gu        // add extra layout space
373521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        startWaitLayout();
373642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3737e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
373888dea72af6042049560140a70e059820dbb8f746Dake Gu            public void run() {
373988dea72af6042049560140a70e059820dbb8f746Dake Gu                mGridView.setExtraLayoutSpace(extraLayoutSize);
374088dea72af6042049560140a70e059820dbb8f746Dake Gu            }
374188dea72af6042049560140a70e059820dbb8f746Dake Gu        });
374221ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        waitForLayout();
374388dea72af6042049560140a70e059820dbb8f746Dake Gu        View v;
374488dea72af6042049560140a70e059820dbb8f746Dake Gu        v = mGridView.getChildAt(mGridView.getChildCount() - 1);
374588dea72af6042049560140a70e059820dbb8f746Dake Gu        assertTrue(v.getTop() < windowSize + extraLayoutSize);
37463103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        assertTrue(v.getBottom() >= windowSize + extraLayoutSize - mGridView.getVerticalMargin());
374788dea72af6042049560140a70e059820dbb8f746Dake Gu
374888dea72af6042049560140a70e059820dbb8f746Dake Gu        mGridView.setSelectedPositionSmooth(150);
374988dea72af6042049560140a70e059820dbb8f746Dake Gu        waitForScrollIdle(mVerifyLayout);
375088dea72af6042049560140a70e059820dbb8f746Dake Gu        v = mGridView.getChildAt(0);
375188dea72af6042049560140a70e059820dbb8f746Dake Gu        assertTrue(v.getBottom() > - extraLayoutSize);
375288dea72af6042049560140a70e059820dbb8f746Dake Gu        assertTrue(v.getTop() <= -extraLayoutSize + mGridView.getVerticalMargin());
375388dea72af6042049560140a70e059820dbb8f746Dake Gu
375488dea72af6042049560140a70e059820dbb8f746Dake Gu        // clear extra layout space
375542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3756e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
375788dea72af6042049560140a70e059820dbb8f746Dake Gu            public void run() {
375888dea72af6042049560140a70e059820dbb8f746Dake Gu                mGridView.setExtraLayoutSpace(0);
375988dea72af6042049560140a70e059820dbb8f746Dake Gu                verifyMargin();
376088dea72af6042049560140a70e059820dbb8f746Dake Gu            }
376188dea72af6042049560140a70e059820dbb8f746Dake Gu        });
376288dea72af6042049560140a70e059820dbb8f746Dake Gu        Thread.sleep(50);
376388dea72af6042049560140a70e059820dbb8f746Dake Gu        v = mGridView.getChildAt(mGridView.getChildCount() - 1);
376488dea72af6042049560140a70e059820dbb8f746Dake Gu        assertTrue(v.getTop() < windowSize);
376588dea72af6042049560140a70e059820dbb8f746Dake Gu        assertTrue(v.getBottom() >= windowSize - mGridView.getVerticalMargin());
376688dea72af6042049560140a70e059820dbb8f746Dake Gu    }
3767d1cab1b54104d55407335c5d649398635822fffdDake Gu
376806dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3769fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu    public void testFocusFinder() throws Throwable {
377006dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3771fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3772fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu                R.layout.vertical_linear_with_button);
3773fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 3);
3774fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
3775fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        initActivity(intent);
3776fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        mOrientation = BaseGridView.VERTICAL;
3777fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        mNumRows = 1;
3778fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu
3779fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        // test focus from button to vertical grid view
3780fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        final View button = mActivity.findViewById(R.id.button);
3781fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        assertTrue(button.isFocused());
378206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
3783fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        assertFalse(mGridView.isFocused());
3784fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        assertTrue(mGridView.hasFocus());
3785fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu
3786fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        // FocusFinder should find last focused(2nd) item on DPAD_DOWN
3787fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        final View secondChild = mGridView.getChildAt(1);
378842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3789fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu            @Override
3790fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu            public void run() {
3791fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu                secondChild.requestFocus();
3792fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu                button.requestFocus();
3793fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu            }
3794fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        });
3795fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        assertTrue(button.isFocused());
379606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
3797fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        assertTrue(secondChild.isFocused());
3798fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu
3799fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        // Bug 26918143 Even VerticalGridView is not focusable, FocusFinder should find last focused
3800fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        // (2nd) item on DPAD_DOWN.
380142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3802fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu            @Override
3803fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu            public void run() {
3804fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu                button.requestFocus();
3805fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu            }
3806fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        });
3807fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        mGridView.setFocusable(false);
3808fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        mGridView.setFocusableInTouchMode(false);
3809fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        assertTrue(button.isFocused());
381006dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
3811fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu        assertTrue(secondChild.isFocused());
3812fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu    }
3813fd4ac97d700ae14ed2b4bb2f0eb6ef83c68a6966Dake Gu
381406dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3815936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu    public void testRestoreIndexAndAddItems() throws Throwable {
381606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3817936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3818936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu                R.layout.vertical_linear);
3819936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.horizontal_item);
3820936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 4);
3821936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        initActivity(intent);
3822936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        mOrientation = BaseGridView.VERTICAL;
3823936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        mNumRows = 1;
3824936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu
3825936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        assertEquals(mGridView.getSelectedPosition(), 0);
3826abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas        final SparseArray<Parcelable> states = new SparseArray<>();
382742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3828936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu            @Override
3829936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu            public void run() {
3830936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu                mGridView.saveHierarchyState(states);
3831936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu                mGridView.setAdapter(null);
3832936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu            }
3833936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu
3834936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        });
383521ac4a7e2cc753b4e4eeaa7edb9696add157ebf8Dake Gu        performAndWaitForAnimation(new Runnable() {
3836936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu            @Override
3837936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu            public void run() {
3838936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu                mGridView.restoreHierarchyState(states);
3839936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu                mActivity.attachToNewAdapter(new int[0]);
3840936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu                mActivity.addItems(0, new int[]{100, 100, 100, 100});
3841936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu            }
3842936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu
3843936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        });
3844936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu        assertEquals(mGridView.getSelectedPosition(), 0);
3845936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu    }
3846936fd406f49a6fae8768084e84fa7d1beccf40a9Dake Gu
384706dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3848678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu    public void test27766012() throws Throwable {
384906dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3850678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3851678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu                R.layout.vertical_linear_with_button_onleft);
3852678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.horizontal_item);
3853678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 2);
3854678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
3855678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, false);
3856678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        initActivity(intent);
3857678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        mOrientation = BaseGridView.VERTICAL;
3858678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        mNumRows = 1;
3859678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu
3860678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        // set remove animator two seconds
3861678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        mGridView.getItemAnimator().setRemoveDuration(2000);
3862678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        final View view = mGridView.getChildAt(1);
386342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3864678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            @Override
3865678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            public void run() {
3866678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu                view.requestFocus();
3867678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            }
3868678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        });
3869678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        assertTrue(view.hasFocus());
387042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3871678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            @Override
3872678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            public void run() {
3873678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu                mActivity.removeItems(0, 2);
3874678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            }
3875678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu
3876678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        });
3877678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        // wait one second, removing second view is still attached to parent
3878678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        Thread.sleep(1000);
3879678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        assertSame(view.getParent(), mGridView);
388042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3881678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            @Override
3882678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            public void run() {
3883678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu                // refocus to the removed item and do a focus search.
3884678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu                view.requestFocus();
3885678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu                view.focusSearch(View.FOCUS_UP);
3886678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu            }
3887678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu
3888678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu        });
3889678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu    }
3890678a58f6a6772d955f21d1ff869f2bcd999aade3Dake Gu
389106dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
3892362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu    public void testBug27258366() throws Throwable {
389306dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
3894362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
3895362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                R.layout.vertical_linear_with_button_onleft);
3896362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.horizontal_item);
3897362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
3898362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
3899362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, false);
3900362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        initActivity(intent);
3901362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        mOrientation = BaseGridView.VERTICAL;
3902362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        mNumRows = 1;
3903362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu
3904362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        // move item1 500 pixels right, when focus is on item1, default focus finder will pick
3905362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        // item0 and item2 for the best match of focusSearch(FOCUS_LEFT).  The grid widget
3906362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        // must override default addFocusables(), not to add item0 or item2.
3907362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        mActivity.mAdapterListener = new GridActivity.AdapterListener() {
3908e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
3909362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            public void onBind(RecyclerView.ViewHolder vh, int position) {
3910362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                if (position == 1) {
3911362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                    vh.itemView.setPaddingRelative(500, 0, 0, 0);
3912362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                } else {
3913362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                    vh.itemView.setPaddingRelative(0, 0, 0, 0);
3914362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                }
3915362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            }
3916362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        };
391742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3918362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            @Override
3919362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            public void run() {
3920362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                mGridView.getAdapter().notifyDataSetChanged();
3921362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            }
3922362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        });
3923362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        Thread.sleep(100);
3924362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu
3925362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        final ViewGroup secondChild = (ViewGroup) mGridView.getChildAt(1);
392642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
3927362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            @Override
3928362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            public void run() {
3929362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu                secondChild.requestFocus();
3930362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu            }
3931362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        });
393206dd2b62f48746fbb1447b171db882d0a458368eDake Gu        sendKey(KeyEvent.KEYCODE_DPAD_LEFT);
3933362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        Thread.sleep(100);
3934362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        final View button = mActivity.findViewById(R.id.button);
3935362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu        assertTrue(button.isFocused());
3936362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu    }
3937362fda0323b85ec2379967901a0bd33a2ad4b8b5Dake Gu
393806dd2b62f48746fbb1447b171db882d0a458368eDake Gu    @Test
39397ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    public void testUpdateHeightScrollHorizontal() throws Throwable {
39407ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        Intent intent = new Intent();
39417ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
39427ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                R.layout.horizontal_linear);
39437ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 30);
39447ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
39457ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true);
39467ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, false);
39477ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE_SECONDARY, true);
39487ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        initActivity(intent);
39497ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        mOrientation = BaseGridView.HORIZONTAL;
39507ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        mNumRows = 1;
39517ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu
39527ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        final int childTop = mGridView.getChildAt(0).getTop();
39537ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        // scroll to end, all children's top should not change.
39547ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        scrollToEnd(new Runnable() {
39557ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            @Override
39567ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            public void run() {
39577ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                for (int i = 0; i < mGridView.getChildCount(); i++) {
39587ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                    assertEquals(childTop, mGridView.getChildAt(i).getTop());
39597ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                }
39607ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            }
39617ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        });
39627ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        // sanity check last child has focus with a larger height.
39637ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        assertTrue(mGridView.getChildAt(0).getHeight()
39647ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                < mGridView.getChildAt(mGridView.getChildCount() - 1).getHeight());
39657ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    }
39667ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu
39677ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    @Test
39687ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    public void testUpdateWidthScrollHorizontal() throws Throwable {
39697ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        Intent intent = new Intent();
39707ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
39717ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                R.layout.horizontal_linear);
39727ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 30);
39737ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
39747ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true);
39757ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, true);
39767ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE_SECONDARY, false);
39777ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        initActivity(intent);
39787ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        mOrientation = BaseGridView.HORIZONTAL;
39797ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        mNumRows = 1;
39807ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu
39817ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        final int childTop = mGridView.getChildAt(0).getTop();
39827ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        // scroll to end, all children's top should not change.
39837ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        scrollToEnd(new Runnable() {
39847ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            @Override
39857ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            public void run() {
39867ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                for (int i = 0; i < mGridView.getChildCount(); i++) {
39877ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                    assertEquals(childTop, mGridView.getChildAt(i).getTop());
39887ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                }
39897ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            }
39907ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        });
39917ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        // sanity check last child has focus with a larger width.
39927ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        assertTrue(mGridView.getChildAt(0).getWidth()
39937ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                < mGridView.getChildAt(mGridView.getChildCount() - 1).getWidth());
39947ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        if (mGridView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
39957ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            assertEquals(mGridView.getPaddingLeft(),
39967ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                    mGridView.getChildAt(mGridView.getChildCount() - 1).getLeft());
39977ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        } else {
39987ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            assertEquals(mGridView.getWidth() - mGridView.getPaddingRight(),
39997ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                    mGridView.getChildAt(mGridView.getChildCount() - 1).getRight());
40007ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        }
40017ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    }
40027ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu
40037ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    @Test
40047ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    public void testUpdateWidthScrollHorizontalRtl() throws Throwable {
40057ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        Intent intent = new Intent();
40067ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
40077ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                R.layout.horizontal_linear_rtl);
40087ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 30);
40097ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
40107ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_LAYOUT_ONFOCUS, true);
40117ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE, true);
40127ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        intent.putExtra(GridActivity.EXTRA_UPDATE_SIZE_SECONDARY, false);
40137ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        initActivity(intent);
40147ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        mOrientation = BaseGridView.HORIZONTAL;
40157ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        mNumRows = 1;
40167ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu
40177ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        final int childTop = mGridView.getChildAt(0).getTop();
40187ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        // scroll to end, all children's top should not change.
40197ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        scrollToEnd(new Runnable() {
40207ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            @Override
40217ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            public void run() {
40227ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                for (int i = 0; i < mGridView.getChildCount(); i++) {
40237ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                    assertEquals(childTop, mGridView.getChildAt(i).getTop());
40247ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                }
40257ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu            }
40267ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        });
40277ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        // sanity check last child has focus with a larger width.
40287ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        assertTrue(mGridView.getChildAt(0).getWidth()
40297ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                < mGridView.getChildAt(mGridView.getChildCount() - 1).getWidth());
40307ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu        assertEquals(mGridView.getPaddingLeft(),
40317ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu                mGridView.getChildAt(mGridView.getChildCount() - 1).getLeft());
40327ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    }
40337ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu
40347ef219d3d0ce885caeaa2064178159b72ddb273fDake Gu    @Test
4035d1cab1b54104d55407335c5d649398635822fffdDake Gu    public void testAccessibility() throws Throwable {
403606dd2b62f48746fbb1447b171db882d0a458368eDake Gu        Intent intent = new Intent();
4037d1cab1b54104d55407335c5d649398635822fffdDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
4038d1cab1b54104d55407335c5d649398635822fffdDake Gu                R.layout.vertical_linear);
4039d1cab1b54104d55407335c5d649398635822fffdDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 1000);
4040d1cab1b54104d55407335c5d649398635822fffdDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4041d1cab1b54104d55407335c5d649398635822fffdDake Gu        initActivity(intent);
4042d1cab1b54104d55407335c5d649398635822fffdDake Gu        mOrientation = BaseGridView.VERTICAL;
4043d1cab1b54104d55407335c5d649398635822fffdDake Gu        mNumRows = 1;
4044d1cab1b54104d55407335c5d649398635822fffdDake Gu
4045d1cab1b54104d55407335c5d649398635822fffdDake Gu        assertTrue(0 == mGridView.getSelectedPosition());
4046d1cab1b54104d55407335c5d649398635822fffdDake Gu
4047d1cab1b54104d55407335c5d649398635822fffdDake Gu        final RecyclerViewAccessibilityDelegate delegateCompat = mGridView
4048d1cab1b54104d55407335c5d649398635822fffdDake Gu                .getCompatAccessibilityDelegate();
4049d1cab1b54104d55407335c5d649398635822fffdDake Gu        final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
405042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
4051d1cab1b54104d55407335c5d649398635822fffdDake Gu            @Override
4052d1cab1b54104d55407335c5d649398635822fffdDake Gu            public void run() {
4053d1cab1b54104d55407335c5d649398635822fffdDake Gu                delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info);
4054d1cab1b54104d55407335c5d649398635822fffdDake Gu            }
4055d1cab1b54104d55407335c5d649398635822fffdDake Gu        });
4056d1cab1b54104d55407335c5d649398635822fffdDake Gu        assertTrue("test sanity", info.isScrollable());
405742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
4058d1cab1b54104d55407335c5d649398635822fffdDake Gu            @Override
4059d1cab1b54104d55407335c5d649398635822fffdDake Gu            public void run() {
4060d1cab1b54104d55407335c5d649398635822fffdDake Gu                delegateCompat.performAccessibilityAction(mGridView,
4061d1cab1b54104d55407335c5d649398635822fffdDake Gu                        AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD, null);
4062d1cab1b54104d55407335c5d649398635822fffdDake Gu            }
4063d1cab1b54104d55407335c5d649398635822fffdDake Gu        });
4064d1cab1b54104d55407335c5d649398635822fffdDake Gu        waitForScrollIdle(mVerifyLayout);
4065d1cab1b54104d55407335c5d649398635822fffdDake Gu        int selectedPosition1 = mGridView.getSelectedPosition();
4066d1cab1b54104d55407335c5d649398635822fffdDake Gu        assertTrue(0 < selectedPosition1);
4067d1cab1b54104d55407335c5d649398635822fffdDake Gu
406842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
4069d1cab1b54104d55407335c5d649398635822fffdDake Gu            @Override
4070d1cab1b54104d55407335c5d649398635822fffdDake Gu            public void run() {
4071d1cab1b54104d55407335c5d649398635822fffdDake Gu                delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info);
4072d1cab1b54104d55407335c5d649398635822fffdDake Gu            }
4073d1cab1b54104d55407335c5d649398635822fffdDake Gu        });
4074d1cab1b54104d55407335c5d649398635822fffdDake Gu        assertTrue("test sanity", info.isScrollable());
407542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityTestRule.runOnUiThread(new Runnable() {
4076d1cab1b54104d55407335c5d649398635822fffdDake Gu            @Override
4077d1cab1b54104d55407335c5d649398635822fffdDake Gu            public void run() {
4078d1cab1b54104d55407335c5d649398635822fffdDake Gu                delegateCompat.performAccessibilityAction(mGridView,
4079d1cab1b54104d55407335c5d649398635822fffdDake Gu                        AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD, null);
4080d1cab1b54104d55407335c5d649398635822fffdDake Gu            }
4081d1cab1b54104d55407335c5d649398635822fffdDake Gu        });
4082d1cab1b54104d55407335c5d649398635822fffdDake Gu        waitForScrollIdle(mVerifyLayout);
4083d1cab1b54104d55407335c5d649398635822fffdDake Gu        int selectedPosition2 = mGridView.getSelectedPosition();
4084d1cab1b54104d55407335c5d649398635822fffdDake Gu        assertTrue(selectedPosition2 < selectedPosition1);
4085d1cab1b54104d55407335c5d649398635822fffdDake Gu    }
4086d1cab1b54104d55407335c5d649398635822fffdDake Gu
40874297da73f24135b4448d2e36f6cf50499d095448Dake Gu    @Test
40884297da73f24135b4448d2e36f6cf50499d095448Dake Gu    public void testAccessibilityScrollForwardHalfVisible() throws Throwable {
40894297da73f24135b4448d2e36f6cf50499d095448Dake Gu        Intent intent = new Intent();
40904297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
40914297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.item_button_at_bottom);
40924297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS,  new int[]{});
40934297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
40944297da73f24135b4448d2e36f6cf50499d095448Dake Gu        initActivity(intent);
40954297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mOrientation = BaseGridView.VERTICAL;
40964297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mNumRows = 1;
40974297da73f24135b4448d2e36f6cf50499d095448Dake Gu
40984297da73f24135b4448d2e36f6cf50499d095448Dake Gu        int height = mGridView.getHeight() - mGridView.getPaddingTop()
40994297da73f24135b4448d2e36f6cf50499d095448Dake Gu                - mGridView.getPaddingBottom();
41004297da73f24135b4448d2e36f6cf50499d095448Dake Gu        final int childHeight = height - mGridView.getVerticalSpacing() - 100;
41014297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
41024297da73f24135b4448d2e36f6cf50499d095448Dake Gu            @Override
41034297da73f24135b4448d2e36f6cf50499d095448Dake Gu            public void run() {
41044297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE);
41054297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setWindowAlignmentOffset(100);
41064297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setWindowAlignmentOffsetPercent(BaseGridView
41074297da73f24135b4448d2e36f6cf50499d095448Dake Gu                        .WINDOW_ALIGN_OFFSET_PERCENT_DISABLED);
41084297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setItemAlignmentOffset(0);
41094297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setItemAlignmentOffsetPercent(BaseGridView
41104297da73f24135b4448d2e36f6cf50499d095448Dake Gu                        .ITEM_ALIGN_OFFSET_PERCENT_DISABLED);
41114297da73f24135b4448d2e36f6cf50499d095448Dake Gu            }
41124297da73f24135b4448d2e36f6cf50499d095448Dake Gu        });
41134297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivity.addItems(0, new int[]{childHeight, childHeight});
41144297da73f24135b4448d2e36f6cf50499d095448Dake Gu        waitForItemAnimation();
41154297da73f24135b4448d2e36f6cf50499d095448Dake Gu        setSelectedPosition(0);
41164297da73f24135b4448d2e36f6cf50499d095448Dake Gu
41174297da73f24135b4448d2e36f6cf50499d095448Dake Gu        final RecyclerViewAccessibilityDelegate delegateCompat = mGridView
41184297da73f24135b4448d2e36f6cf50499d095448Dake Gu                .getCompatAccessibilityDelegate();
41194297da73f24135b4448d2e36f6cf50499d095448Dake Gu        final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
41204297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
41214297da73f24135b4448d2e36f6cf50499d095448Dake Gu            @Override
41224297da73f24135b4448d2e36f6cf50499d095448Dake Gu            public void run() {
41234297da73f24135b4448d2e36f6cf50499d095448Dake Gu                delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info);
41244297da73f24135b4448d2e36f6cf50499d095448Dake Gu            }
41254297da73f24135b4448d2e36f6cf50499d095448Dake Gu        });
41264297da73f24135b4448d2e36f6cf50499d095448Dake Gu        assertTrue("test sanity", info.isScrollable());
41274297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
41284297da73f24135b4448d2e36f6cf50499d095448Dake Gu            @Override
41294297da73f24135b4448d2e36f6cf50499d095448Dake Gu            public void run() {
41304297da73f24135b4448d2e36f6cf50499d095448Dake Gu                delegateCompat.performAccessibilityAction(mGridView,
41314297da73f24135b4448d2e36f6cf50499d095448Dake Gu                        AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD, null);
41324297da73f24135b4448d2e36f6cf50499d095448Dake Gu            }
41334297da73f24135b4448d2e36f6cf50499d095448Dake Gu        });
41344297da73f24135b4448d2e36f6cf50499d095448Dake Gu        waitForScrollIdle(mVerifyLayout);
41354297da73f24135b4448d2e36f6cf50499d095448Dake Gu        assertEquals(1, mGridView.getSelectedPosition());
41364297da73f24135b4448d2e36f6cf50499d095448Dake Gu    }
41374297da73f24135b4448d2e36f6cf50499d095448Dake Gu
41384297da73f24135b4448d2e36f6cf50499d095448Dake Gu    @Test
41394297da73f24135b4448d2e36f6cf50499d095448Dake Gu    public void testAccessibilityScrollBackwardHalfVisible() throws Throwable {
41404297da73f24135b4448d2e36f6cf50499d095448Dake Gu        Intent intent = new Intent();
41414297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
41424297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.item_button_at_top);
41434297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS,  new int[]{});
41444297da73f24135b4448d2e36f6cf50499d095448Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
41454297da73f24135b4448d2e36f6cf50499d095448Dake Gu        initActivity(intent);
41464297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mOrientation = BaseGridView.VERTICAL;
41474297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mNumRows = 1;
41484297da73f24135b4448d2e36f6cf50499d095448Dake Gu
41494297da73f24135b4448d2e36f6cf50499d095448Dake Gu        int height = mGridView.getHeight() - mGridView.getPaddingTop()
41504297da73f24135b4448d2e36f6cf50499d095448Dake Gu                - mGridView.getPaddingBottom();
41514297da73f24135b4448d2e36f6cf50499d095448Dake Gu        final int childHeight = height - mGridView.getVerticalSpacing() - 100;
41524297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
41534297da73f24135b4448d2e36f6cf50499d095448Dake Gu            @Override
41544297da73f24135b4448d2e36f6cf50499d095448Dake Gu            public void run() {
41554297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE);
41564297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setWindowAlignmentOffset(100);
41574297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setWindowAlignmentOffsetPercent(BaseGridView
41584297da73f24135b4448d2e36f6cf50499d095448Dake Gu                        .WINDOW_ALIGN_OFFSET_PERCENT_DISABLED);
41594297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setItemAlignmentOffset(0);
41604297da73f24135b4448d2e36f6cf50499d095448Dake Gu                mGridView.setItemAlignmentOffsetPercent(BaseGridView
41614297da73f24135b4448d2e36f6cf50499d095448Dake Gu                        .ITEM_ALIGN_OFFSET_PERCENT_DISABLED);
41624297da73f24135b4448d2e36f6cf50499d095448Dake Gu            }
41634297da73f24135b4448d2e36f6cf50499d095448Dake Gu        });
41644297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivity.addItems(0, new int[]{childHeight, childHeight});
41654297da73f24135b4448d2e36f6cf50499d095448Dake Gu        waitForItemAnimation();
41664297da73f24135b4448d2e36f6cf50499d095448Dake Gu        setSelectedPosition(1);
41674297da73f24135b4448d2e36f6cf50499d095448Dake Gu
41684297da73f24135b4448d2e36f6cf50499d095448Dake Gu        final RecyclerViewAccessibilityDelegate delegateCompat = mGridView
41694297da73f24135b4448d2e36f6cf50499d095448Dake Gu                .getCompatAccessibilityDelegate();
41704297da73f24135b4448d2e36f6cf50499d095448Dake Gu        final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
41714297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
41724297da73f24135b4448d2e36f6cf50499d095448Dake Gu            @Override
41734297da73f24135b4448d2e36f6cf50499d095448Dake Gu            public void run() {
41744297da73f24135b4448d2e36f6cf50499d095448Dake Gu                delegateCompat.onInitializeAccessibilityNodeInfo(mGridView, info);
41754297da73f24135b4448d2e36f6cf50499d095448Dake Gu            }
41764297da73f24135b4448d2e36f6cf50499d095448Dake Gu        });
41774297da73f24135b4448d2e36f6cf50499d095448Dake Gu        assertTrue("test sanity", info.isScrollable());
41784297da73f24135b4448d2e36f6cf50499d095448Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
41794297da73f24135b4448d2e36f6cf50499d095448Dake Gu            @Override
41804297da73f24135b4448d2e36f6cf50499d095448Dake Gu            public void run() {
41814297da73f24135b4448d2e36f6cf50499d095448Dake Gu                delegateCompat.performAccessibilityAction(mGridView,
41824297da73f24135b4448d2e36f6cf50499d095448Dake Gu                        AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD, null);
41834297da73f24135b4448d2e36f6cf50499d095448Dake Gu            }
41844297da73f24135b4448d2e36f6cf50499d095448Dake Gu        });
41854297da73f24135b4448d2e36f6cf50499d095448Dake Gu        waitForScrollIdle(mVerifyLayout);
41864297da73f24135b4448d2e36f6cf50499d095448Dake Gu        assertEquals(0, mGridView.getSelectedPosition());
41874297da73f24135b4448d2e36f6cf50499d095448Dake Gu    }
41884297da73f24135b4448d2e36f6cf50499d095448Dake Gu
41895c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    void slideInAndWaitIdle() throws Throwable {
41905c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle(5000);
41915c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    }
41925c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
41935c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    void slideInAndWaitIdle(long timeout) throws Throwable {
41945c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // animateIn() would reset position
41955c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4196e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
41975c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public void run() {
41985c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.animateIn();
41995c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
42005c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
42015c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(timeout, new PollingCheck.PollingCheckCondition() {
42025c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
42035c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
42045c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return !mGridView.getLayoutManager().isSmoothScrolling()
42055c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                        && mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
42065c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
42075c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
42085c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    }
42095c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
42108e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    @Test
42115c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    public void testAnimateOutBlockScrollTo() throws Throwable {
42128e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        Intent intent = new Intent();
42138e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
42148e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                R.layout.vertical_linear_with_button_onleft);
42158e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        int[] items = new int[100];
42168e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        for (int i = 0; i < items.length; i++) {
42178e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            items[i] = 300;
42188e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        }
42198e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
42208e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
42218e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mOrientation = BaseGridView.VERTICAL;
42228e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mNumRows = 1;
42238e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
42248e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        initActivity(intent);
42258e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
42268e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
42278e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getTop());
42288e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
42298e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4230e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
42318e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
42328e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.animateOut();
42338e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
42348e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
42355c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // wait until sliding out.
42368e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
42378e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
42388e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
42398e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop();
42408e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
42418e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
42425c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // scrollToPosition() should not affect slideOut status
42438e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4244e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
42458e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
42468e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.scrollToPosition(0);
42478e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
42488e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
42498e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
42508e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
42518e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
42528e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
42538e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
42548e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
42555c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertTrue("First view slided Out", mGridView.getChildAt(0).getTop()
42565c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                >= mGridView.getHeight());
42575c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
42585c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle();
42595c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
42605c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.getChildAt(0).getTop());
42615c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    }
42625c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
42635c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    @Test
42645c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    public void testAnimateOutBlockSmoothScrolling() throws Throwable {
42655c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        Intent intent = new Intent();
42665c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
42675c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                R.layout.vertical_linear_with_button_onleft);
42685c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        int[] items = new int[30];
42695c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        for (int i = 0; i < items.length; i++) {
42705c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            items[i] = 300;
42715c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        }
42725c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
42735c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
42745c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mOrientation = BaseGridView.VERTICAL;
42755c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mNumRows = 1;
42765c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
42775c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        initActivity(intent);
42788e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
42798e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
42808e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getTop());
42815c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
42825c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4283e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
42845c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public void run() {
42855c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.animateOut();
42865c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
42875c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
42885c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // wait until sliding out.
42895c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
42905c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
42915c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
42925c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop();
42935c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
42945c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
42955c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // smoothScrollToPosition() should not affect slideOut status
42965c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4297e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
42985c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public void run() {
42995c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.smoothScrollToPosition(29);
43005c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
43015c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
43025c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(10000, new PollingCheck.PollingCheckCondition() {
43035c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
43045c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
43055c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
43065c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
43075c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
43085c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertTrue("First view slided Out", mGridView.getChildAt(0).getTop()
43095c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                >= mGridView.getHeight());
43105c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43115c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle();
43125c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
43135c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertSame("Scrolled to last child",
43145c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.findViewHolderForAdapterPosition(29).itemView, lastChild);
43158e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    }
43168e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
43178e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    @Test
43185c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    public void testAnimateOutBlockLongScrollTo() throws Throwable {
43195c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        Intent intent = new Intent();
43205c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
43215c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                R.layout.vertical_linear_with_button_onleft);
43225c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        int[] items = new int[30];
43235c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        for (int i = 0; i < items.length; i++) {
43245c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            items[i] = 300;
43255c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        }
43265c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
43275c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
43285c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mOrientation = BaseGridView.VERTICAL;
43295c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mNumRows = 1;
43305c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43315c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        initActivity(intent);
43325c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43335c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
43345c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.getChildAt(0).getTop());
43355c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43365c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4337e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
43385c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public void run() {
43395c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.animateOut();
43405c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
43415c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
43425c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // wait until sliding out.
43435c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
43445c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
43455c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
43465c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop();
43475c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
43485c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
43495c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // smoothScrollToPosition() should not affect slideOut status
43505c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4351e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
43525c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public void run() {
43535c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.scrollToPosition(29);
43545c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
43555c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
43565c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(10000, new PollingCheck.PollingCheckCondition() {
43575c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
43585c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
43595c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
43605c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
43615c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
43625c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertTrue("First view slided Out", mGridView.getChildAt(0).getTop()
43635c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                >= mGridView.getHeight());
43645c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43655c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle();
43665c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
43675c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertSame("Scrolled to last child",
43685c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.findViewHolderForAdapterPosition(29).itemView, lastChild);
43695c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    }
43705c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43715c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    @Test
43725c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    public void testAnimateOutBlockLayout() throws Throwable {
43735c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        Intent intent = new Intent();
43745c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
43755c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                R.layout.vertical_linear_with_button_onleft);
43765c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        int[] items = new int[100];
43775c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        for (int i = 0; i < items.length; i++) {
43785c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            items[i] = 300;
43795c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        }
43805c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
43815c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
43825c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mOrientation = BaseGridView.VERTICAL;
43835c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mNumRows = 1;
43845c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43855c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        initActivity(intent);
43865c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43875c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
43885c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.getChildAt(0).getTop());
43895c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
43905c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4391e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
43925c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public void run() {
43935c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.animateOut();
43945c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
43955c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
43965c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // wait until sliding out.
43975c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
43985c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
43995c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
44005c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop();
44015c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
44025c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
44035c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // change adapter should not affect slideOut status
44045c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4405e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
44065c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public void run() {
44075c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mActivity.changeItem(0, 200);
44085c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
44095c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
44105c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
44115c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
44125c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
44135c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
44145c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
44155c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
44165c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertTrue("First view slided Out", mGridView.getChildAt(0).getTop()
44175c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                >= mGridView.getHeight());
44185c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertEquals("onLayout suppressed during slide out", 300,
44195c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.getChildAt(0).getHeight());
44205c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
44215c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle();
44225c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
44235c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                mGridView.getChildAt(0).getTop());
44245c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        // size of item should be updated immediately after slide in animation finishes:
44255c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        PollingCheck.waitFor(1000, new PollingCheck.PollingCheckCondition() {
44265c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            @Override
44275c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            public boolean canProceed() {
44285c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                return 200 == mGridView.getChildAt(0).getHeight();
44295c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu            }
44305c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        });
44315c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    }
44325c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
44335c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    @Test
44345c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    public void testAnimateOutBlockFocusChange() throws Throwable {
44358e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        Intent intent = new Intent();
44368e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
44378e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                R.layout.vertical_linear_with_button_onleft);
44388e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        int[] items = new int[100];
44398e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        for (int i = 0; i < items.length; i++) {
44408e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            items[i] = 300;
44418e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        }
44428e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
44438e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
44448e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mOrientation = BaseGridView.VERTICAL;
44458e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mNumRows = 1;
44468e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
44478e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        initActivity(intent);
44488e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
44498e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
44508e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getTop());
44518e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
44528e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4453e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
44548e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
44558e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.animateOut();
44568e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mActivity.findViewById(R.id.button).requestFocus();
44578e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
44588e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
44598e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertTrue(mActivity.findViewById(R.id.button).hasFocus());
44608e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
44618e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
44628e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
44638e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getChildAt(0).getTop() > mGridView.getPaddingTop();
44648e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
44658e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
44668e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4467e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
44688e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
44698e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.requestFocus();
44708e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
44718e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
44728e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
44738e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
44748e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
44758e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
44768e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
44778e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
44785c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertTrue("First view slided Out", mGridView.getChildAt(0).getTop()
44795c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                >= mGridView.getHeight());
44808e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
44815c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle();
44828e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding top", mGridView.getPaddingTop(),
44838e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getTop());
44848e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    }
44858e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
44868e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    @Test
44875c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu    public void testHorizontalAnimateOutBlockScrollTo() throws Throwable {
44888e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        Intent intent = new Intent();
44898e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
44908e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                R.layout.horizontal_linear);
44918e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        int[] items = new int[100];
44928e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        for (int i = 0; i < items.length; i++) {
44938e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            items[i] = 300;
44948e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        }
44958e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
44968e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
44978e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mOrientation = BaseGridView.HORIZONTAL;
44988e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mNumRows = 1;
44998e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45008e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        initActivity(intent);
45018e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45028e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding left", mGridView.getPaddingLeft(),
45038e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getLeft());
45048e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45058e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4506e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
45078e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
45088e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.animateOut();
45098e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45108e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45118e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
45128e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
45138e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
45148e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getChildAt(0).getLeft() > mGridView.getPaddingLeft();
45158e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45168e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45178e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4518e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
45198e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
45208e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.scrollToPosition(0);
45218e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45228e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45238e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
45248e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
45258e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
45268e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
45278e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45288e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45298e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45305c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertTrue("First view is slided out", mGridView.getChildAt(0).getLeft()
45315c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu                > mGridView.getWidth());
45325c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
45335c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle();
45348e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding left", mGridView.getPaddingLeft(),
45358e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getLeft());
45365c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
45378e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    }
45388e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45398e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    @Test
45408e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    public void testHorizontalAnimateOutRtl() throws Throwable {
45418e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        Intent intent = new Intent();
45428e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
45438e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                R.layout.horizontal_linear_rtl);
45448e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        int[] items = new int[100];
45458e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        for (int i = 0; i < items.length; i++) {
45468e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            items[i] = 300;
45478e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        }
45488e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
45498e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
45508e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mOrientation = BaseGridView.HORIZONTAL;
45518e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mNumRows = 1;
45528e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45538e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        initActivity(intent);
45548e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45558e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding right",
45568e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getWidth() - mGridView.getPaddingRight(),
45578e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getRight());
45588e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45598e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4560e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
45618e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
45628e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.animateOut();
45638e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45648e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45658e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
45668e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
45678e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
45688e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getChildAt(0).getRight()
45698e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                        < mGridView.getWidth() - mGridView.getPaddingRight();
45708e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45718e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45728e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4573e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
45748e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public void run() {
45758e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.smoothScrollToPosition(0);
45768e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45778e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45788e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
45798e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            @Override
45808e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            public boolean canProceed() {
45818e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                return mGridView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE;
45828e06d698aa47dfdea344d2529f2879489eb4610fDake Gu            }
45838e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        });
45848e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
45855c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        assertTrue("First view is slided out", mGridView.getChildAt(0).getRight() < 0);
45865c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu
45875c05fc026b77c6387917560f8dbbbd4bff13bbf9Dake Gu        slideInAndWaitIdle();
45888e06d698aa47dfdea344d2529f2879489eb4610fDake Gu        assertEquals("First view is aligned with padding right",
45898e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getWidth() - mGridView.getPaddingRight(),
45908e06d698aa47dfdea344d2529f2879489eb4610fDake Gu                mGridView.getChildAt(0).getRight());
45918e06d698aa47dfdea344d2529f2879489eb4610fDake Gu    }
45928e06d698aa47dfdea344d2529f2879489eb4610fDake Gu
4593b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu    @Test
4594b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu    public void testSmoothScrollerOutRange() throws Throwable {
4595b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        Intent intent = new Intent();
4596b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
4597b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu                R.layout.vertical_linear_with_button_onleft);
4598b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
4599b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        int[] items = new int[30];
4600b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        for (int i = 0; i < items.length; i++) {
4601b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu            items[i] = 680;
4602b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        }
4603b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
4604b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4605b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        mOrientation = BaseGridView.VERTICAL;
4606b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        mNumRows = 1;
4607b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu
4608b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        initActivity(intent);
4609b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu
4610b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        final View button = mActivity.findViewById(R.id.button);
4611b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4612b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu            public void run() {
4613b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu                button.requestFocus();
4614b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu            }
4615b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        });
4616b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu
4617b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        mGridView.setSelectedPositionSmooth(0);
4618b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        waitForScrollIdle(mVerifyLayout);
4619b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu
4620b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4621b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu            public void run() {
4622b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu                mGridView.setSelectedPositionSmooth(120);
4623b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu            }
4624b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        });
4625b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        waitForScrollIdle(mVerifyLayout);
4626b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        assertTrue(button.hasFocus());
4627b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        int key;
4628b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
4629b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu            key = KeyEvent.KEYCODE_DPAD_LEFT;
4630b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        } else {
4631b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu            key = KeyEvent.KEYCODE_DPAD_RIGHT;
4632b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        }
4633b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        sendKey(key);
4634b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        // the GridView should has focus in its children
4635b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        assertTrue(mGridView.hasFocus());
4636b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        assertFalse(mGridView.isFocused());
4637b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu        assertEquals(29, mGridView.getSelectedPosition());
4638b484ccb63d546196c4b39f9a86a9c714006cfdc3Dake Gu    }
46395c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu
46405c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu    @Test
46415c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu    public void testRemoveLastItemWithStableId() throws Throwable {
46425c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        Intent intent = new Intent();
46435c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
46445c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, true);
46455c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        int[] items = new int[1];
46465c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        for (int i = 0; i < items.length; i++) {
46475c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu            items[i] = 680;
46485c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        }
46495c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
46505c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
46515c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        mOrientation = BaseGridView.VERTICAL;
46525c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        mNumRows = 1;
46535c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu
46545c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        initActivity(intent);
46555c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu
46565c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
46575c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu            @Override
46585c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu            public void run() {
46595c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu                mGridView.getItemAnimator().setRemoveDuration(2000);
46605c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu                mActivity.removeItems(0, 1, false);
46615c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu                mGridView.getAdapter().notifyDataSetChanged();
46625c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu            }
46635c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        });
46645c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        Thread.sleep(500);
46655c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu        assertEquals(-1, mGridView.getSelectedPosition());
46665c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu    }
4667e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4668db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu    @Test
46697124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    public void testUpdateAndSelect1() throws Throwable {
46707124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        Intent intent = new Intent();
46717124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
46727124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, false);
46737124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
46747124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
46757124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mOrientation = BaseGridView.VERTICAL;
46767124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mNumRows = 1;
46777124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
46787124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        initActivity(intent);
46797124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
46807124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
46817124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            @Override
46827124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            public void run() {
46837124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                mGridView.getAdapter().notifyDataSetChanged();
46847124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                mGridView.setSelectedPosition(1);
46857124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            }
46867124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        });
46877124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        waitOneUiCycle();
46887124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        assertEquals(1, mGridView.getSelectedPosition());
46897124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    }
46907124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
46917124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    @Test
46927124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    public void testUpdateAndSelect2() throws Throwable {
46937124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        Intent intent = new Intent();
46947124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
46957124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, false);
46967124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100);
46977124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
46987124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mOrientation = BaseGridView.VERTICAL;
46997124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mNumRows = 1;
47007124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
47017124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        initActivity(intent);
47027124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
47037124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
47047124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            @Override
47057124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            public void run() {
47067124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                mGridView.getAdapter().notifyDataSetChanged();
47077124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                mGridView.setSelectedPosition(50);
47087124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            }
47097124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        });
47107124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        waitOneUiCycle();
47117124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        assertEquals(50, mGridView.getSelectedPosition());
47127124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    }
47137124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
47147124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    @Test
47157124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    public void testUpdateAndSelect3() throws Throwable {
47167124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        Intent intent = new Intent();
47177124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
47187124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_HAS_STABLE_IDS, false);
47197124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
47207124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
47217124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mOrientation = BaseGridView.VERTICAL;
47227124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mNumRows = 1;
47237124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
47247124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        initActivity(intent);
47257124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
47267124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
47277124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            @Override
47287124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            public void run() {
47297124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                int[] newItems = new int[100];
47307124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                for (int i = 0; i < newItems.length; i++) {
47317124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                    newItems[i] = mActivity.mItemLengths[0];
47327124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                }
47337124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                mActivity.addItems(0, newItems, false);
47347124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                mGridView.getAdapter().notifyDataSetChanged();
47357124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu                mGridView.setSelectedPosition(50);
47367124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu            }
47377124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        });
47387124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        waitOneUiCycle();
47397124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu        assertEquals(50, mGridView.getSelectedPosition());
47407124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    }
47417124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu
47427124ccd6be8ffec8b9a26587b90e09f7b6e2d4ceDake Gu    @Test
4743db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu    public void testFocusedPositonAfterRemoved1() throws Throwable {
4744db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        Intent intent = new Intent();
4745db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
4746db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        final int[] items = new int[2];
4747db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        for (int i = 0; i < items.length; i++) {
4748db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            items[i] = 300;
4749db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        }
4750db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
4751db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4752db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        mOrientation = BaseGridView.VERTICAL;
4753db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        mNumRows = 1;
4754db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu
4755db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        initActivity(intent);
4756db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        setSelectedPosition(1);
4757db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        assertEquals(1, mGridView.getSelectedPosition());
4758db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu
4759db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        final int[] newItems = new int[3];
4760db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        for (int i = 0; i < newItems.length; i++) {
4761db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            newItems[i] = 300;
4762db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        }
4763db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        performAndWaitForAnimation(new Runnable() {
4764db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            @Override
4765db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            public void run() {
4766db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu                mActivity.removeItems(0, 2, true);
4767db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu                mActivity.addItems(0, newItems, true);
4768db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            }
4769db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        });
4770db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        assertEquals(0, mGridView.getSelectedPosition());
4771db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu    }
4772db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu
4773db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu    @Test
4774db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu    public void testFocusedPositonAfterRemoved2() throws Throwable {
4775db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        Intent intent = new Intent();
4776db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
4777db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        final int[] items = new int[2];
4778db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        for (int i = 0; i < items.length; i++) {
4779db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            items[i] = 300;
4780db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        }
4781db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
4782db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4783db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        mOrientation = BaseGridView.VERTICAL;
4784db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        mNumRows = 1;
4785db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu
4786db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        initActivity(intent);
4787db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        setSelectedPosition(1);
4788db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        assertEquals(1, mGridView.getSelectedPosition());
4789db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu
4790db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        final int[] newItems = new int[3];
4791db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        for (int i = 0; i < newItems.length; i++) {
4792db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            newItems[i] = 300;
4793db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        }
4794db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        performAndWaitForAnimation(new Runnable() {
4795db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            @Override
4796db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            public void run() {
4797db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu                mActivity.removeItems(1, 1, true);
4798db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu                mActivity.addItems(1, newItems, true);
4799db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu            }
4800db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        });
4801db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu        assertEquals(1, mGridView.getSelectedPosition());
4802db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu    }
4803db7f8aa22ee060d1404897b58d60365fa94d0799Dake Gu
4804e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    static void assertNoCollectionItemInfo(AccessibilityNodeInfoCompat info) {
4805e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        AccessibilityNodeInfoCompat.CollectionItemInfoCompat nodeInfoCompat =
4806e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                info.getCollectionItemInfo();
4807e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        if (nodeInfoCompat == null) {
4808e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            return;
4809e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        }
4810e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        assertTrue(nodeInfoCompat.getRowIndex() < 0);
4811e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        assertTrue(nodeInfoCompat.getColumnIndex() < 0);
4812e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    }
4813e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4814e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    /**
4815e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu     * This test would need talkback on.
4816e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu     */
4817e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    @Test
4818e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    public void testAccessibilityOfItemsBeingPushedOut() throws Throwable {
4819e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        Intent intent = new Intent();
4820e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid);
4821e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100);
4822e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4823e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
4824e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mNumRows = 3;
4825e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4826e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        initActivity(intent);
4827e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4828e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        final int lastPos = mGridView.getChildAdapterPosition(
4829e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getChildAt(mGridView.getChildCount() - 1));
4830e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4831e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            @Override
4832e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            public void run() {
4833e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getLayoutManager().setItemPrefetchEnabled(false);
4834e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
4835e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        });
4836e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        final int numItemsToPushOut = mNumRows;
4837e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4838e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            @Override
4839e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            public void run() {
4840e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                // set longer enough so that accessibility service will initialize node
4841e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                // within setImportantForAccessibility().
4842e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getItemAnimator().setRemoveDuration(2000);
4843e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getItemAnimator().setAddDuration(2000);
4844e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                final int[] newItems = new int[numItemsToPushOut];
4845e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                final int newItemValue = mActivity.mItemLengths[0];
4846e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                for (int i = 0; i < newItems.length; i++) {
4847e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                    newItems[i] = newItemValue;
4848e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                }
4849e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mActivity.addItems(lastPos - numItemsToPushOut + 1, newItems);
4850e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
4851e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        });
48526d65d10a40b33e52a365610cb299771178a56824Dake Gu        waitForItemAnimation();
4853e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    }
4854e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4855e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    /**
4856e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu     * This test simulates talkback by calling setImportanceForAccessibility at end of animation
4857e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu     */
4858e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    @Test
4859e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    public void simulatesAccessibilityOfItemsBeingPushedOut() throws Throwable {
4860e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        Intent intent = new Intent();
4861e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid);
4862e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 100);
4863e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4864e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
4865e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mNumRows = 3;
4866e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4867e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        initActivity(intent);
4868e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4869134b0891c25facf14c53ef939846010284025ca9Dake Gu        final HashSet<View> moveAnimationViews = new HashSet();
4870e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mActivity.mImportantForAccessibilityListener =
4871e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                new GridActivity.ImportantForAccessibilityListener() {
4872e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            RecyclerView.LayoutManager mLM = mGridView.getLayoutManager();
4873e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            @Override
4874e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            public void onImportantForAccessibilityChanged(View view, int newValue) {
4875e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                // simulates talkack, having setImportantForAccessibility to call
4876e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                // onInitializeAccessibilityNodeInfoForItem() for the DISAPPEARING items.
4877134b0891c25facf14c53ef939846010284025ca9Dake Gu                if (moveAnimationViews.contains(view)) {
4878e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                    AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
4879e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                    mLM.onInitializeAccessibilityNodeInfoForItem(
4880e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                            null, null, view, info);
4881e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                }
4882e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
4883e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        };
4884e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        final int lastPos = mGridView.getChildAdapterPosition(
4885e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getChildAt(mGridView.getChildCount() - 1));
4886134b0891c25facf14c53ef939846010284025ca9Dake Gu        final int numItemsToPushOut = mNumRows;
4887134b0891c25facf14c53ef939846010284025ca9Dake Gu        for (int i = 0; i < numItemsToPushOut; i++) {
4888134b0891c25facf14c53ef939846010284025ca9Dake Gu            moveAnimationViews.add(
4889134b0891c25facf14c53ef939846010284025ca9Dake Gu                    mGridView.getChildAt(mGridView.getChildCount() - 1 - i));
4890134b0891c25facf14c53ef939846010284025ca9Dake Gu        }
4891e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4892e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            @Override
4893e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            public void run() {
4894e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.setItemAnimator(new DefaultItemAnimator() {
4895e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                    @Override
4896134b0891c25facf14c53ef939846010284025ca9Dake Gu                    public void onMoveFinished(RecyclerView.ViewHolder item) {
4897134b0891c25facf14c53ef939846010284025ca9Dake Gu                        moveAnimationViews.remove(item.itemView);
4898e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                    }
4899e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                });
4900e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getLayoutManager().setItemPrefetchEnabled(false);
4901e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
4902e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        });
4903e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4904e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            @Override
4905e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            public void run() {
4906e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                final int[] newItems = new int[numItemsToPushOut];
4907e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                final int newItemValue = mActivity.mItemLengths[0] + 1;
4908e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                for (int i = 0; i < newItems.length; i++) {
4909e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                    newItems[i] = newItemValue;
4910e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                }
4911e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mActivity.addItems(lastPos - numItemsToPushOut + 1, newItems);
4912e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
4913e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        });
4914134b0891c25facf14c53ef939846010284025ca9Dake Gu        while (moveAnimationViews.size() != 0) {
4915e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            Thread.sleep(100);
4916e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        }
4917e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    }
4918e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4919e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    @Test
4920e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    public void testAccessibilityNodeInfoOnRemovedFirstItem() throws Throwable {
4921e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        Intent intent = new Intent();
4922e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid);
4923e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 6);
4924e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4925e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
4926e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mNumRows = 3;
4927e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4928e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        initActivity(intent);
4929e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4930e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        final View lastView = mGridView.findViewHolderForAdapterPosition(0).itemView;
4931e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4932e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            @Override
4933e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            public void run() {
4934e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getItemAnimator().setRemoveDuration(20000);
4935e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mActivity.removeItems(0, 1);
4936e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
4937e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        });
4938e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        waitForItemAnimationStart();
4939e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(lastView);
4940e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mGridView.getLayoutManager().onInitializeAccessibilityNodeInfoForItem(null, null,
4941e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                lastView, info);
4942e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        assertNoCollectionItemInfo(info);
4943e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    }
4944e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4945e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    @Test
4946e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    public void testAccessibilityNodeInfoOnRemovedLastItem() throws Throwable {
4947e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        Intent intent = new Intent();
4948e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_grid);
4949e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 6);
4950e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
4951e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
4952e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mNumRows = 3;
4953e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4954e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        initActivity(intent);
4955e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu
4956e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        final View lastView = mGridView.findViewHolderForAdapterPosition(5).itemView;
4957e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
4958e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            @Override
4959e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            public void run() {
4960e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mGridView.getItemAnimator().setRemoveDuration(20000);
4961e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                mActivity.removeItems(5, 1);
4962e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu            }
4963e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        });
4964e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        waitForItemAnimationStart();
4965e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(lastView);
4966e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        mGridView.getLayoutManager().onInitializeAccessibilityNodeInfoForItem(null, null,
4967e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu                lastView, info);
4968e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu        assertNoCollectionItemInfo(info);
4969e36e2ce16cbd6144ccd49e0b90ae4c587a08c8f3Dake Gu    }
4970bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
4971bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    static class FiveViewTypesProvider implements ViewTypeProvider {
4972bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
4973bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        @Override
4974bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        public int getViewType(int position) {
4975bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            switch (position) {
4976bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 0:
4977bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return 0;
4978bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 1:
4979bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return 1;
4980bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 2:
4981bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return 2;
4982bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 3:
4983bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return 3;
4984bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 4:
4985bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return 4;
4986bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            }
4987bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            return 199;
4988bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        }
4989bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    }
4990bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
4991bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    // Used by testItemAlignmentVertical() testItemAlignmentHorizontal()
4992bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    static class ItemAlignmentWithPaddingFacetProvider implements
4993bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            ItemAlignmentFacetProvider {
4994bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        final ItemAlignmentFacet mFacet0;
4995bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        final ItemAlignmentFacet mFacet1;
4996bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        final ItemAlignmentFacet mFacet2;
4997bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        final ItemAlignmentFacet mFacet3;
4998bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        final ItemAlignmentFacet mFacet4;
4999bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5000bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        ItemAlignmentWithPaddingFacetProvider() {
5001bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            ItemAlignmentFacet.ItemAlignmentDef[] defs;
5002bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet0 = new ItemAlignmentFacet();
5003bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs = new ItemAlignmentFacet.ItemAlignmentDef[1];
5004bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
5005bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentViewId(R.id.t1);
5006bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetPercent(0);
5007bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetWithPadding(false);
5008bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet0.setAlignmentDefs(defs);
5009bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet1 = new ItemAlignmentFacet();
5010bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs = new ItemAlignmentFacet.ItemAlignmentDef[1];
5011bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
5012bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentViewId(R.id.t1);
5013bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetPercent(0);
5014bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetWithPadding(true);
5015bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet1.setAlignmentDefs(defs);
5016bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet2 = new ItemAlignmentFacet();
5017bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs = new ItemAlignmentFacet.ItemAlignmentDef[1];
5018bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
5019bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentViewId(R.id.t2);
5020bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetPercent(100);
5021bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetWithPadding(true);
5022bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet2.setAlignmentDefs(defs);
5023bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet3 = new ItemAlignmentFacet();
5024bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs = new ItemAlignmentFacet.ItemAlignmentDef[1];
5025bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
5026bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentViewId(R.id.t2);
5027bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetPercent(50);
5028bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetWithPadding(true);
5029bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet3.setAlignmentDefs(defs);
5030bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet4 = new ItemAlignmentFacet();
5031bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs = new ItemAlignmentFacet.ItemAlignmentDef[1];
5032bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0] = new ItemAlignmentFacet.ItemAlignmentDef();
5033bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentViewId(R.id.t2);
5034bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetPercent(50);
5035bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            defs[0].setItemAlignmentOffsetWithPadding(false);
5036bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            mFacet4.setAlignmentDefs(defs);
5037bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        }
5038bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5039bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        @Override
5040bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        public ItemAlignmentFacet getItemAlignmentFacet(int viewType) {
5041bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            switch (viewType) {
5042bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 0:
5043bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return mFacet0;
5044bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 1:
5045bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return mFacet1;
5046bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 2:
5047bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return mFacet2;
5048bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 3:
5049bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return mFacet3;
5050bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                case 4:
5051bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                    return mFacet4;
5052bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            }
5053bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            return null;
5054bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        }
5055bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    }
5056bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5057bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    @Test
5058bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    public void testItemAlignmentVertical() throws Throwable {
5059bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        Intent intent = new Intent();
5060bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
5061bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout2);
5062bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        int[] items = new int[5];
5063bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        for (int i = 0; i < items.length; i++) {
5064bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            items[i] = 300;
5065bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        }
5066bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
5067bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
5068bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
5069bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                FiveViewTypesProvider.class.getName());
5070bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS,
5071bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                ItemAlignmentWithPaddingFacetProvider.class.getName());
5072bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mOrientation = BaseGridView.VERTICAL;
5073bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mNumRows = 1;
5074bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5075bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        initActivity(intent);
5076bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        startWaitLayout();
5077bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
5078bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            @Override
5079bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            public void run() {
5080bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE);
5081bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignmentOffsetPercent(50);
5082bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignmentOffset(0);
5083bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            }
5084bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        });
5085bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        waitForLayout();
5086bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
508793b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        final float windowAlignCenter = mGridView.getHeight() / 2f;
5088bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        Rect rect = new Rect();
5089bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        View textView;
5090bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5091bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 1: does not include padding
5092bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.t1);
5093bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth(), textView.getHeight());
5094bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
509593b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.top, DELTA);
5096bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5097bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 2: including low padding
5098bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(1);
5099bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.t1);
5100bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingTop() > 0);
5101bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, textView.getPaddingTop(), textView.getWidth(), textView.getHeight());
5102bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
510393b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.top, DELTA);
5104bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5105bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 3: including high padding
5106bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(2);
5107bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(2).itemView.findViewById(R.id.t2);
5108bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingBottom() > 0);
5109bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth(),
5110bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                textView.getHeight() - textView.getPaddingBottom());
5111bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
511293b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.bottom, DELTA);
5113bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5114bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 4: including padding will be ignored if offsetPercent is not 0 or 100
5115bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(3);
5116bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(3).itemView.findViewById(R.id.t2);
5117bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingTop() != textView.getPaddingBottom());
5118bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth(), textView.getHeight() / 2);
5119bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
512093b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.bottom, DELTA);
5121bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5122bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 5: does not include padding
5123bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(4);
5124bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(4).itemView.findViewById(R.id.t2);
5125bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingTop() != textView.getPaddingBottom());
5126bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth(), textView.getHeight() / 2);
5127bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
512893b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.bottom, DELTA);
5129bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    }
5130bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5131bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    @Test
5132bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    public void testItemAlignmentHorizontal() throws Throwable {
5133bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        Intent intent = new Intent();
5134bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear);
5135bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout3);
5136bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        int[] items = new int[5];
5137bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        for (int i = 0; i < items.length; i++) {
5138bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            items[i] = 300;
5139bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        }
5140bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
5141bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
5142bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
5143bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                FiveViewTypesProvider.class.getName());
5144bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS,
5145bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                ItemAlignmentWithPaddingFacetProvider.class.getName());
5146bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mOrientation = BaseGridView.VERTICAL;
5147bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mNumRows = 1;
5148bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5149bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        initActivity(intent);
5150bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        startWaitLayout();
5151bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
5152bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            @Override
5153bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            public void run() {
5154bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE);
5155bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignmentOffsetPercent(50);
5156bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignmentOffset(0);
5157bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            }
5158bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        });
5159bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        waitForLayout();
5160bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
516193b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        final float windowAlignCenter = mGridView.getWidth() / 2f;
5162bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        Rect rect = new Rect();
5163bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        View textView;
5164bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5165bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 1: does not include padding
5166bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.t1);
5167bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth(), textView.getHeight());
5168bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
516993b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.left, DELTA);
5170bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5171bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 2: including low padding
5172bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(1);
5173bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.t1);
5174bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingLeft() > 0);
5175bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(textView.getPaddingLeft(), 0, textView.getWidth(), textView.getHeight());
5176bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
517793b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.left, DELTA);
5178bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5179bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 3: including high padding
5180bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(2);
5181bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(2).itemView.findViewById(R.id.t2);
5182bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingRight() > 0);
5183bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth() - textView.getPaddingRight(),
5184bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                textView.getHeight());
5185bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
518693b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.right, DELTA);
5187bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5188bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 4: including padding will be ignored if offsetPercent is not 0 or 100
5189bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(3);
5190bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(3).itemView.findViewById(R.id.t2);
5191bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingLeft() != textView.getPaddingRight());
5192bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth() / 2, textView.getHeight());
5193bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
519493b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.right, DELTA);
5195bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5196bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 5: does not include padding
5197bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(4);
5198bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(4).itemView.findViewById(R.id.t2);
5199bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingLeft() != textView.getPaddingRight());
5200bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth() / 2, textView.getHeight());
5201bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
520293b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.right, DELTA);
5203bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    }
5204bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5205bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    @Test
5206bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    public void testItemAlignmentHorizontalRtl() throws Throwable {
5207bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        Intent intent = new Intent();
5208bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear);
5209bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_CHILD_LAYOUT_ID, R.layout.relative_layout3);
5210bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        int[] items = new int[5];
5211bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        for (int i = 0; i < items.length; i++) {
5212bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            items[i] = 300;
5213bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        }
5214bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
5215bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
5216bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
5217bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                FiveViewTypesProvider.class.getName());
5218bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMALIGNMENTPROVIDER_CLASS,
5219bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                ItemAlignmentWithPaddingFacetProvider.class.getName());
5220bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mOrientation = BaseGridView.VERTICAL;
5221bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mNumRows = 1;
5222bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5223bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        initActivity(intent);
5224bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        startWaitLayout();
5225bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
5226bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            @Override
5227bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            public void run() {
5228bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
5229bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_NO_EDGE);
5230bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignmentOffsetPercent(50);
5231bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                mGridView.setWindowAlignmentOffset(0);
5232bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu            }
5233bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        });
5234bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        waitForLayout();
5235bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
523693b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        final float windowAlignCenter = mGridView.getWidth() / 2f;
5237bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        Rect rect = new Rect();
5238bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        View textView;
5239bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5240bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 1: does not include padding
5241bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.t1);
5242bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth(), textView.getHeight());
5243bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
524493b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.right, DELTA);
5245bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5246bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 2: including low padding
5247bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(1);
5248bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.t1);
5249bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingRight() > 0);
5250bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth() - textView.getPaddingRight(),
5251bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                textView.getHeight());
5252bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
525393b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.right, DELTA);
5254bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5255bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 3: including high padding
5256bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(2);
5257bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(2).itemView.findViewById(R.id.t2);
5258bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingLeft() > 0);
5259bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(textView.getPaddingLeft(), 0, textView.getWidth(),
5260bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu                textView.getHeight());
5261bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
526293b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.left, DELTA);
5263bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5264bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 4: including padding will be ignored if offsetPercent is not 0 or 100
5265bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(3);
5266bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(3).itemView.findViewById(R.id.t2);
5267bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingLeft() != textView.getPaddingRight());
5268bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth() / 2, textView.getHeight());
5269bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
527093b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.right, DELTA);
5271bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu
5272bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        // test 5: does not include padding
5273bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        setSelectedPosition(4);
5274bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        textView = mGridView.findViewHolderForAdapterPosition(4).itemView.findViewById(R.id.t2);
5275bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        assertTrue(textView.getPaddingLeft() != textView.getPaddingRight());
5276bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        rect.set(0, 0, textView.getWidth() / 2, textView.getHeight());
5277bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu        mGridView.offsetDescendantRectToMyCoords(textView, rect);
527893b954ed786fcd8c25c332cb921b9a51c525dfd4Dake Gu        assertEquals(windowAlignCenter, rect.right, DELTA);
5279bc6713f8e2fa9702675dc3827591ed401b539723Dake Gu    }
52805c4d5ee6697503c9c170fe240b0fe97792d83904Dake Gu
5281b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    enum ItemLocation {
5282b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        ITEM_AT_LOW,
5283b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        ITEM_AT_KEY_LINE,
5284b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        ITEM_AT_HIGH
5285b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    };
5286b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5287b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    static class ItemAt {
5288b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int mScrollPosition;
5289b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final int mPosition;
5290b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        final ItemLocation mLocation;
5291b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5292b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        ItemAt(int scrollPosition, int position, ItemLocation loc) {
5293b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            mScrollPosition = scrollPosition;
5294b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            mPosition = position;
5295b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            mLocation = loc;
5296b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        }
5297b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5298b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        ItemAt(int position, ItemLocation loc) {
5299b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            mScrollPosition = position;
5300b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            mPosition = position;
5301b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            mLocation = loc;
5302b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        }
5303b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5304b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5305b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    /**
5306b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu     * When scroll to position, item at position is expected at given location.
5307b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu     */
5308b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    static ItemAt itemAt(int position, ItemLocation location) {
5309b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        return new ItemAt(position, location);
5310b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5311b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5312b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    /**
5313b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu     * When scroll to scrollPosition, item at position is expected at given location.
5314b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu     */
5315b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    static ItemAt itemAt(int scrollPosition, int position, ItemLocation location) {
5316b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        return new ItemAt(scrollPosition, position, location);
5317b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5318b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5319b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    void prepareKeyLineTest(int numItems) throws Throwable {
5320b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        Intent intent = new Intent();
53214b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.horizontal_linear);
5322b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        int[] items = new int[numItems];
5323b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        for (int i = 0; i < items.length; i++) {
5324b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            items[i] = 32;
5325b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        }
5326b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
5327b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
53284b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        mOrientation = BaseGridView.HORIZONTAL;
5329b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mNumRows = 1;
5330b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5331b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        initActivity(intent);
5332b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5333b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5334b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testPreferKeyLine(final int windowAlignment,
5335b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverLow,
5336b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverHigh,
5337b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemLocation assertFirstItemLocation,
5338b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemLocation assertLastItemLocation) throws Throwable {
5339b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(windowAlignment, preferKeyLineOverLow, preferKeyLineOverHigh,
5340b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, assertFirstItemLocation),
5341b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(mActivity.mNumItems - 1, assertLastItemLocation));
5342b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5343b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5344b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testPreferKeyLine(final int windowAlignment,
5345b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverLow,
5346b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverHigh,
5347b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemLocation assertFirstItemLocation,
5348b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemAt assertLastItemLocation) throws Throwable {
5349b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(windowAlignment, preferKeyLineOverLow, preferKeyLineOverHigh,
5350b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, assertFirstItemLocation),
5351b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                assertLastItemLocation);
5352b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5353b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5354b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testPreferKeyLine(final int windowAlignment,
5355b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverLow,
5356b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverHigh,
5357b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemAt assertFirstItemLocation,
5358b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemLocation assertLastItemLocation) throws Throwable {
5359b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(windowAlignment, preferKeyLineOverLow, preferKeyLineOverHigh,
5360b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                assertFirstItemLocation,
5361b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(mActivity.mNumItems - 1, assertLastItemLocation));
5362b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5363b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5364b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testPreferKeyLine(final int windowAlignment,
5365b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverLow,
5366b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            final boolean preferKeyLineOverHigh,
5367b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemAt assertFirstItemLocation,
5368b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            ItemAt assertLastItemLocation) throws Throwable {
53694b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        TestPreferKeyLineOptions options = new TestPreferKeyLineOptions();
53704b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        options.mAssertItemLocations = new ItemAt[] {assertFirstItemLocation,
53714b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                assertLastItemLocation};
53724b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        options.mPreferKeyLineOverLow = preferKeyLineOverLow;
53734b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        options.mPreferKeyLineOverHigh = preferKeyLineOverHigh;
53744b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        options.mWindowAlignment = windowAlignment;
53754b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu
53764b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        options.mRtl = false;
53774b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        testPreferKeyLine(options);
53784b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu
53794b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        options.mRtl = true;
53804b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        testPreferKeyLine(options);
53814b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu    }
53824b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu
53834b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu    static class TestPreferKeyLineOptions {
53844b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        int mWindowAlignment;
53854b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        boolean mPreferKeyLineOverLow;
53864b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        boolean mPreferKeyLineOverHigh;
53874b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        ItemAt[] mAssertItemLocations;
53884b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        boolean mRtl;
53894b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu    }
53904b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu
53914b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu    public void testPreferKeyLine(final TestPreferKeyLineOptions options) throws Throwable {
5392b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        startWaitLayout();
5393b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        mActivityTestRule.runOnUiThread(new Runnable() {
5394b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            @Override
5395b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            public void run() {
53964b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                if (options.mRtl) {
53974b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    mGridView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
53984b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                } else {
53994b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    mGridView.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
54004b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                }
54014b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                mGridView.setWindowAlignment(options.mWindowAlignment);
5402b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                mGridView.setWindowAlignmentOffsetPercent(50);
5403b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                mGridView.setWindowAlignmentOffset(0);
54044b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                mGridView.setWindowAlignmentPreferKeyLineOverLowEdge(options.mPreferKeyLineOverLow);
54054b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                mGridView.setWindowAlignmentPreferKeyLineOverHighEdge(
54064b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                        options.mPreferKeyLineOverHigh);
5407b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu            }
5408b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        });
5409b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        waitForLayout();
5410b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
54114b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        final int paddingStart = mGridView.getPaddingStart();
54124b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        final int paddingEnd = mGridView.getPaddingEnd();
54134b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        final int windowAlignCenter = mGridView.getWidth() / 2;
54144b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu
54154b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu        for (int i = 0; i < options.mAssertItemLocations.length; i++) {
54164b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu            ItemAt assertItemLocation = options.mAssertItemLocations[i];
54174b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu            setSelectedPosition(assertItemLocation.mScrollPosition);
54184b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu            View view = mGridView.findViewHolderForAdapterPosition(assertItemLocation.mPosition)
54194b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    .itemView;
54204b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu            switch (assertItemLocation.mLocation) {
54214b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                case ITEM_AT_LOW:
54224b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    if (options.mRtl) {
54234b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                        assertEquals(mGridView.getWidth() - paddingStart, view.getRight());
54244b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    } else {
54254b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                        assertEquals(paddingStart, view.getLeft());
54264b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    }
54274b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    break;
54284b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                case ITEM_AT_HIGH:
54294b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    if (options.mRtl) {
54304b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                        assertEquals(paddingEnd, view.getLeft());
54314b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    } else {
54324b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                        assertEquals(mGridView.getWidth() - paddingEnd, view.getRight());
54334b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    }
54344b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    break;
54354b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                case ITEM_AT_KEY_LINE:
54364b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    assertEquals(windowAlignCenter, (view.getLeft() + view.getRight()) / 2, DELTA);
54374b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu                    break;
54384b79f71ae9a20ed0882170a15fdcbe0f3efba9d9Dake Gu            }
5439b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        }
5440b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5441b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5442b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    @Test
5443b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testPreferKeyLine1() throws Throwable {
5444b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        prepareKeyLineTest(1);
5445b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, false,
5446b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5447b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, true,
5448b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5449b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, false,
5450b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5451b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, true,
5452b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5453b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5454b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, false,
5455b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW);
5456b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, true,
5457b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW);
5458b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, false,
5459b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5460b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, true,
5461b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5462b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5463b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, false,
5464b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_HIGH, ItemLocation.ITEM_AT_HIGH);
5465b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, true,
5466b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5467b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, false,
5468b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_HIGH, ItemLocation.ITEM_AT_HIGH);
5469b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, true,
5470b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5471b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5472b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, false,
5473b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW);
5474b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, true,
5475b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_LOW);
5476b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, false,
5477b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5478b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, true,
5479b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5480b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5481b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5482b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    @Test
5483b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testPreferKeyLine2() throws Throwable {
5484b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        prepareKeyLineTest(2);
5485b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, false,
5486b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5487b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, true,
5488b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5489b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, false,
5490b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5491b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, true,
5492b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5493b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5494b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, false,
5495b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW));
5496b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, true,
5497b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW));
5498b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, false,
5499b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE),
5500b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE));
5501b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, true,
5502b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE),
5503b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE));
5504b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5505b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, false,
5506b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 1, ItemLocation.ITEM_AT_HIGH),
5507b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 1, ItemLocation.ITEM_AT_HIGH));
5508b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, true,
5509b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 0, ItemLocation.ITEM_AT_KEY_LINE),
5510b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 0, ItemLocation.ITEM_AT_KEY_LINE));
5511b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, false,
5512b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 1, ItemLocation.ITEM_AT_HIGH),
5513b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 1, ItemLocation.ITEM_AT_HIGH));
5514b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, true,
5515b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 0, ItemLocation.ITEM_AT_KEY_LINE),
5516b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 0, ItemLocation.ITEM_AT_KEY_LINE));
5517b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5518b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, false,
5519b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW));
5520b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, true,
5521b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, itemAt(1, 0, ItemLocation.ITEM_AT_LOW));
5522b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, false,
5523b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE),
5524b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE));
5525b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, true,
5526b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(0, 1, ItemLocation.ITEM_AT_KEY_LINE),
5527b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                itemAt(1, 1, ItemLocation.ITEM_AT_KEY_LINE));
5528b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5529b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5530b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    @Test
5531b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    public void testPreferKeyLine10000() throws Throwable {
5532b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        prepareKeyLineTest(10000);
5533b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, false,
5534b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5535b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, false, true,
5536b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5537b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, false,
5538b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5539b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_NO_EDGE, true, true,
5540b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_KEY_LINE);
5541b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5542b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, false,
5543b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE);
5544b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, false, true,
5545b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE);
5546b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, false,
5547b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE);
5548b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_LOW_EDGE, true, true,
5549b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_KEY_LINE);
5550b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5551b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, false,
5552b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH);
5553b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, false, true,
5554b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH);
5555b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, false,
5556b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH);
5557b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE, true, true,
5558b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_KEY_LINE, ItemLocation.ITEM_AT_HIGH);
5559b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu
5560b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, false,
5561b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH);
5562b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, false, true,
5563b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH);
5564b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, false,
5565b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH);
5566b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu        testPreferKeyLine(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE, true, true,
5567b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu                ItemLocation.ITEM_AT_LOW, ItemLocation.ITEM_AT_HIGH);
5568b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu    }
5569b6dde2cfe2fbe3151c52d92e3754288aab11a3b1Dake Gu}
5570