1123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov/*
2123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * Copyright (C) 2016 The Android Open Source Project
3123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov *
4123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * Licensed under the Apache License, Version 2.0 (the "License");
5123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * you may not use this file except in compliance with the License.
6123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * You may obtain a copy of the License at
7123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov *
8123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov *      http://www.apache.org/licenses/LICENSE-2.0
9123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov *
10123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * Unless required by applicable law or agreed to in writing, software
11123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * distributed under the License is distributed on an "AS IS" BASIS,
12123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * See the License for the specific language governing permissions and
14123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov * limitations under the License.
15123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov */
16123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
17123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovpackage android.support.design.widget;
18123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
19bb3740d273d4b5108ab63f6d264466250a197e5bChris Banesimport android.os.SystemClock;
20123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport android.support.annotation.LayoutRes;
21123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport android.support.annotation.StringRes;
22123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport android.support.design.test.R;
23123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport android.support.design.testutils.Cheeses;
24c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikovimport android.test.suitebuilder.annotation.LargeTest;
25123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport android.test.suitebuilder.annotation.MediumTest;
26123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport org.junit.Test;
27123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
28123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport static android.support.design.testutils.TestUtilsActions.addTabs;
29123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport static android.support.test.espresso.Espresso.onView;
30123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport static android.support.test.espresso.matcher.ViewMatchers.withId;
31123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovimport static org.junit.Assert.assertEquals;
32123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
33123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov@MediumTest
34123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikovpublic class AppBarWithToolbarAndTabsTest extends AppBarLayoutBaseTest {
35123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    private TabLayout mTabLayout;
36123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
37123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    @Override
38123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    protected void configureContent(@LayoutRes int layoutResId, @StringRes int titleResId) {
39123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        super.configureContent(layoutResId, titleResId);
40123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
41123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mTabLayout = (TabLayout) mAppBar.findViewById(R.id.tabs);
42c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        String[] tabTitles = new String[5];
43c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        System.arraycopy(Cheeses.sCheeseStrings, 0, tabTitles, 0, 5);
44c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        onView(withId(R.id.tabs)).perform(addTabs(tabTitles));
45123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    }
46123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
47123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    @Test
48123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    public void testScrollingToolbarAndScrollingTabs() {
49123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        configureContent(R.layout.design_appbar_toolbar_scroll_tabs_scroll,
50123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.string.design_appbar_toolbar_scroll_tabs_scroll);
51123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
52123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int[] appbarOnScreenXY = new int[2];
53123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int[] coordinatorLayoutOnScreenXY = new int[2];
54123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
55123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mCoordinatorLayout.getLocationOnScreen(coordinatorLayoutOnScreenXY);
56123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
57123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int originalAppbarTop = appbarOnScreenXY[1];
58123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int originalAppbarBottom = appbarOnScreenXY[1] + mAppBar.getHeight();
59123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int centerX = appbarOnScreenXY[0] + mAppBar.getWidth() / 2;
60123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
61123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int toolbarHeight = mToolbar.getHeight();
62123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int tabsHeight = mTabLayout.getHeight();
63123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int appbarHeight = mAppBar.getHeight();
64123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int longSwipeAmount = 3 * appbarHeight / 2;
65123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int shortSwipeAmount = toolbarHeight;
66123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
67b539fd57119c80c2b24d3b3f599e131f9aeb17ddChris Banes        // Perform a swipe-up gesture across the horizontal center of the screen, starting from
68b539fd57119c80c2b24d3b3f599e131f9aeb17ddChris Banes        // just below the AppBarLayout
69c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
70123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
71123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
72b539fd57119c80c2b24d3b3f599e131f9aeb17ddChris Banes                originalAppbarBottom + 20,
73123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                longSwipeAmount);
74123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
75123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
76123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should not be visually "present" on the screen, with its bottom
77123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // edge aligned with the system status bar. Allow for off-by-a-pixel margin of error.
78123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1] + appbarHeight, 1);
791a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
80123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
81123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform another swipe-up gesture
82c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
83123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
84123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
85123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom,
86123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                shortSwipeAmount);
87123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
88123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
89123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should still be off the screen. Allow for off-by-a-pixel
90123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // margin of error.
91123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1] + appbarHeight, 1);
921a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
93123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
94123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform a long swipe-down gesture across the horizontal center of the screen.
95123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Note that the swipe down is a bit longer than the swipe up to fully bring down
96123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // the scrolled-away toolbar and tab layout
97123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        performVerticalSwipeDownGesture(
98123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
99123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
100123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom,
101123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                longSwipeAmount * 3 / 2);
102123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
103123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
104123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should be visually snapped below the system status bar as it
105123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // in scrolling mode and we've swiped down. Allow for off-by-a-pixel
106123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // margin of error.
107123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
108123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
1091a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
110123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
111123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform another swipe-down gesture across the horizontal center of the screen.
112123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        performVerticalSwipeDownGesture(
113123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
114123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
115123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom,
116123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                longSwipeAmount);
117123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
118123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
119123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should be in its original position.
120123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Allow for off-by-a-pixel margin of error.
121123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
122123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
1231a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
124123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
125123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform yet another swipe-down gesture across the horizontal center of the screen.
126123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        performVerticalSwipeDownGesture(
127123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
128123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
129123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom,
130123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                longSwipeAmount);
131123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
132123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
133123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should still be in its original position.
134123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Allow for off-by-a-pixel margin of error.
135123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
136123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
1371a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
138123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    }
139123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
140123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    @Test
141c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov    public void testScrollingToolbarAndPinnedTabs() {
142123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        configureContent(R.layout.design_appbar_toolbar_scroll_tabs_pinned,
143123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.string.design_appbar_toolbar_scroll_tabs_pin);
144123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
145123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int[] appbarOnScreenXY = new int[2];
146123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int[] coordinatorLayoutOnScreenXY = new int[2];
147123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
148123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mCoordinatorLayout.getLocationOnScreen(coordinatorLayoutOnScreenXY);
149123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
150123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int originalAppbarTop = appbarOnScreenXY[1];
151123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int originalAppbarBottom = appbarOnScreenXY[1] + mAppBar.getHeight();
152123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int centerX = appbarOnScreenXY[0] + mAppBar.getWidth() / 2;
153123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
154123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int toolbarHeight = mToolbar.getHeight();
155123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int tabsHeight = mTabLayout.getHeight();
156123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int appbarHeight = mAppBar.getHeight();
157123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int longSwipeAmount = 3 * appbarHeight / 2;
158123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        final int shortSwipeAmount = toolbarHeight;
159123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
160b539fd57119c80c2b24d3b3f599e131f9aeb17ddChris Banes        // Perform a swipe-up gesture across the horizontal center of the screen, starting from
161b539fd57119c80c2b24d3b3f599e131f9aeb17ddChris Banes        // just below the AppBarLayout
162c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
163123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
164123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
165b539fd57119c80c2b24d3b3f599e131f9aeb17ddChris Banes                originalAppbarBottom + 20,
166123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                longSwipeAmount);
167123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
168123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
169123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the tab bar should be visually snapped below the system status bar.
170123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Allow for off-by-a-pixel margin of error.
171123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop + tabsHeight, appbarOnScreenXY[1] + appbarHeight, 1);
1721a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
173123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
174123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform another swipe-up gesture
175c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
176123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
177123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
178123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom,
179123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                shortSwipeAmount);
180123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
181123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
182123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the tab bar should still be visually snapped below the system status bar
183123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // as it is in the pinned mode. Allow for off-by-a-pixel margin of error.
184123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop + tabsHeight, appbarOnScreenXY[1] + appbarHeight, 1);
1851a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
186123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
187123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform a short swipe-down gesture across the horizontal center of the screen.
188123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Note that the swipe down is a bit longer than the swipe up to fully bring down
189123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // the scrolled-away toolbar and tab layout
190123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        performVerticalSwipeDownGesture(
191123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
192123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
193123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom - shortSwipeAmount,
194123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                3 * shortSwipeAmount / 2);
195123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
196123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
197123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should be in its original position as it
198123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // in scrolling mode and we've swiped down. Allow for off-by-a-pixel
199123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // margin of error.
200123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
201123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
2021a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
203123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
204123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform another swipe-down gesture across the horizontal center of the screen.
205123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        performVerticalSwipeDownGesture(
206123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
207123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
208123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom,
209123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                longSwipeAmount);
210123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
211123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
212123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should be in its original position.
213123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Allow for off-by-a-pixel margin of error.
214123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
215123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
2161a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
217123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
218123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Perform yet another swipe-down gesture across the horizontal center of the screen.
219123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        performVerticalSwipeDownGesture(
220123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                R.id.coordinator_layout,
221123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                centerX,
222123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                originalAppbarBottom,
223123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov                longSwipeAmount);
224123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
225123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
226123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // At this point the app bar should still be in its original position.
227123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        // Allow for off-by-a-pixel margin of error.
228123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
229123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
2301a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
231123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov    }
232123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov
233c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov    @LargeTest
234c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov    @Test
235c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov    public void testSnappingToolbarAndSnappingTabs() {
236c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        configureContent(R.layout.design_appbar_toolbar_scroll_tabs_scroll_snap,
237c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.string.design_appbar_toolbar_scroll_tabs_scroll_snap);
238c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
239c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int[] appbarOnScreenXY = new int[2];
240c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int[] coordinatorLayoutOnScreenXY = new int[2];
241c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
242c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mCoordinatorLayout.getLocationOnScreen(coordinatorLayoutOnScreenXY);
243c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
244c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int originalAppbarTop = appbarOnScreenXY[1];
245c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int originalAppbarBottom = appbarOnScreenXY[1] + mAppBar.getHeight();
246c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int centerX = appbarOnScreenXY[0] + mAppBar.getWidth() / 2;
247c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
248c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int toolbarHeight = mToolbar.getHeight();
249c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int tabsHeight = mTabLayout.getHeight();
250c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        final int appbarHeight = mAppBar.getHeight();
251c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
252c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Since AppBarLayout doesn't expose a way to track snap animations, the three possible
253c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // options are
254c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // a) track how vertical offsets and invalidation is propagated through the
255c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // view hierarchy and wait until there are no more events of that kind
256c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // b) run a dummy Espresso action that waits until the main thread is idle
257c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // c) sleep for a hardcoded period of time to "wait" until the snap animation is done
258c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // In this test method we go with option b)
259c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
260c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a swipe-up gesture across the horizontal center of the screen. The amount
261c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // of swipe is 25% of the toolbar height and we expect the snap behavior to "move"
262c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // the app bar back to its original position.
263c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
264c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
265c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
266c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
267c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                toolbarHeight / 4);
268c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
269c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
270bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
271c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
272c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
273c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should be in its original position as it
274c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // in snapping mode and we haven't swiped "enough". Allow for off-by-a-pixel
275c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // margin of error.
276c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
277c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
2781a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
279c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
280c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a slightly longer swipe-up gesture, this time by 75% of the toolbar height.
281c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // We expect the snap behavior to move the app bar to snap the tab layout below the
282c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // system status bar.
283c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
284c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
285c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
286c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
287c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                3 * toolbarHeight / 4);
288c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
289c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
290bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
291c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
292c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
293c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should "snap" the toolbar away and align the tab layout below
294c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // the system status bar. Allow for off-by-a-pixel margin of error.
295c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop + tabsHeight, appbarOnScreenXY[1] + appbarHeight, 1);
2961a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
297c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
298c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a short swipe-up gesture, this time by 25% of the tab layout height. We expect
299c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // snap behavior to move the app bar back to snap the tab layout below the system status
300c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // bar.
301c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
302c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
303c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
304c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
305c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                tabsHeight / 4);
306c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
307c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
308bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
309c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
310c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
311c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should "snap" back to align the tab layout below
312c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // the system status bar. Allow for off-by-a-pixel margin of error.
313c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop + tabsHeight, appbarOnScreenXY[1] + appbarHeight, 1);
3141a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
315c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
316c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a longer swipe-up gesture, this time by 75% of the tab layout height. We expect
317c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // snap behavior to move the app bar fully away from the screen.
318c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeUpGesture(
319c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
320c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
321c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
322c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                3 * tabsHeight / 4);
323c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
324c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
325bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
326c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
327c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
328c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should not be visually "present" on the screen, with its bottom
329c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // edge aligned with the system status bar. Allow for off-by-a-pixel margin of error.
330c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1] + appbarHeight, 1);
3311a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
332c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
333c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a short swipe-down gesture by 25% of the tab layout height. We expect
334c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // snap behavior to move the app bar back fully away from the screen.
335c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeDownGesture(
336c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
337c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
338c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
339c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                tabsHeight / 4);
340c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
341c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
342bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
343c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
344c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
345c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should still not be visually "present" on the screen, with
346c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // its bottom edge aligned with the system status bar. Allow for off-by-a-pixel margin
347c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // of error.
348c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1] + appbarHeight, 1);
3491a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
350c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
351c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a longer swipe-up gesture, this time by 75% of the tab layout height. We expect
352c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // snap behavior to move the app bar to snap the tab layout below the system status
353c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // bar.
354c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeDownGesture(
355c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
356c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
357c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
358c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                3 * tabsHeight / 4);
359c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
360c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
361bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
362c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
363c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
364c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should "snap" the toolbar away and align the tab layout below
365c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // the system status bar. Allow for off-by-a-pixel margin of error.
366c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop + tabsHeight, appbarOnScreenXY[1] + appbarHeight, 1);
3671a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
368c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
369c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a short swipe-down gesture by 25% of the toolbar height. We expect
370c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // snap behavior to align the tab layout below the system status bar
371c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeDownGesture(
372c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
373c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
374c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
375c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                toolbarHeight / 4);
376c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
377c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
378bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
379c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
380c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
381c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should still align the tab layout below
382c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // the system status bar. Allow for off-by-a-pixel margin of error.
383c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop + tabsHeight, appbarOnScreenXY[1] + appbarHeight, 1);
3841a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
385c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
386c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Perform a longer swipe-up gesture, this time by 75% of the toolbar height. We expect
387c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // snap behavior to move the app bar back to its original place (fully visible).
388c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        performVerticalSwipeDownGesture(
389c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                R.id.coordinator_layout,
390c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                centerX,
391c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                originalAppbarBottom + toolbarHeight,
392c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov                3 * tabsHeight / 4);
393c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
394c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Wait for the snap animation to be done
395bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        waitForSnapAnimationToFinish();
396c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov
397c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        mAppBar.getLocationOnScreen(appbarOnScreenXY);
398c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // At this point the app bar should be in its original position.
399c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        // Allow for off-by-a-pixel margin of error.
400c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1);
401c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov        assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1);
4021a8e4886abbc35e479cddb7b4acd601cede2fd8aChris Banes        assertAppBarElevation(mDefaultElevationValue);
403c530cc115fddab8e1d9645b322424dd45f9ecd0dKirill Grouchnikov    }
404bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes
405bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes    private void waitForSnapAnimationToFinish() {
406bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior)
407bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes                ((CoordinatorLayout.LayoutParams) mAppBar.getLayoutParams()).getBehavior();
408bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        while (behavior.isOffsetAnimatorRunning()) {
409bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes            SystemClock.sleep(16);
410bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes        }
411bb3740d273d4b5108ab63f6d264466250a197e5bChris Banes    }
412123544eaa855a7734be92dd35901233a222f64a8Kirill Grouchnikov}
413