Skip to content

Conversation

@TahaTesser
Copy link
Member

@TahaTesser TahaTesser commented Jan 11, 2023

fixes #110951

Description

  1. Pass the foregroundColor from SliverAppBar.large and SliverAppBar.medium to flexible space for the title and resolve foregroundColor with the app bar theme's foregroundColor.

SliverAppBar.large and SliverAppBar.medium don't use the title parameter as a result widget's foregroundColor needs to be passed to flexible space for the title.

  1. Use the new appBarTheme variable in centerTitle and fix a missing comma.
code sample (from the issue)
// MIT License
//
// Copyright (c) 2022 Mike Rydstrom
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import 'package:flutter/material.dart';

// Used as M3 seed color
const Color seedColor = Color(0xFF386A20);

// Make a seed generated M3 light mode ColorScheme.
final ColorScheme lightScheme = ColorScheme.fromSeed(
  brightness: Brightness.light,
  seedColor: seedColor,
);

// Make a seed generated M3 dark mode ColorScheme.
final ColorScheme darkScheme = ColorScheme.fromSeed(
  brightness: Brightness.dark,
  seedColor: seedColor,
);

// AppBar colors set via widget properties
const Color appBarBackground = Color(0xFFE9EEB5);
const Color appBarForeground = Color(0xFF1489C0);

// Make AppBarTheme with custom foreground and background colors.
AppBarTheme appBarTheme({required ColorScheme colorScheme}) => AppBarTheme(
      backgroundColor: colorScheme.tertiaryContainer,
      foregroundColor: colorScheme.error,
    );

// A simple custom theme
ThemeData appTheme(Brightness mode, bool useMaterial3) => ThemeData.from(
      colorScheme: mode == Brightness.light ? lightScheme : darkScheme,
      useMaterial3: useMaterial3,
    ).copyWith(
      appBarTheme: appBarTheme(
        colorScheme: mode == Brightness.light ? lightScheme : darkScheme,
      ),
    );

void main() {
  runApp(const IssueDemoApp());
}

class IssueDemoApp extends StatefulWidget {
  const IssueDemoApp({super.key});

  @override
  State<IssueDemoApp> createState() => _IssueDemoAppState();
}

class _IssueDemoAppState extends State<IssueDemoApp> {
  bool useMaterial3 = true;
  ThemeMode themeMode = ThemeMode.light;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      themeMode: themeMode,
      theme: appTheme(Brightness.light, useMaterial3),
      darkTheme: appTheme(Brightness.dark, useMaterial3),
      home: Scaffold(
        appBar: AppBar(
          title: const Text(('AppBar Issue Demo')),
          actions: [
            IconButton(
              icon: useMaterial3
                  ? const Icon(Icons.filter_3)
                  : const Icon(Icons.filter_2),
              onPressed: () {
                setState(() {
                  useMaterial3 = !useMaterial3;
                });
              },
              tooltip: 'Switch to Material ${useMaterial3 ? 2 : 3}',
            ),
            IconButton(
              icon: themeMode == ThemeMode.dark
                  ? const Icon(Icons.wb_sunny_outlined)
                  : const Icon(Icons.wb_sunny),
              onPressed: () {
                setState(() {
                  if (themeMode == ThemeMode.light) {
                    themeMode = ThemeMode.dark;
                  } else {
                    themeMode = ThemeMode.light;
                  }
                });
              },
              tooltip: "Toggle brightness",
            ),
          ],
        ),
        body: const HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      children: [
        const SizedBox(height: 8),
        Text(
          'AppBar Issue',
          style: Theme.of(context).textTheme.headlineSmall,
        ),
        Text(
          'Foreground color on SliverAppBar.medium and SliverAppBar.large are '
          'not respected via AppBarTheme or AppBar properties.',
          style: Theme.of(context).textTheme.bodyLarge,
        ),
        const Divider(),
        const ShowAppBarColors(),
        const SizedBox(height: 8),
        const AppBarShowcase(),
        const Divider(),
        const ShowAppBarColors(
          foregroundColor: appBarForeground,
          backgroundColor: appBarBackground,
        ),
        const SizedBox(height: 8),
        const AppBarShowcase(
          foregroundColor: appBarForeground,
          backgroundColor: appBarBackground,
        ),
      ],
    );
  }
}

