From 992ac23449b67e7daca0b6afb63b2d33a322977c Mon Sep 17 00:00:00 2001 From: Chris Banes Date: Fri, 9 Dec 2016 03:46:02 +0000 Subject: [PATCH] Merge "Fix CollapsingToolbarLayout scrim not being drawn" into nyc-support-25.1-dev GitOrigin-RevId=9e34c75622e53a85a686a8d457e9b648633e67da PiperOrigin-RevId: 141514714 --- .../widget/CollapsingToolbarLayout.java | 27 +++++----- .../CollapsingToolbarLayoutActions.java | 52 +++++++++++++++++++ .../design/widget/AppBarLayoutBaseTest.java | 38 ++++++++++++-- .../AppBarWithCollapsingToolbarTest.java | 11 ++++ 4 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 lib/tests/src/android/support/design/testutils/CollapsingToolbarLayoutActions.java diff --git a/lib/src/android/support/design/widget/CollapsingToolbarLayout.java b/lib/src/android/support/design/widget/CollapsingToolbarLayout.java index 8fcf79658..5f8de3627 100644 --- a/lib/src/android/support/design/widget/CollapsingToolbarLayout.java +++ b/lib/src/android/support/design/widget/CollapsingToolbarLayout.java @@ -110,7 +110,6 @@ public class CollapsingToolbarLayout extends FrameLayout { private Toolbar mToolbar; private View mToolbarDirectChild; private View mDummyView; - private int mToolbarDrawIndex; private int mExpandedMarginStart; private int mExpandedMarginTop; @@ -314,16 +313,14 @@ public class CollapsingToolbarLayout extends FrameLayout { protected boolean drawChild(Canvas canvas, View child, long drawingTime) { // This is a little weird. Our scrim needs to be behind the Toolbar (if it is present), // but in front of any other children which are behind it. To do this we intercept the - // drawChild() call, and draw our scrim after the preceding view is drawn - boolean invalidate = super.drawChild(canvas, child, drawingTime); - - if (mContentScrim != null && mScrimAlpha > 0 && isToolbarChildDrawnNext(child)) { + // drawChild() call, and draw our scrim just before the Toolbar is drawn + boolean invalidated = false; + if (mContentScrim != null && mScrimAlpha > 0 && isToolbarChild(child)) { mContentScrim.mutate().setAlpha(mScrimAlpha); mContentScrim.draw(canvas); - invalidate = true; + invalidated = true; } - - return invalidate; + return super.drawChild(canvas, child, drawingTime) || invalidated; } @Override @@ -369,8 +366,10 @@ public class CollapsingToolbarLayout extends FrameLayout { mRefreshToolbar = false; } - private boolean isToolbarChildDrawnNext(View child) { - return mToolbarDrawIndex >= 0 && mToolbarDrawIndex == indexOfChild(child) + 1; + private boolean isToolbarChild(View child) { + return (mToolbarDirectChild == null || mToolbarDirectChild == this) + ? child == mToolbar + : child == mToolbarDirectChild; } /** @@ -480,13 +479,9 @@ public class CollapsingToolbarLayout extends FrameLayout { } if (mToolbarDirectChild == null || mToolbarDirectChild == this) { setMinimumHeight(getHeightWithMargins(mToolbar)); - mToolbarDrawIndex = indexOfChild(mToolbar); } else { setMinimumHeight(getHeightWithMargins(mToolbarDirectChild)); - mToolbarDrawIndex = indexOfChild(mToolbarDirectChild); } - } else { - mToolbarDrawIndex = -1; } updateScrimVisibility(); @@ -631,6 +626,10 @@ public class CollapsingToolbarLayout extends FrameLayout { } } + int getScrimAlpha() { + return mScrimAlpha; + } + /** * Set the drawable to use for the content scrim from resources. Providing null will disable * the scrim functionality. diff --git a/lib/tests/src/android/support/design/testutils/CollapsingToolbarLayoutActions.java b/lib/tests/src/android/support/design/testutils/CollapsingToolbarLayoutActions.java new file mode 100644 index 000000000..71dd15069 --- /dev/null +++ b/lib/tests/src/android/support/design/testutils/CollapsingToolbarLayoutActions.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.support.design.testutils; + +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; + +import android.support.annotation.ColorInt; +import android.support.design.widget.CollapsingToolbarLayout; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.view.View; + +import org.hamcrest.Matcher; + +public class CollapsingToolbarLayoutActions { + + public static ViewAction setContentScrimColor(@ColorInt final int color) { + return new ViewAction() { + @Override + public Matcher getConstraints() { + return isDisplayed(); + } + + @Override + public String getDescription() { + return "Set the content scrim to a color"; + } + + @Override + public void perform(UiController uiController, View view) { + uiController.loopMainThreadUntilIdle(); + CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) view; + ctl.setContentScrimColor(color); + uiController.loopMainThreadUntilIdle(); + } + }; + } +} diff --git a/lib/tests/src/android/support/design/widget/AppBarLayoutBaseTest.java b/lib/tests/src/android/support/design/widget/AppBarLayoutBaseTest.java index 39486e5ea..fc131a45a 100644 --- a/lib/tests/src/android/support/design/widget/AppBarLayoutBaseTest.java +++ b/lib/tests/src/android/support/design/widget/AppBarLayoutBaseTest.java @@ -16,16 +16,21 @@ package android.support.design.widget; +import static android.support.design.testutils.CollapsingToolbarLayoutActions.setContentScrimColor; import static android.support.design.testutils.TestUtilsActions.setText; import static android.support.design.testutils.TestUtilsActions.setTitle; import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static org.junit.Assert.assertEquals; +import android.graphics.Color; import android.os.Build; +import android.os.SystemClock; import android.support.annotation.CallSuper; import android.support.annotation.IdRes; +import android.support.annotation.IntRange; import android.support.annotation.LayoutRes; import android.support.annotation.StringRes; import android.support.design.test.R; @@ -41,6 +46,10 @@ import android.text.TextUtils; import android.view.View; import android.widget.TextView; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + public abstract class AppBarLayoutBaseTest extends BaseDynamicCoordinatorLayoutTest { protected AppBarLayout mAppBar; @@ -110,13 +119,15 @@ public abstract class AppBarLayoutBaseTest extends BaseDynamicCoordinatorLayoutT final CharSequence activityTitle = activity.getString(titleResId); activity.setTitle(activityTitle); if (mCollapsingToolbar != null) { - onView(withId(R.id.collapsing_app_bar)).perform(setTitle(activityTitle)); + onView(withId(R.id.collapsing_app_bar)) + .perform(setTitle(activityTitle)) + .perform(setContentScrimColor(Color.MAGENTA)); } TextView dialog = (TextView) mCoordinatorLayout.findViewById(R.id.textview_dialogue); if (dialog != null) { - onView(withId(R.id.textview_dialogue)).perform( - setText(TextUtils.concat(Shakespeare.DIALOGUE))); + onView(withId(R.id.textview_dialogue)) + .perform(setText(TextUtils.concat(Shakespeare.DIALOGUE))); } mDefaultElevationValue = mAppBar.getResources() @@ -128,4 +139,25 @@ public abstract class AppBarLayoutBaseTest extends BaseDynamicCoordinatorLayoutT assertEquals(expectedValue, ViewCompat.getElevation(mAppBar), 0.05f); } } + + protected void assertScrimAlpha(@IntRange(from = 0, to = 255) int alpha) { + SystemClock.sleep(300); + onView(withId(R.id.collapsing_app_bar)) + .check(matches(withScrimAlpha(alpha))); + } + + static Matcher withScrimAlpha(final int alpha) { + return new TypeSafeMatcher() { + @Override + public void describeTo(Description description) { + description.appendText( + "CollapsingToolbarLayout has content scrim with alpha: " + alpha); + } + + @Override + protected boolean matchesSafely(CollapsingToolbarLayout view) { + return alpha == view.getScrimAlpha(); + } + }; + } } diff --git a/lib/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java b/lib/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java index 84e1abedf..adcfee8b3 100644 --- a/lib/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java +++ b/lib/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java @@ -55,6 +55,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { final int shortSwipeAmount = toolbarHeight; assertAppBarElevation(0f); + assertScrimAlpha(0); // Perform a swipe-up gesture across the horizontal center of the screen. performVerticalSwipeUpGesture( @@ -82,6 +83,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { assertEquals(originalAppbarTop + toolbarHeight + mAppBar.getTopInset(), appbarOnScreenXY[1] + appbarHeight, 1); assertAppBarElevation(mDefaultElevationValue); + assertScrimAlpha(255); // Perform a short swipe-down gesture across the horizontal center of the screen. // Note that the swipe down is a bit longer than the swipe up to check that the app bar @@ -99,6 +101,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { assertEquals(originalAppbarTop + toolbarHeight + mAppBar.getTopInset(), appbarOnScreenXY[1] + appbarHeight, 1); assertAppBarElevation(mDefaultElevationValue); + assertScrimAlpha(255); // Perform another swipe-down gesture across the horizontal center of the screen. performVerticalSwipeDownGesture( @@ -113,6 +116,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1); assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1); assertAppBarElevation(0f); + assertScrimAlpha(0); // Perform yet another swipe-down gesture across the horizontal center of the screen. performVerticalSwipeDownGesture( @@ -127,6 +131,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1); assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1); assertAppBarElevation(0f); + assertScrimAlpha(0); } @Test @@ -157,6 +162,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { final int shortSwipeAmount = toolbarHeight; assertAppBarElevation(0f); + assertScrimAlpha(0); // Perform a swipe-up gesture across the horizontal center of the screen, starting from // just below the AppBarLayout @@ -173,6 +179,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { // Allow for off-by-a-pixel margin of error. assertEquals(originalAppbarTop, appbarOnScreenXY[1] + appbarHeight - topInset, 1); assertAppBarElevation(0f); + assertScrimAlpha(255); // Perform another swipe-up gesture performVerticalSwipeUpGesture( @@ -186,6 +193,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { // margin of error. assertEquals(originalAppbarTop, appbarOnScreenXY[1] + appbarHeight - topInset, 1); assertAppBarElevation(0f); + assertScrimAlpha(255); // Perform a short swipe-down gesture across the horizontal center of the screen. // Note that the swipe down is a bit longer than the swipe up to fully bring down @@ -203,6 +211,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { assertEquals(originalAppbarTop + toolbarHeight + topInset, appbarOnScreenXY[1] + appbarHeight, 1); assertAppBarElevation(mDefaultElevationValue); + assertScrimAlpha(255); // Perform another swipe-down gesture across the horizontal center of the screen. performVerticalSwipeDownGesture( @@ -217,6 +226,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { assertEquals(originalAppbarTop, appbarOnScreenXY[1]); assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight); assertAppBarElevation(0f); + assertScrimAlpha(0); // Perform yet another swipe-down gesture across the horizontal center of the screen. performVerticalSwipeDownGesture( @@ -231,6 +241,7 @@ public class AppBarWithCollapsingToolbarTest extends AppBarLayoutBaseTest { assertEquals(originalAppbarTop, appbarOnScreenXY[1], 1); assertEquals(originalAppbarBottom, appbarOnScreenXY[1] + appbarHeight, 1); assertAppBarElevation(0f); + assertScrimAlpha(0); } @Test