我如何将 Flutter 中的所有设计元素隔离到一个 ThemeData 类...有任何策略 os 解决方案吗?

Posted

技术标签:

【中文标题】我如何将 Flutter 中的所有设计元素隔离到一个 ThemeData 类...有任何策略 os 解决方案吗?【英文标题】:How i can isolate all design elements in Flutter to one ThemeData class ... Have any strategy os solution? 【发布时间】:2021-07-13 10:13:43 【问题描述】:

如何将 Flutter 中的所有设计元素隔离到一个 ThemeData 类文件中。颜色,装饰,配色方案。我尝试将我的代码分离为设计、页面、业务/类似...

myThemeData 文件:

import 'package:flutter/material.dart';

class MyTheme 
  final BuildContext context;

  MyTheme(this.context);

  ColorScheme get myColorSheme 
    return Theme.of(context).colorScheme.copyWith(
          primary: Colors.red,
          onPrimary: Colors.black,
          primaryVariant: Colors.orange,
          background: Colors.red,
          onBackground: Colors.black,
          secondary: Colors.red,
          onSecondary: Colors.white,
          secondaryVariant: Colors.deepOrange,
          error: Colors.black,
          onError: Colors.white,
          surface: Colors.white,
          onSurface: Colors.black,
          brightness: Brightness.light,
        );
  

  ThemeData get myThemeData 
    return ThemeData(
      buttonTheme: ButtonThemeData(
        textTheme: ButtonTextTheme.primary,
      ),
      hintColor: Colors.red,
      brightness: Brightness.dark,
      colorScheme: myColorSheme,
    );
  

  static InputDecoration inputDecoration(String hintText, Icon icon) 
    return InputDecoration(
      hintStyle: MyTheme.hintTextStyle,
      hintText: hintText,
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.white, width: 3),
      ),
      enabledBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.white54, width: 1),
      ),
      prefixIcon:
          IconTheme(data: IconThemeData(color: Colors.white), child: icon),
    );
  

  static TextStyle get hintTextStyle 
    return TextStyle(
        fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white30);
  

  static TextStyle get textFieldStyle 
    return TextStyle();
  

  static TextStyle get logoTextStyle 
    return TextStyle(
      fontSize: 40,
      fontWeight: FontWeight.bold,
    );
  

结果我有错误

════════小部件库捕获的异常═════════════════════════════════════ ═ 在构建 MyApp(dirty, state: _MyAppState#84f70) 时抛出了以下断言: 断言失败: C:\…\material\theme_data.dart:316 colorScheme?.brightness == null ||亮度 == 空 || colorScheme!.brightness == 亮度 不是真的

相关的导致错误的小部件是 我的应用 lib\main.dart:10 抛出异常时,这是堆栈 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 236:49 throw C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3 assertFailed 包/flutter/src/material/theme_data.dart 316:106 新 包/服务/UI/Theme.dart 27:12 获取 myThemeData 包/服务/main.dart 24:38 构建 ... ══════════════════════════════════════════════════ ══════════════════════════════

【问题讨论】:

【参考方案1】:

在定义自己的主题数据时使用copyWith 方法很好。大多数时候使用不使用所有字段,并且某些字段是强制性的。

所以做这样的事情

For Dark theme
 ThemeData get myThemeData 
    return ThemeData.dark().copyWith()(
      buttonTheme: ButtonThemeData(
        textTheme: ButtonTextTheme.primary,
      ),
      hintColor: Colors.red,
      brightness: Brightness.dark,
      colorScheme: myColorSheme,
    );
  


For Light theme
 ThemeData get myThemeData 
    return ThemeData.light().copyWith()(
      buttonTheme: ButtonThemeData(
        textTheme: ButtonTextTheme.primary,
      ),
      hintColor: Colors.red,
      brightness: Brightness.dark,
      colorScheme: myColorSheme,
    );
  

您还可以看到我如何在我的一个项目中使用 ThemeData,如下所示

我的黑暗/黑色主题


ThemeData blackTheme(BuildContext context) 
  return ThemeData.dark().copyWith(
    snackBarTheme: SnackBarThemeData(
      backgroundColor: selectedPrimaryColor,
      actionTextColor: greyColor,
      contentTextStyle: const TextStyle(color: Colors.white),
      shape: const ContinuousRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
    ),
    accentColor: selectedPrimaryColor,
    cardColor: Colors.black,
    primaryColor: Colors.black,
    brightness: Brightness.dark,
    primaryColorLight: Colors.black,
    scaffoldBackgroundColor: Colors.black,
    dialogBackgroundColor: Colors.black,
    canvasColor: Colors.black,
    floatingActionButtonTheme: FloatingActionButtonThemeData(
      foregroundColor: Colors.white,
      backgroundColor: selectedPrimaryColor,
    ),
    dialogTheme: DialogTheme(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
      ),
    ),
    textSelectionTheme: TextSelectionThemeData(
      cursorColor: selectedPrimaryColor,
      selectionHandleColor: selectedPrimaryColor,
      selectionColor: darken(selectedPrimaryColor, 50),
    ),
    textTheme: const TextTheme(
      headline5: TextStyle(color: Colors.white),
      headline1: TextStyle(color: Colors.white),
      headline2: TextStyle(color: Colors.white),
      bodyText1: TextStyle(color: Colors.white),
      bodyText2: TextStyle(color: Colors.white),
      caption: TextStyle(color: Colors.white),
      subtitle1: TextStyle(color: Colors.white),
      subtitle2: TextStyle(color: Colors.white),
    ),
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.resolveWith<Color>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return greyColor;
            
            return selectedPrimaryColor; // Defer to the widget's default.
          ,
        ),
        /* elevation: MaterialStateProperty.resolveWith<double>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return 0;
            
            return 0; // Defer to the widget's default.
          ,
        ),*/
        foregroundColor: MaterialStateProperty.resolveWith<Color>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return greyColor;
            
            return selectedPrimaryColor; // Defer to the widget's default.
          ,
        ),
      ),
    ),
    bottomSheetTheme: const BottomSheetThemeData(
      backgroundColor: Colors.black,
    ),
    textButtonTheme: TextButtonThemeData(
      style: ButtonStyle(
        foregroundColor: MaterialStateProperty.resolveWith<Color>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return greyColor;
            
            return Colors.white; // Defer to the widget's default.
          ,
        ),
        backgroundColor: MaterialStateProperty.resolveWith<Color>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return greyColor;
            
            return Colors.black; // Defer to the widget's default.
          ,
        ),
      ),
    ),
  );