class AppBarShowcase extends StatelessWidget {
  const AppBarShowcase({super.key, this.foregroundColor, this.backgroundColor});
  final Color? foregroundColor;
  final Color? backgroundColor;

  @override
  Widget build(BuildContext context) {
    return MediaQuery.removePadding(
      context: context,
      removeBottom: true,
      removeTop: true,
      child: Column(
        children: <Widget>[
          AppBar(
            foregroundColor: foregroundColor,
            backgroundColor: backgroundColor,
            leading: IconButton(
              icon: const Icon(Icons.menu),
              onPressed: () {},
            ),
            title: const Text('Normal AppBar'),
            actions: <Widget>[
              IconButton(
                icon: const Icon(Icons.search),
                onPressed: () {},
              ),
            ],
          ),
          const SizedBox(height: 8),
          CustomScrollView(
            // Normally avoid shrinkWrap, but for showing a few demo
            // widgets here, we can get away with it.
            shrinkWrap: true,
            slivers: <Widget>[
              SliverAppBar(
                foregroundColor: foregroundColor,
                backgroundColor: backgroundColor,
                leading: IconButton(
                  icon: const Icon(Icons.menu),
                  onPressed: () {},
                ),
                title: const Text('Sliver AppBar'),
                actions: <Widget>[
                  IconButton(
                    icon: const Icon(Icons.search),
                    onPressed: () {},
                  ),
                ],
              ),
              const SliverToBoxAdapter(child: SizedBox(height: 8)),
              SliverAppBar.medium(
                foregroundColor: foregroundColor,
                backgroundColor: backgroundColor,
                leading: IconButton(
                  icon: const Icon(Icons.menu),
                  onPressed: () {},
                ),
                title: const Text('SliverAppBar.medium'),
                actions: <Widget>[
                  IconButton(
                    icon: const Icon(Icons.search),
                    onPressed: () {},
                  ),
                ],
              ),
              const SliverToBoxAdapter(child: SizedBox(height: 8)),
              SliverAppBar.large(
                foregroundColor: foregroundColor,
                backgroundColor: backgroundColor,
                leading: IconButton(
                  icon: const Icon(Icons.menu),
                  onPressed: () {},
                ),
                title: const Text('SliverAppBar.large'),
                actions: <Widget>[
                  IconButton(
                    icon: const Icon(Icons.search),
                    onPressed: () {},
                  ),
                ],
              )
            ],
          ),
        ],
      ),
    );
  }
}

/// Draw a number of boxes showing the colors of key theme color properties
/// in the ColorScheme of the inherited ThemeData and its color properties.
class ShowAppBarColors extends StatelessWidget {
  const ShowAppBarColors({
    super.key,
    this.foregroundColor,
    this.backgroundColor,
  });
  final Color? foregroundColor;
  final Color? backgroundColor;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    final bool useMaterial3 = theme.useMaterial3;
    const double spacing = 6;

    final String colorSource =
        foregroundColor == null ? ' via AppBarTheme' : ' via AppBar properties';

