Material Design 3 Top app bar does not have a shadow. How to enable it?

3.5k views Asked by At

The new 'Material Design 3 top app bar' docs says they got rid of the drop shadow. How can I enable it? Setting elevation on Toolbar or AppBar does not work at all. enter image description here

4

There are 4 answers

0
Yurii Konovalov On BEST ANSWER

I had the same situation. I found that:

  1. The shadow drop applies starting from API 28, below API 28 - the shadow effect is the same as with a MaterialComponents theme.
  2. A color fill works below API 28 (tested on API 26).

Docs for Top app bar specs says that the container of the TopAppBar has a role "Surface" and Elevation (on scroll) Level 2.

On the page Color system - Color roles I found information that:

At elevation +2 components with surface color containers receive a primary color overlay with 8% opacity.

So the default style for a TopAppBarLayout uses ?attr/colorSurface as a background color and ?attr/colorPrimary with 8% opacity as an overlay (kind of a scrim effect).

My solution:

  • Case 1 - Only enable a shadow effect.

Create a style for AppBarLayout and set android:outlineAmbientShadowColor and android:outlineSpotShadowColor to black (as it's a default color for creating shadow). These attributes are set as transparent in Widget.Material3.AppBarLayout.

<style name="Widget.App.AppBarLayout" parent="Widget.Material3.AppBarLayout">
      <item name="android:outlineAmbientShadowColor" ns1:ignore="NewApi">@android:color/black</item>
      <item name="android:outlineSpotShadowColor" ns1:ignore="NewApi">@android:color/black</item>
</style>
  • Case 2 - Enable a shadow effect and get rid of the overlay.

In addition to the above you can add either an android:background attribute with you color or a materialThemeOverlay attribute with setting colorSurface to your color (a background) and colorPrimary to @android:transparent (an overlay). I prefer to add directly android:background because adding materialThemeOverlay can have impact on the child views of your AppBarLayout which.

   <style name="Widget.App.AppBarLayout" parent="Widget.Material3.AppBarLayout">
        <item name="android:outlineAmbientShadowColor" ns1:ignore="NewApi">@android:color/black</item>
        <item name="android:outlineSpotShadowColor" ns1:ignore="NewApi">@android:color/black</item>
        <item name="android:background">@color/white</item>
    </style>

or

<style name="Widget.App.AppBarLayout" parent="Widget.Material3.AppBarLayout">
        <item name="android:outlineAmbientShadowColor" ns1:ignore="NewApi">@android:color/black</item>
        <item name="android:outlineSpotShadowColor" ns1:ignore="NewApi">@android:color/black</item>
        <item name="materialThemeOverlay">@style/ThemeOverlay.App.DayNight.NoActionBar</item>
    </style>

    <style name="ThemeOverlay.App.DayNight.NoActionBar" parent="Theme.Material3.DayNight.NoActionBar">
        <item name="colorPrimary">@android:color/transparent</item>
        <item name="colorSurface">@android:color/white</item>
    </style>

Don't forget apply your style to your AppBarLayout or theme.

By the way, a liftOnScroll attribute is set to true in Widget.Material3.AppBarLayout so there's no need for setting it. Everything works with setting only layout_behavior for a scrolling view.

0
Alvin Konda On

It seems the answers above only tackle Android but i'm not seeing the shadow on iOS, but i suppose the following should work also for Android

return Scaffold(
  key: _scaffoldMessengerKey,
  appBar: AppBar(
    elevation: 6,
    shadowColor: Colors.black.withOpacity(.5),
    ...
  )
  ...
)

or globally to apply on all pages

return MaterialApp(
  title: 'Flutter App',
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.red,
      background: Colors.grey.shade50,
    ),
    useMaterial3: true,
    appBarTheme: AppBarTheme.of(context).copyWith(
      elevation: 6,
      shadowColor: Colors.black.withOpacity(.5),
    ),
  ),
  ...
);
1
sdytik On

You can use, special attribute for your theme from material docs

<style name="AppTheme" parent="Theme.Material3.Light.NoActionBar">
    <item name="elevationOverlayEnabled">false</item>
</style>
0
Berk Inan On

Update code with surfaceTinColor and shadowColor.

AppBar(
   backgroundColour: blue, //whatever you want
   surfaceTinColor: blue, // backgraound of appbar when you scroll
   elevetion: 4, // default level of material 2
   shadowColor: Colors.black.withOpacity(0.6), //looks good to me
)