我的轻主题

ThemeData lightTheme(BuildContext context) 
  // debugPrint(selectedPrimaryColor.toString());
  return ThemeData.light().copyWith(
    canvasColor: Colors.white,
    cardColor: const Color.fromARGB(255, 255, 255, 255),
    accentColor: selectedPrimaryColor,
    toggleableActiveColor: selectedPrimaryColor,
    primaryColor: selectedPrimaryColor,
    dialogTheme: const DialogTheme(
        titleTextStyle: TextStyle(
      color: Colors.black,
      fontWeight: FontWeight.bold,
    )),
    snackBarTheme: SnackBarThemeData(
      backgroundColor: selectedPrimaryColor,
      actionTextColor: Colors.white,
      contentTextStyle: const TextStyle(
        color: Colors.white,
      ),
      shape: const ContinuousRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
    ),
    brightness: Brightness.light,
    bottomSheetTheme: BottomSheetThemeData(
      backgroundColor: Colors.white,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
      ),
    ),
    textTheme: TextTheme(
      headline5: const TextStyle(color: Colors.black),
      headline1: const TextStyle(color: Colors.black),
      headline2: const TextStyle(color: Colors.black),
      bodyText1: const TextStyle(color: Colors.black),
      bodyText2: const TextStyle(color: Colors.black),
      caption: const TextStyle(color: Colors.black),
      subtitle1: const TextStyle(color: Colors.black),
      subtitle2: TextStyle(color: Colors.grey[200]),
    ),
    textSelectionTheme: TextSelectionThemeData(
      cursorColor: selectedPrimaryColor,
      selectionHandleColor: selectedPrimaryColor,
      selectionColor: lighten(selectedPrimaryColor, 65),
    ),
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.resolveWith<Color>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return greyColor;
            
            return selectedPrimaryColor; // Defer to the widget's default.
          ,
        ),
        foregroundColor: MaterialStateProperty.resolveWith<Color>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return Colors.black;
            
            return selectedPrimaryColor; // Defer to the widget's default.
          ,
        ),
      ),
    ),
    floatingActionButtonTheme:
        Theme.of(context).floatingActionButtonTheme.copyWith(
              backgroundColor: selectedPrimaryColor,
              foregroundColor: Colors.white,
            ),
    textButtonTheme: TextButtonThemeData(
      style: ButtonStyle(
        foregroundColor: MaterialStateProperty.resolveWith<Color>(
          (Set<MaterialState> states) 
            if (states.contains(MaterialState.disabled)) 
              return greyColor;
            
            return selectedPrimaryColor;
          ,
        ),
      ),
    ),
  );


【讨论】:

萨克斯。据我了解,copyWith(...) 仅用于部分更改您想要的内容? 是的。但如果你决定走其他路。从头开始定义一切。然后你应该提供所有必填字段。 Kop kop rakhme(非常非常 Thax)对不起我的英语! 如果可能? 1模式问题!我如何理解 MaterialApp 有 2 种模式 Dakr 和 light!我可以创建 MyMode 吗?以及如何更好地重新实现?

以上是关于我如何将 Flutter 中的所有设计元素隔离到一个 ThemeData 类...有任何策略 os 解决方案吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过对flutter中的元素求和来拆分列表

Flutter - 如何访问 ListView.builder 中的一个元素?

如何将机器人消息发送到一台服务器中的多个通道(阅读正文以获取更多信息)

Flutter:如何显示同一张表中的所有列

从零到一学习Flutter——状态和路由

如何将 TextButton 背景颜色输入到 Flutter/dart 中的函数