Skip to content

Commit

Permalink
[TopAppBar] Updated the handling of liftOnScrollColor not override an…
Browse files Browse the repository at this point in the history
…droid:background.

PiperOrigin-RevId: 547883467
  • Loading branch information
pekingme authored and paulfthomas committed Jul 17, 2023
1 parent 1d3b8e1 commit 2b476b3
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 19 deletions.
60 changes: 46 additions & 14 deletions lib/java/com/google/android/material/appbar/AppBarLayout.java
Expand Up @@ -36,6 +36,7 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.ColorStateListDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
Expand Down Expand Up @@ -74,6 +75,7 @@
import androidx.core.view.accessibility.AccessibilityViewCommand;
import androidx.customview.view.AbsSavedState;
import com.google.android.material.animation.AnimationUtils;
import com.google.android.material.animation.ArgbEvaluatorCompat;
import com.google.android.material.appbar.AppBarLayout.BaseBehavior.SavedState;
import com.google.android.material.internal.ThemeEnforcement;
import com.google.android.material.motion.MotionUtils;
Expand Down Expand Up @@ -271,7 +273,6 @@ public AppBarLayout(@NonNull Context context, @Nullable AttributeSet attrs, int
} else {
initializeLiftOnScrollWithElevation(context, materialShapeDrawable);
}
ViewCompat.setBackground(this, materialShapeDrawable);
}

liftOnScrollColorDuration = MotionUtils.resolveThemeDuration(context,
Expand Down Expand Up @@ -337,19 +338,34 @@ private ColorStateList getBackgroundCSL() {
}

private void initializeLiftOnScrollWithColor(MaterialShapeDrawable background) {
background.setAlpha(lifted ? 255 : 0);
background.setFillColor(liftOnScrollColor);
liftOnScrollColorUpdateListener = valueAnimator -> {
float alpha = (float) valueAnimator.getAnimatedValue();
background.setAlpha((int) alpha);
MaterialShapeDrawable liftBackground = new MaterialShapeDrawable();
liftBackground.setFillColor(liftOnScrollColor);
liftBackground.setAlpha(lifted ? 255 : 0);
background.setAlpha(lifted ? 0 : 255);

liftOnScrollColorUpdateListener =
valueAnimator -> {
float liftAlpha = (float) valueAnimator.getAnimatedValue();
background.setAlpha((int) (255f - liftAlpha));
liftBackground.setAlpha((int) liftAlpha);

if (!liftOnScrollListeners.isEmpty()) {
int mixedColor =
ArgbEvaluatorCompat.getInstance()
.evaluate(
liftAlpha / 255f,
background.getResolvedTintColor(),
liftBackground.getResolvedTintColor());
for (LiftOnScrollListener liftOnScrollListener : liftOnScrollListeners) {
if (background.getFillColor() != null) {
liftOnScrollListener.onUpdate(0, mixedColor);
}
}
}
};

for (LiftOnScrollListener liftOnScrollListener : liftOnScrollListeners) {
if (background.getFillColor() != null) {
liftOnScrollListener.onUpdate(
0, background.getFillColor().withAlpha((int) alpha).getDefaultColor());
}
}
};
LayerDrawable layerBackground = new LayerDrawable(new Drawable[] {background, liftBackground});
ViewCompat.setBackground(this, layerBackground);
}

private void initializeLiftOnScrollWithElevation(
Expand All @@ -365,6 +381,7 @@ private void initializeLiftOnScrollWithElevation(
liftOnScrollListener.onUpdate(elevation, background.getResolvedTintColor());
}
};
ViewCompat.setBackground(this, background);
}

/**
Expand Down Expand Up @@ -1003,7 +1020,7 @@ boolean setLiftedState(boolean lifted, boolean force) {
if (force && this.lifted != lifted) {
this.lifted = lifted;
refreshDrawableState();
if (liftOnScroll && getBackground() instanceof MaterialShapeDrawable) {
if (liftOnScroll && isLiftOnScrollCompatibleBackground()) {
if (liftOnScrollColor != null) {
startLiftOnScrollColorAnimation(
lifted ? 0 : 255, lifted ? 255 : 0);
Expand All @@ -1017,6 +1034,21 @@ boolean setLiftedState(boolean lifted, boolean force) {
return false;
}

private boolean isLiftOnScrollCompatibleBackground() {
if (getBackground() instanceof MaterialShapeDrawable) {
return true;
}
if (getBackground() instanceof LayerDrawable) {
LayerDrawable layerBackground = (LayerDrawable) getBackground();
if (layerBackground.getNumberOfLayers() == 2
&& layerBackground.getDrawable(0) instanceof MaterialShapeDrawable
&& layerBackground.getDrawable(1) instanceof MaterialShapeDrawable) {
return true;
}
}
return false;
}

private void startLiftOnScrollColorAnimation(
float fromValue, float toValue) {
if (liftOnScrollColorAnimator != null) {
Expand Down
Expand Up @@ -26,6 +26,7 @@
android:id="@+id/app_bar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="@color/material_blue_grey_900"
app:liftOnScroll="true"
app:liftOnScrollColor="@color/material_blue_grey_950">

Expand Down
Expand Up @@ -22,6 +22,7 @@
import static org.junit.Assert.assertEquals;

import android.graphics.Rect;
import android.graphics.drawable.LayerDrawable;
import android.view.View;
import android.view.ViewGroup;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
Expand Down Expand Up @@ -394,7 +395,19 @@ public void testLiftOnScrollColor() throws Throwable {
final int appbarHeight = mAppBar.getHeight();
final int longSwipeAmount = 3 * appbarHeight / 2;

assertEquals(0, ((MaterialShapeDrawable) mAppBar.getBackground()).getAlpha());
LayerDrawable background = (LayerDrawable) mAppBar.getBackground();
MaterialShapeDrawable backgroundLayer = (MaterialShapeDrawable) background.getDrawable(0);
MaterialShapeDrawable liftLayer = (MaterialShapeDrawable) background.getDrawable(1);

assertEquals(
mAppBar.getResources().getColor(R.color.material_blue_grey_900),
backgroundLayer.getResolvedTintColor());
assertEquals(
mAppBar.getResources().getColor(R.color.material_blue_grey_950),
liftLayer.getResolvedTintColor());

assertEquals(255, backgroundLayer.getAlpha());
assertEquals(0, liftLayer.getAlpha());

// Perform a swipe-up gesture across the horizontal center of the screen.
performVerticalSwipeUpGesture(
Expand All @@ -403,9 +416,7 @@ public void testLiftOnScrollColor() throws Throwable {
originalAppbarBottom + 3 * longSwipeAmount / 2,
longSwipeAmount);

assertEquals(255, ((MaterialShapeDrawable) mAppBar.getBackground()).getAlpha());
assertEquals(
mAppBar.getResources().getColor(R.color.material_blue_grey_950),
((MaterialShapeDrawable) mAppBar.getBackground()).getFillColor().getDefaultColor());
assertEquals(0, backgroundLayer.getAlpha());
assertEquals(255, liftLayer.getAlpha());
}
}

0 comments on commit 2b476b3

Please sign in to comment.