    // Grab the card border from the theme card shape
    ShapeBorder? border = theme.cardTheme.shape;
    // If we had one, copy in a border side to it.
    if (border is RoundedRectangleBorder) {
      border = border.copyWith(
        side: BorderSide(
          color: theme.dividerColor,
          width: 1,
        ),
      );
      // If
    } else {
      // If border was null, make one matching Card default, but with border
      // side, if it was not null, we leave it as it was.
      border ??= RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(useMaterial3 ? 12 : 4)),
        side: BorderSide(
          color: theme.dividerColor,
          width: 1,
        ),
      );
    }

    // Wrap this widget branch in a custom theme where card has a border outline
    // if it did not have one, but retains in ambient themed border radius.
    return Theme(
      data: Theme.of(context).copyWith(
        cardTheme: CardTheme.of(context).copyWith(
          elevation: 0,
          shape: border,
        ),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 8),
            child: Text(
              'AppBar Colors$colorSource',
              style: theme.textTheme.titleLarge,
            ),
          ),
          Wrap(
            alignment: WrapAlignment.start,
            crossAxisAlignment: WrapCrossAlignment.center,
            spacing: spacing,
            runSpacing: spacing,
            children: <Widget>[
              ColorCard(
                label: 'AppBar\nBackground',
                color: backgroundColor ?? theme.appBarTheme.backgroundColor!,
                textColor:
                    foregroundColor ?? theme.appBarTheme.foregroundColor!,
              ),
              ColorCard(
                label: 'AppBar\nForeground',
                color: foregroundColor ?? theme.appBarTheme.foregroundColor!,
                textColor:
                    backgroundColor ?? theme.appBarTheme.backgroundColor!,
              ),
            ],
          ),
        ],
      ),
    );
  }
}

/// A [SizedBox] with a [Card] and string text in it. Used in this demo to
/// display theme color boxes.
///
/// Can specify label text color and background color.
class ColorCard extends StatelessWidget {
  const ColorCard({
    super.key,
    required this.label,
    required this.color,
    required this.textColor,
    this.size,
  });

  final String label;
  final Color color;
  final Color textColor;
  final Size? size;

  @override
  Widget build(BuildContext context) {
    const double fontSize = 11;
    const Size effectiveSize = Size(86, 58);

    return SizedBox(
      width: effectiveSize.width,
      height: effectiveSize.height,
      child: Card(
        margin: EdgeInsets.zero,
        clipBehavior: Clip.antiAlias,
        color: color,
        child: Center(
          child: Text(
            label,
            style: TextStyle(color: textColor, fontSize: fontSize),
            textAlign: TextAlign.center,
          ),
        ),
      ),
    );
  }
}

Before After

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard flutter-dashboard bot added f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Jan 11, 2023
Copy link
Contributor

@darrenaustin darrenaustin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Nice work @TahaTesser.

