Skip to content

Commit

Permalink
[AppBarLayout] Simplified logics to animate the container color betwe…
Browse files Browse the repository at this point in the history
…en lifted state and the default state.

PiperOrigin-RevId: 566754407
  • Loading branch information
pekingme authored and dsn5ft committed Sep 20, 2023
1 parent 8d83a31 commit 1e9f5f0
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 61 deletions.
71 changes: 23 additions & 48 deletions lib/java/com/google/android/material/appbar/AppBarLayout.java
Expand Up @@ -35,7 +35,6 @@
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
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 @@ -73,7 +72,6 @@
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.color.MaterialColors;
import com.google.android.material.drawable.DrawableUtils;
Expand Down Expand Up @@ -210,7 +208,7 @@ public interface LiftOnScrollListener {
private boolean liftOnScroll;
@IdRes private int liftOnScrollTargetViewId;
@Nullable private WeakReference<View> liftOnScrollTargetView;
@Nullable private final ColorStateList liftOnScrollColor;
private final boolean hasLiftOnScrollColor;
@Nullable private ValueAnimator liftOnScrollColorAnimator;
@Nullable private AnimatorUpdateListener liftOnScrollColorUpdateListener;
private final List<LiftOnScrollListener> liftOnScrollListeners = new ArrayList<>();
Expand Down Expand Up @@ -259,19 +257,19 @@ public AppBarLayout(@NonNull Context context, @Nullable AttributeSet attrs, int

ViewCompat.setBackground(this, a.getDrawable(R.styleable.AppBarLayout_android_background));

liftOnScrollColor =
MaterialResources.getColorStateList(
context, a, R.styleable.AppBarLayout_liftOnScrollColor);
ColorStateList liftOnScrollColor =
MaterialResources.getColorStateList(context, a, R.styleable.AppBarLayout_liftOnScrollColor);
hasLiftOnScrollColor = liftOnScrollColor != null;

ColorStateList backgroundColorStateList =
DrawableUtils.getColorStateListOrNull(getBackground());
if (backgroundColorStateList != null) {
ColorStateList originalBackgroundColor = DrawableUtils.getColorStateListOrNull(getBackground());
if (originalBackgroundColor != null) {
MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
materialShapeDrawable.setFillColor(backgroundColorStateList);
materialShapeDrawable.setFillColor(originalBackgroundColor);
// If there is a lift on scroll color specified, we do not initialize the elevation overlay
// and set the alpha to zero manually.
if (liftOnScrollColor != null) {
initializeLiftOnScrollWithColor(materialShapeDrawable);
initializeLiftOnScrollWithColor(
materialShapeDrawable, originalBackgroundColor, liftOnScrollColor);
} else {
initializeLiftOnScrollWithElevation(context, materialShapeDrawable);
}
Expand Down Expand Up @@ -328,26 +326,20 @@ public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets)
});
}

private void initializeLiftOnScrollWithColor(MaterialShapeDrawable background) {
MaterialShapeDrawable liftBackground = new MaterialShapeDrawable();
liftBackground.setFillColor(liftOnScrollColor);
liftBackground.setAlpha(lifted ? 255 : 0);
background.setAlpha(lifted ? 0 : 255);

private void initializeLiftOnScrollWithColor(
MaterialShapeDrawable background,
@NonNull ColorStateList originalBackgroundColor,
@NonNull ColorStateList liftOnScrollColor) {
Integer colorSurface = MaterialColors.getColorOrNull(getContext(), R.attr.colorSurface);

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

float liftProgress = (float) valueAnimator.getAnimatedValue();
int mixedColor =
ArgbEvaluatorCompat.getInstance()
.evaluate(
liftAlpha / 255f,
background.getResolvedTintColor(),
liftBackground.getResolvedTintColor());
MaterialColors.layer(
originalBackgroundColor.getDefaultColor(),
liftOnScrollColor.getDefaultColor(),
liftProgress);
background.setFillColor(ColorStateList.valueOf(mixedColor));
if (statusBarForeground != null
&& statusBarForegroundOriginalColor != null
&& statusBarForegroundOriginalColor.equals(colorSurface)) {
Expand All @@ -362,9 +354,7 @@ private void initializeLiftOnScrollWithColor(MaterialShapeDrawable background) {
}
}
};

LayerDrawable layerBackground = new LayerDrawable(new Drawable[] {background, liftBackground});
ViewCompat.setBackground(this, layerBackground);
ViewCompat.setBackground(this, background);
}

private void initializeLiftOnScrollWithElevation(
Expand Down Expand Up @@ -693,9 +683,6 @@ public CoordinatorLayout.Behavior<AppBarLayout> getBehavior() {
@Nullable
public MaterialShapeDrawable getMaterialShapeBackground() {
Drawable background = getBackground();
if (background instanceof LayerDrawable) {
background = ((LayerDrawable) background).getDrawable(0);
}
return background instanceof MaterialShapeDrawable ? (MaterialShapeDrawable) background : null;
}

Expand Down Expand Up @@ -1043,10 +1030,10 @@ boolean setLiftedState(boolean lifted, boolean force) {
this.lifted = lifted;
refreshDrawableState();
if (isLiftOnScrollCompatibleBackground()) {
if (liftOnScrollColor != null) {
if (hasLiftOnScrollColor) {
// Only start the liftOnScrollColor based animation because the elevation based
// animation will happen via the lifted drawable state change and state list animator.
startLiftOnScrollColorAnimation(lifted ? 0 : 255, lifted ? 255 : 0);
startLiftOnScrollColorAnimation(lifted ? 0 : 1, lifted ? 1 : 0);
} else if (liftOnScroll) {
startLiftOnScrollColorAnimation(
lifted ? 0 : appBarElevation, lifted ? appBarElevation : 0);
Expand All @@ -1058,19 +1045,7 @@ boolean setLiftedState(boolean lifted, boolean force) {
}

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

private void startLiftOnScrollColorAnimation(
Expand Down
Expand Up @@ -22,7 +22,6 @@
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 @@ -395,19 +394,11 @@ public void testLiftOnScrollColor() throws Throwable {
final int appbarHeight = mAppBar.getHeight();
final int longSwipeAmount = 3 * appbarHeight / 2;

LayerDrawable background = (LayerDrawable) mAppBar.getBackground();
MaterialShapeDrawable backgroundLayer = (MaterialShapeDrawable) background.getDrawable(0);
MaterialShapeDrawable liftLayer = (MaterialShapeDrawable) background.getDrawable(1);
MaterialShapeDrawable backgroundDrawable = mAppBar.getMaterialShapeBackground();

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());
backgroundDrawable.getResolvedTintColor());

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

assertEquals(0, backgroundLayer.getAlpha());
assertEquals(255, liftLayer.getAlpha());
assertEquals(
mAppBar.getResources().getColor(R.color.material_blue_grey_950),
backgroundDrawable.getResolvedTintColor());
}
}

0 comments on commit 1e9f5f0

Please sign in to comment.