猫哥课堂 ducafecat.com

flutter 主题色彩管理组件 flex_color_scheme

前言

平时我们做样式适配关心几个方面:

  • 设计稿颜色
  • 标记尺寸大小、比例
  • 全局修改为主
  • 快速可修改

今天将会介绍一个快速调整主题色彩样式的三方组件 flex_color_scheme

https://pub-web.flutter-io.cn/packages/flex_color_scheme

这个组件已经支持了 flutter 3.10 和 Material 3

参考

Flex color scheme

https://pub-web.flutter-io.cn/packages/flex_color_scheme

https://docs.flexcolorscheme.com/

https://rydmike.com/flexcolorscheme/themesplayground-v7-1/

Material 3

https://m3.material.io/

https://m3.material.io/theme-builder

https://space.bilibili.com/389903587/channel/collectiondetail?sid=246709

本机环境

❯ flutter --version Flutter 3.10.5 • channel stable • https://github.com/flutter/flutter.git Framework • revision 796c8ef792 (2 天前)2023-06-13 15:51:02 -0700 Engine • revision 45f6e00911 Tools • Dart 3.0.5 • DevTools 2.23.1

步骤

第一步:配置依赖

pubspec.yaml

dependencies: flutter: sdk: flutter ... flex_color_scheme: ^7.1.2

第二步:打开样式定制器

https://rydmike.com/flexcolorscheme/themesplayground-v7-1/

第三步:复制样式代码

lib/main.dart

// This widget is the root of your application. Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', // Theme config for FlexColorScheme version 7.1.x. Make sure you use // same or higher package version, but still same major version. If you // use a lower package version, some properties may not be supported. // In that case remove them after copying this theme to your app. theme: FlexThemeData.light( colors: const FlexSchemeColor( primary: Color(0xff065808), primaryContainer: Color(0xff9ee29f), secondary: Color(0xff365b37), secondaryContainer: Color(0xffaebdaf), tertiary: Color(0xff2c7e2e), tertiaryContainer: Color(0xffb8e6b9), appBarColor: Color(0xffb8e6b9), error: Color(0xffb00020), ), surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold, blendLevel: 7, appBarStyle: FlexAppBarStyle.material, appBarOpacity: 0.87, transparentStatusBar: false, appBarElevation: 12.5, subThemesData: const FlexSubThemesData( useTextTheme: true, useM2StyleDividerInM3: true, tabBarIndicatorWeight: 5, tabBarIndicatorTopRadius: 6, ), keyColors: const FlexKeyColors( useSecondary: true, useTertiary: true, ), visualDensity: FlexColorScheme.comfortablePlatformDensity, useMaterial3: true, swapLegacyOnMaterial3: true, // To use the Playground font, add GoogleFonts package and uncomment // fontFamily: GoogleFonts.notoSans().fontFamily, ), darkTheme: FlexThemeData.dark( colors: const FlexSchemeColor( primary: Color(0xff629f80), primaryContainer: Color(0xff274033), secondary: Color(0xff81b39a), secondaryContainer: Color(0xff4d6b5c), tertiary: Color(0xff88c5a6), tertiaryContainer: Color(0xff356c50), appBarColor: Color(0xff356c50), error: Color(0xffcf6679), ), surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold, blendLevel: 13, transparentStatusBar: false, subThemesData: const FlexSubThemesData( useTextTheme: true, useM2StyleDividerInM3: true, tabBarIndicatorWeight: 5, tabBarIndicatorTopRadius: 6, ), keyColors: const FlexKeyColors( useSecondary: true, useTertiary: true, ), visualDensity: FlexColorScheme.comfortablePlatformDensity, useMaterial3: true, swapLegacyOnMaterial3: true, // To use the Playground font, add GoogleFonts package and uncomment // fontFamily: GoogleFonts.notoSans().fontFamily, ), // If you do not have a themeMode switch, uncomment this line // to let the device system mode control the theme mode: themeMode: ThemeMode.system, home: const MyHomePage(title: 'Flutter Demo Home Page'), ); }

运行

通过 FlexSchemeColor 自定义颜色

const FlexSchemeData _myFlexScheme = FlexSchemeData( name: 'Midnight blue', description: 'Midnight blue theme, custom definition of all colors', light: FlexSchemeColor( primary: Color(0xFF00296B), primaryContainer: Color(0xFFA0C2ED), secondary: Color(0xFFD26900), secondaryContainer: Color(0xFFFFD270), tertiary: Color(0xFF5C5C95), tertiaryContainer: Color(0xFFC8DBF8), ), dark: FlexSchemeColor( primary: Color(0xFFB1CFF5), primaryContainer: Color(0xFF3873BA), secondary: Color(0xFFFFD270), secondaryContainer: Color(0xFFD26900), tertiary: Color(0xFFC9CBFC), tertiaryContainer: Color(0xFF535393), ), );