@TahaTesser TahaTesser added the autosubmit Merge PR when tree becomes green via auto submit App label Jan 12, 2023
@auto-submit auto-submit bot merged commit 44f5403 into flutter:master Jan 12, 2023
@TahaTesser TahaTesser deleted the fix_sliver_app_bar_foreground_color branch January 12, 2023 10:37
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jan 12, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 12, 2023
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Jan 12, 2023
* 33c71be Bump actions/upload-artifact from 3.1.1 to 3.1.2 (flutter/flutter#118116)

* 2e0849e Bump actions/checkout from 3.1.0 to 3.3.0 (flutter/flutter#118052)

* aabf146 Bump github/codeql-action from 2.1.35 to 2.1.37 (flutter/flutter#117104)

* a50e2c8 6048f9110 Roll Dart SDK from 23cbd61a1327 to 22fa50e09ee8 (3 revisions) (flutter/engine#38776) (flutter/flutter#118320)

* e697805 Roll Plugins from 9fdc899b72ca to 620a059d62b2 (4 revisions) (flutter/flutter#118317)

* b4a07de ee76ab71e Cleanup Skia includes in image_generator/descriptor (flutter/engine#38775) (flutter/flutter#118335)

* c6be43a Roll Flutter Engine from ee76ab71e0a6 to cccaae2f3d8b (3 revisions) (flutter/flutter#118349)

* 4b2d3eb 764a9e012 Roll Skia from e1f3980272f3 to dfb838747295 (48 revisions) (flutter/engine#38790) (flutter/flutter#118355)

* b2b4050 Roll Flutter Engine from 764a9e01204d to 4a8d6866a1c0 (2 revisions) (flutter/flutter#118357)

* 727e860 Marks Mac_ios complex_layout_scroll_perf_bad_ios__timeline_summary to be unflaky (flutter/flutter#111570)

* 13ebde6 Marks Mac channels_integration_test to be unflaky (flutter/flutter#111571)

* f8628b5 Marks Mac_ios platform_views_scroll_perf_non_intersecting_impeller_ios__timeline_summary to be unflaky (flutter/flutter#116668)

* 44f5403 Fix `SliverAppBar.large` and `SliverAppBar.medium` do not use `foregroundColor` (flutter/flutter#118322)

* 51c2af5 docs: update docs about color property in material card (flutter/flutter#117263)

* 0d91c03 Fix M3 `Drawer` default shape in RTL (flutter/flutter#118185)
auto-submit bot pushed a commit to flutter/plugins that referenced this pull request Jan 12, 2023
* 5335a96 0a0e3d2 Roll Flutter from 43b9120 to 5070620 (9 revisions) (#6919) (flutter/flutter#118183)

* 6c225dd Roll Flutter Engine from 33d7f8a1b307 to 03609b420beb (6 revisions) (flutter/flutter#118125)

* 478d1da remove the unused check in selectable_text (flutter/flutter#117716)

* c87cfd7 Roll Flutter Engine from 03609b420beb to b5513d7a442a (2 revisions) (flutter/flutter#118186)

* 234452f Roll Flutter Engine from b5513d7a442a to 5bdb04f33f99 (2 revisions) (flutter/flutter#118187)

* 78416d8 51baed6e0 [fuchsia][scenic] Use infinite hit region (flutter/engine#38647) (flutter/flutter#118189)

* a02b9d2 Update to Xcode 14.2 (flutter/flutter#117507)

* eaaacdc Allow iOS and macOS plugins to share darwin directory (flutter/flutter#115337)

* 5bf6357 Roll Flutter Engine from 51baed6e01b8 to 5df0072a0e63 (3 revisions) (flutter/flutter#118192)

* 46e48ba Use program during attach if provided (flutter/flutter#118130)

* 31da712 eb5c6f0b4 iOS FlutterTextureRegistry should be a proxy, not the engine itself (flutter/engine#37666) (flutter/flutter#118197)

* fa1a4ee Update `ListTile` to support Material 3 (flutter/flutter#117965)

* 02a8bbf 3a7d8862f Re-enable UIA text/range provider unit tests (flutter/engine#38718) (flutter/flutter#118201)

* e9bbb11 Fix path for require.js (flutter/flutter#118120)

* 851611b ee0c4d26b Roll flutter/packages to 25454e (flutter/engine#38685) (flutter/flutter#118205)

* 00a9db8 Roll Flutter Engine from ee0c4d26b0fa to 264aa032cf75 (2 revisions) (flutter/flutter#118208)

* d6cd9c0 9c0b187a1 Roll Dart SDK from 853eff8b0faa to 418bee5da2e2 (4 revisions) (flutter/engine#38727) (flutter/flutter#118210)

* 4205357 add closed/open focus traversal; use open on web (flutter/flutter#115961)

* 466cb54 Roll Flutter Engine from 9c0b187a1139 to 716bb9172c0d (3 revisions) (flutter/flutter#118220)

* ad7322d Hide InkWell hover highlight when an hovered InkWell is disabled (flutter/flutter#118026)

* 583a812  Allow select cases to be numbers (flutter/flutter#116625)

* 700fe3d [Impeller Scene] Add SceneC asset importing (flutter/flutter#118157)

* 07bc245 Add a comment about repeat event + fix typos (flutter/flutter#118095)

* 5d96d61 Add  MaterialStateProperty `overlayColor` & `mouseCursor` and fix hovering on thumbs behavior (flutter/flutter#116894)

* f2c088b Roll Flutter Engine from 716bb9172c0d to 687e3cb0fbe2 (2 revisions) (flutter/flutter#118242)

* 669a3d2 Roll Plugins from 0a0e3d2 to 9fdc899 (8 revisions) (flutter/flutter#118253)

* cb62cfd Manually mark Windows run_debug_test_windows as unflaky (flutter/flutter#118112)

* 0cd8d84 Marks Mac_arm64_android run_debug_test_android to be unflaky (flutter/flutter#117469)

* 3cee38e Marks Mac_arm64_ios run_debug_test_macos to be unflaky (flutter/flutter#117990)

* 1d2e62b remove unsound mode web test (flutter/flutter#118256)

* 3d3f8e8 Update `CupertinoPicker` example (flutter/flutter#118248)

* 594333b roll packages (flutter/flutter#118117)

* a6f17e6 Add option for opting out of enter route snapshotting. (flutter/flutter#118086)

* 01583b7 roll packages (flutter/flutter#118272)

* cf529ec Roll Flutter Engine from 687e3cb0fbe2 to c1d61cf11da8 (6 revisions) (flutter/flutter#118274)

* b7881e5 Align `flutter pub get/upgrade/add/remove/downgrade` (flutter/flutter#117896)

* 12b43ed ae9e181e3 Roll Dart SDK from 5e344de60564 to 7b4d49402252 (1 revision) (flutter/engine#38756) (flutter/flutter#118287)

* b13f83a Fix Finnish TimeOfDate format (flutter/flutter#118204)

* 55e3894 Roll Flutter Engine from ae9e181e30c2 to 53bd4bbf9646 (3 revisions) (flutter/flutter#118289)

* a40fb9b 9ade91c8b removed forbidden skia include (flutter/engine#38761) (flutter/flutter#118296)

* 32b1ea3 8d7beac82 Roll Dart SDK from 7b4d49402252 to 23cbd61a1327 (1 revision) (flutter/engine#38764) (flutter/flutter#118297)

* 957781a 6256f05db Roll Fuchsia Mac SDK from 6xysoRPCXJ3cJX12x... to a9NpYJbjhDRX9P9u4... (flutter/engine#38767) (flutter/flutter#118300)

* f10965f FIX: UnderlineInputBorder hashCode and equality by including borderRadius (flutter/flutter#118284)

* 33c71be Bump actions/upload-artifact from 3.1.1 to 3.1.2 (flutter/flutter#118116)

* 2e0849e Bump actions/checkout from 3.1.0 to 3.3.0 (flutter/flutter#118052)

* aabf146 Bump github/codeql-action from 2.1.35 to 2.1.37 (flutter/flutter#117104)

* a50e2c8 6048f9110 Roll Dart SDK from 23cbd61a1327 to 22fa50e09ee8 (3 revisions) (flutter/engine#38776) (flutter/flutter#118320)

* e697805 Roll Plugins from 9fdc899 to 620a059 (4 revisions) (flutter/flutter#118317)

* b4a07de ee76ab71e Cleanup Skia includes in image_generator/descriptor (flutter/engine#38775) (flutter/flutter#118335)

* c6be43a Roll Flutter Engine from ee76ab71e0a6 to cccaae2f3d8b (3 revisions) (flutter/flutter#118349)

* 4b2d3eb 764a9e012 Roll Skia from e1f3980272f3 to dfb838747295 (48 revisions) (flutter/engine#38790) (flutter/flutter#118355)

* b2b4050 Roll Flutter Engine from 764a9e01204d to 4a8d6866a1c0 (2 revisions) (flutter/flutter#118357)

* 727e860 Marks Mac_ios complex_layout_scroll_perf_bad_ios__timeline_summary to be unflaky (flutter/flutter#111570)

* 13ebde6 Marks Mac channels_integration_test to be unflaky (flutter/flutter#111571)

* f8628b5 Marks Mac_ios platform_views_scroll_perf_non_intersecting_impeller_ios__timeline_summary to be unflaky (flutter/flutter#116668)

* 44f5403 Fix `SliverAppBar.large` and `SliverAppBar.medium` do not use `foregroundColor` (flutter/flutter#118322)

* 51c2af5 docs: update docs about color property in material card (flutter/flutter#117263)

* 0d91c03 Fix M3 `Drawer` default shape in RTL (flutter/flutter#118185)
esouthren pushed a commit to esouthren/flutter that referenced this pull request Jan 15, 2023