Skip to content

Commit

Permalink
[AppBarLayout] Fix dynamic status bar foreground lift on scroll color…
Browse files Browse the repository at this point in the history
… when using Tonal Surface Color

Resolves #3530

PiperOrigin-RevId: 564364138
  • Loading branch information
dsn5ft authored and leticiarossi committed Sep 12, 2023
1 parent 4e1b130 commit 569ddac
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
Expand Up @@ -31,7 +31,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.shape.MaterialShapeDrawable;
import com.google.android.material.color.MaterialColors;
import com.google.android.material.tabs.TabLayout;
import io.material.catalog.feature.DemoFragment;
import io.material.catalog.feature.DemoUtils;
Expand Down Expand Up @@ -59,8 +59,8 @@ public View onCreateDemoView(
activity.setSupportActionBar(toolbar);

AppBarLayout appBarLayout = view.findViewById(R.id.appbarlayout);
appBarLayout.setStatusBarForeground(
MaterialShapeDrawable.createWithElevationOverlay(requireContext()));
appBarLayout.setStatusBarForegroundColor(
MaterialColors.getColor(appBarLayout, R.attr.colorSurface));

TabLayout tabs = view.findViewById(R.id.tabs);
ToggleButton showHideTabsButton = view.findViewById(R.id.show_hide_tabs_button);
Expand Down
Expand Up @@ -29,7 +29,7 @@
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.shape.MaterialShapeDrawable;
import com.google.android.material.color.MaterialColors;
import io.material.catalog.feature.DemoFragment;
import io.material.catalog.feature.DemoUtils;

Expand All @@ -52,8 +52,8 @@ public View onCreateDemoView(
activity.setSupportActionBar(toolbar);

AppBarLayout appBarLayout = view.findViewById(R.id.appbarlayout);
appBarLayout.setStatusBarForeground(
MaterialShapeDrawable.createWithElevationOverlay(requireContext()));
appBarLayout.setStatusBarForegroundColor(
MaterialColors.getColor(appBarLayout, R.attr.colorSurface));

return view;
}
Expand Down
9 changes: 9 additions & 0 deletions docs/components/TopAppBar.md
Expand Up @@ -327,6 +327,15 @@ appBarLayout.setStatusBarForeground(
MaterialShapeDrawable.createWithElevationOverlay(getContext()));
```

Or if using Tonal Surface Colors instead of Elevation Overlays, you can simply
set the `statusBarForeground` to `colorSurface` to let `AppBarLayout`
automatically match the status bar color to its own background:

```
appBarLayout.setStatusBarForegroundColor(
MaterialColors.getColor(appBarLayout, R.attr.colorSurface));
```

### Center aligned top app bar example

All of the same guidance and code from the sections above is relevant for Center
Expand Down
38 changes: 32 additions & 6 deletions lib/java/com/google/android/material/appbar/AppBarLayout.java
Expand Up @@ -75,6 +75,7 @@
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;
import com.google.android.material.internal.ThemeEnforcement;
import com.google.android.material.motion.MotionUtils;
Expand Down Expand Up @@ -220,6 +221,7 @@ public interface LiftOnScrollListener {
private int[] tmpStatesArray;

@Nullable private Drawable statusBarForeground;
@Nullable private Integer statusBarForegroundOriginalColor;

private final float appBarElevation;

Expand Down Expand Up @@ -332,19 +334,29 @@ private void initializeLiftOnScrollWithColor(MaterialShapeDrawable background) {
liftBackground.setAlpha(lifted ? 255 : 0);
background.setAlpha(lifted ? 0 : 255);

ColorStateList colorSurface =
MaterialColors.getColorStateListOrNull(getContext(), R.attr.colorSurface);

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

int mixedColor =
ArgbEvaluatorCompat.getInstance()
.evaluate(
liftAlpha / 255f,
background.getResolvedTintColor(),
liftBackground.getResolvedTintColor());
if (statusBarForeground != null
&& statusBarForegroundOriginalColor != null
&& colorSurface != null
&& statusBarForegroundOriginalColor == colorSurface.getDefaultColor()) {
DrawableCompat.setTint(statusBarForeground, mixedColor);
}

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);
Expand Down Expand Up @@ -447,6 +459,7 @@ public void setStatusBarForeground(@Nullable Drawable drawable) {
statusBarForeground.setCallback(null);
}
statusBarForeground = drawable != null ? drawable.mutate() : null;
statusBarForegroundOriginalColor = extractStatusBarForegroundColor();
if (statusBarForeground != null) {
if (statusBarForeground.isStateful()) {
statusBarForeground.setState(getDrawableState());
Expand Down Expand Up @@ -497,6 +510,19 @@ public Drawable getStatusBarForeground() {
return statusBarForeground;
}

@Nullable
private Integer extractStatusBarForegroundColor() {
if (statusBarForeground instanceof MaterialShapeDrawable) {
return ((MaterialShapeDrawable) statusBarForeground).getResolvedTintColor();
}
ColorStateList statusBarForegroundColorStateList =
DrawableUtils.getColorStateListOrNull(statusBarForeground);
if (statusBarForegroundColorStateList != null) {
return statusBarForegroundColorStateList.getDefaultColor();
}
return null;
}

@Override
public void draw(@NonNull Canvas canvas) {
super.draw(canvas);
Expand Down

0 comments on commit 569ddac

Please sign in to comment.