FlexThemeData 是对 ThemeData 扩展

/// /// However, Dart does not yet support such extensions, see: /// https://github.com/dart-lang/language/issues/723 extension FlexThemeData on ThemeData { /// Returns a [ThemeData] object defined by factory [FlexColorScheme.light] /// and its [FlexColorScheme.toTheme] method. static ThemeData light({ /// The [FlexSchemeColor] that will be used to create the light /// [FlexColorScheme]. /// /// You can use predefined [FlexSchemeColor] values from [FlexColor] or /// [FlexColor.schemes] map or define your own colors with /// [FlexSchemeColor] or [FlexSchemeColor.from]. /// /// For using built-in color schemes, the convenience shortcut to select /// it with the [scheme] property is recommended and leaving [colors] /// undefined. If both are specified the scheme colors defined by [colors] /// are used. If both are null then [scheme] defaults to /// [FlexScheme.material], thus defining the resulting scheme. final FlexSchemeColor? colors,

FlexThemeData.light 返回的还是 ThemeData ,所以你可以加入自己的内容。

加入自定义样式定义

// Theme config for FlexColorScheme version 7.1.x. Make sure you use // same or higher package version, but still same major version. If you // use a lower package version, some properties may not be supported. // In that case remove them after copying this theme to your app. theme: FlexThemeData.light( colors: const FlexSchemeColor( primary: Color(0xff065808), primaryContainer: Color(0xff9ee29f), secondary: Color(0xff365b37), secondaryContainer: Color(0xffaebdaf), tertiary: Color(0xff2c7e2e), tertiaryContainer: Color(0xffb8e6b9), appBarColor: Color(0xffb8e6b9), error: Color(0xffb00020), ), surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold, blendLevel: 7, appBarStyle: FlexAppBarStyle.material, appBarOpacity: 0.87, transparentStatusBar: false, appBarElevation: 12.5, subThemesData: const FlexSubThemesData( useTextTheme: true, useM2StyleDividerInM3: true, tabBarIndicatorWeight: 5, tabBarIndicatorTopRadius: 6, ), keyColors: const FlexKeyColors( useSecondary: true, useTertiary: true, ), visualDensity: FlexColorScheme.comfortablePlatformDensity, useMaterial3: true, swapLegacyOnMaterial3: true, // To use the Playground font, add GoogleFonts package and uncomment // fontFamily: GoogleFonts.notoSans().fontFamily, ).copyWith( elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: Colors.red, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), ), ), ),

通过 copyWith 的方式

FlexSubThemesData 子主题重写

/// Activate using FlexColorScheme opinionated component sub-themes by /// passing in a default `FlexSubThemesData()`. /// /// To further configure the sub-themes, change the simple flat value /// properties as desired in `FlexSubThemesData()`. /// /// By default [FlexThemeData.light], [FlexThemeData.dark] and /// [FlexColorScheme.toTheme], do as little as they need to just /// provide a consistent Material 2 color schemed theme. The additions they /// do are described in [FlexColorScheme.toTheme]. /// /// The original purpose of the opinionated sub-themes was to make it easy /// to add themed corner radius to all Widgets that support it, and to /// provide a consistent look on all buttons, including [ToggleButtons]. /// /// Therefore the sub themes are a convenient way to opt-in on customized /// corner radius on Widgets using above themes. By opting in you can set /// corner radius for all covered Widgets to same corner radius in one go. /// There are also properties to override the global default for each widget /// to set different rounding per widget if so desired. /// /// By default, if a `defaultRadius` is not specified, each widgets corner /// radius and some other styling take inspiration from the Material 3 (M3) /// specification https://m3.material.io/ and uses its specifications as /// defaults when it is possible to do so in Flutter SDK theming when using /// Material2 mode and via defaults also in Material 3 mode. /// /// Starting from version 5, by opting in via a default [subThemesData] you /// get an extensive set of widget component sub themes applied. /// They can be customized via the [subThemesData] property, that has /// quick and flat sub theme configuration values in the data class /// [FlexSubThemesData]. /// /// Customizable sub-themes are available for: /// /// * [AppBarTheme] for [AppBar] via [FlexSubThemes.appBarTheme]. /// * [BottomAppBarTheme] for [BottomAppBar] via /// [FlexSubThemes.bottomAppBarTheme]. /// * [BottomNavigationBarThemeData] for [BottomNavigationBar] via /// [FlexSubThemes.bottomNavigationBar]. /// * [BottomSheetThemeData] for [BottomSheet] via /// [FlexSubThemes.bottomSheetTheme]. /// * [ButtonThemeData] for old deprecated buttons, via /// [FlexSubThemes.buttonTheme]. /// * [CardTheme] for [Card] via [FlexSubThemes.cardTheme]. /// * [CheckboxThemeData] for [Checkbox] via [FlexSubThemes.checkboxTheme]. /// * [ChipThemeData] for [Chip] via [FlexSubThemes.chipTheme]. /// * [DatePickerThemeData] for [DatePicker] via /// [FlexSubThemes.datePickerTheme]. /// * [DialogTheme] for [Dialog] via [FlexSubThemes.dialogTheme]. /// * [DrawerThemeData] for [Drawer] via [FlexSubThemes.drawerTheme]. /// * [DropdownMenuThemeData] for [DropDownMenu] via /// [FlexSubThemes.dropdownMenuTheme]. /// * [ElevatedButtonThemeData] for [ElevatedButton] via /// [FlexSubThemes.elevatedButtonTheme]. /// * [FilledButtonThemeData] for [FilledButton] via /// [FlexSubThemes.filledButtonTheme]. /// * [FloatingActionButtonThemeData] for [FloatingActionButton] via /// [FlexSubThemes.floatingActionButtonTheme]. /// * [IconButtonThemeData] for [IconButton] via /// [FlexSubThemes.iconButtonTheme]. /// * [InputDecorationTheme] for [InputDecoration] via /// [FlexSubThemes.inputDecorationTheme]. /// * [MenuBarThemeData] for [MenuBar] via [FlexSubThemes.menuBarTheme]. /// * [MenuButtonThemeData] for [MenuButton] via /// [FlexSubThemes.menuButtonTheme]. /// * [MenuThemeData] for [MenuBar], [MenuAnchor] and [DropDownMenu] via /// [FlexSubThemes.menuTheme]. /// * [ListTileThemeData] for [ListTile] via /// [FlexSubThemes.listTileTheme]. /// * [NavigationBarThemeData] for [NavigationBar] via /// [FlexSubThemes.navigationBarTheme]. /// * [NavigationDrawerThemeData] for [NavigationDrawer] via /// [FlexSubThemes.navigationDrawerTheme]. /// * [NavigationRailThemeData] for [NavigationRail] via /// [FlexSubThemes.navigationRailTheme]. /// * [OutlinedButtonThemeData] for [OutlinedButton] via /// [FlexSubThemes.outlinedButtonTheme]. /// * [PopupMenuThemeData] for [PopupMenuButton] via /// [FlexSubThemes.popupMenuTheme]. /// * [RadioThemeData] for [Radio] via [FlexSubThemes.radioTheme]. /// * [SliderThemeData] for [Slider] via [FlexSubThemes.sliderTheme]. /// * [SnackBarThemeData] for [SnackBar] via [FlexSubThemes.snackBarTheme]. /// * [SwitchThemeData] for [Switch] via [FlexSubThemes.switchTheme]. /// * [TabBarTheme] for [TabBar] via [FlexSubThemes.tabBarTheme]. /// * [TextButtonThemeData] for [TextButton] via /// [FlexSubThemes.textButtonTheme]. /// * [TimePickerThemeData] for [TimePickerDialog] via /// [FlexSubThemes.timePickerTheme]. /// * [ToggleButtonsThemeData] for [ToggleButtons] via /// [FlexSubThemes.toggleButtonsTheme]. /// * [TooltipThemeData] for [Tooltip] via [FlexSubThemes.tooltipTheme]. /// /// Defaults to null, resulting in FlexColorScheme not using any extra /// sub-theming in addition to those described in [FlexColorScheme.toTheme]. final FlexSubThemesData? subThemesData,

subThemesData 中罗列了常见的样式属性

代码

https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_flex_color_scheme

小结

flex_color_scheme 是一个快速的样式设置工具,还修复了 flutter sdk 中的一些组件颜色不到位的缺陷,赶快用上吧。

感谢阅读本文

如果我有什么错?请在评论中让我知道。我很乐意改进。


© 猫哥 ducafecat.com

end


Copyright 2023 ducafecat. All rights reserved.
微信: ducafecat, line: ducafecat,京ICP备2021009050号-3