Flutter - 如何根据按钮是在应用栏还是主屏幕中为平面按钮设置不同颜色的文本

Posted

技术标签:

【中文标题】Flutter - 如何根据按钮是在应用栏还是主屏幕中为平面按钮设置不同颜色的文本【英文标题】:Flutter - How to style different color text for Flat Buttons depending on whether button is in appbar or main screen 【发布时间】:2020-05-30 19:38:23 【问题描述】:

在我的 styles.dart 中,我有以下主题:

final ThemeData purpleTheme = ThemeData(
    brightness: Brightness.light,
    primaryColor: PURPLE,
    buttonColor: GREEN,
    fontFamily: FontNameDefault,
    buttonTheme: ButtonThemeData(
        textTheme: ButtonTextTheme
            .primary, // TODO: This is making the flat buttons all appear in blue instead of purple
        buttonColor: GREEN,
        height: 45),
    appBarTheme: AppBarTheme(
      textTheme: TextTheme(title: AppBarTextStyle, button: AppBarTextStyle),
      iconTheme: new IconThemeData(color: Colors.white),
      brightness: Brightness.dark,
      color: PURPLE,
    ),
    textTheme: TextTheme(
        title: TitleTextStyle,
        body1: Body1TextStyle,
        subtitle: SubtitleTextStyle));

通过上述主题设置,buttonTheme textTheme 为 ButtonTextTheme.primary。由于某种原因,原色似乎是蓝色,尽管我的造型中没有使用蓝色。当我添加

colorScheme: ColorScheme.light().copyWith(primary: PURPLE)

到风格,原色变成紫色。但是,我希望紫色应用栏中的平面按钮使用白色文本,而白色屏幕中的平面按钮使用紫色文本。如何将其编码到 ThemeData 中?

【问题讨论】:

为什么不能简单地使用这两种颜色???是什么阻止你这样做? 用一个主题来做会更优雅:) 【参考方案1】:

您的用例已经在 Material 主题规范中得到了很好的定义。

在这里,我将解释如何根据父小部件颜色设置任何小部件的颜色样式(例如:按钮/文本/自定义小部件..)。

示例用例:

    白色 appBar 上的主要彩色文本 原色 appBar 上的白色文本 白色表面上的黑色文本 白色表面上的原色文本

给你。

第 1 步:

首先, 定义一个原色样本,定义从 50 到 900 的所有变体。

final MaterialColor lightPrimaryColorSwatch = MaterialColor(
    0xff4f9af0,
    
      50: Color(0xffeaf3fd),
      100: Color(0xffcae1fb),
      200: Color(0xffa7cdf8),
      300: Color(0xff84b8f5),
      400: Color(0xff69a9f2),
      500: Color(0xff4f9af0),
      600: Color(0xff4892ee),
      700: Color(0xff3f88ec),
      800: Color(0xff367ee9),
      900: Color(0xff266ce5),
    ,
  );

第 2 步:

您需要定义一个 ColorScheme 对象来定义材料规格的所有 12 种颜色。

final ColorScheme lightColorScheme = ColorScheme(
        brightness: Brightness.light,
        primary: Color(0xff4f9af0),
        primaryVariant: Color(0xff2c86ed),
        secondary: Color(0xff0863c4),
        secondaryVariant: Color(0xff259b24),
        error: Color(0xffb00020),
        background: Color(0xfff7f8fa),
        onError: Colors.white,
        onSecondary: Colors.white,
        onBackground: Color(0xff292929),
        onPrimary: Colors.white,
        onSurface: Color(0xff292929),
        surface: Colors.white,
      );

第三步:

使用上述定义的值为您的MaterialApp 定义主题数据。

 return MaterialApp(

      theme: ThemeData(
        brightness: Brightness.light,
        primarySwatch: lightPrimaryColorSwatch,
        primaryColor: lightColorScheme.primary,
        primaryColorDark: lightColorScheme.primaryVariant,
        errorColor: lightColorScheme.error,
        colorScheme: lightColorScheme,
        primaryColorBrightness: Brightness.dark,
        accentColorBrightness: Brightness.dark,
        accentColor: lightColorScheme.secondary,
        primaryColorLight: lightColorScheme.secondaryVariant,
        backgroundColor: lightColorScheme.background,
        canvasColor: lightColorScheme.background,
      ),
    //... other attributes go here
  );

现在一切就绪。从现在开始,您可以将这 12 种颜色用于您想要的任何类型的组合。

这是一个例子。

import 'package:flutter/material.dart';


void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final MaterialColor lightPrimaryColorSwatch = MaterialColor(
      0xff4f9af0,
      
        50: Color(0xffeaf3fd),
        100: Color(0xffcae1fb),
        200: Color(0xffa7cdf8),
        300: Color(0xff84b8f5),
        400: Color(0xff69a9f2),
        500: Color(0xff4f9af0),
        600: Color(0xff4892ee),
        700: Color(0xff3f88ec),
        800: Color(0xff367ee9),
        900: Color(0xff266ce5),
      ,
    );

    final ColorScheme lightColorScheme = ColorScheme(
      brightness: Brightness.light,
      primary: Color(0xff4f9af0),
      primaryVariant: Color(0xff2c86ed),
      secondary: Color(0xff0863c4),
      secondaryVariant: Color(0xff259b24),
      error: Color(0xffb00020),
      background: Color(0xfff7f8fa),
      onError: Colors.white,
      onSecondary: Colors.white,
      onBackground: Color(0xff292929),
      onPrimary: Colors.white,
      onSurface: Color(0xff292929),
      surface: Colors.white,
    );
    return MaterialApp(
      theme: ThemeData(
        brightness: Brightness.light,
        primarySwatch: lightPrimaryColorSwatch,
        primaryColor: lightColorScheme.primary,
        primaryColorDark: lightColorScheme.primaryVariant,
        errorColor: lightColorScheme.error,
        colorScheme: lightColorScheme,
        primaryColorBrightness: Brightness.dark,
        accentColorBrightness: Brightness.dark,
        accentColor: lightColorScheme.secondary,
        primaryColorLight: lightColorScheme.secondaryVariant,
        backgroundColor: lightColorScheme.background,
        canvasColor: lightColorScheme.background,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  


    class MyWidget extends StatelessWidget 
      @override
      Widget build(BuildContext context) 
        return Column(
          children: <Widget>[
            SizedBox(height: 8.0),
           ///white color text on container with primary color
            Container(
                color: Theme.of(context).colorScheme.primary,
                height: 40.0,
                width: 100.0,
                alignment: Alignment.center,
                child: Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text('Hello, World!',
                      style: Theme.of(context).textTheme.bodyText2.copyWith(
                          color: Theme.of(context).colorScheme.onPrimary)),
                )),
            SizedBox(height: 8.0),
            ///Primary color text on  white color container.
            Container(
                color: Theme.of(context).colorScheme.surface,
                height: 40.0,
                width: 100.0,
                alignment: Alignment.center,
                child: Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text('Hello, World!',
                      style: Theme.of(context)
                          .textTheme
                          .bodyText2
                          .copyWith(color: Theme.of(context).colorScheme.primary)),
                )),
          ],
        );
      
    

您可以找到现场演示 here。

【讨论】:

+1 信息丰富;虽然我希望有一个解决方案,小部件本身不需要样式代码,但这似乎是目前最好的解决方案。

以上是关于Flutter - 如何根据按钮是在应用栏还是主屏幕中为平面按钮设置不同颜色的文本的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 使用插件实现双屏交互

浏览器和应用栏中的后退按钮在 Flutter Web 开发中不起作用

Flutter——两种监听导航栏返回按钮的方法

Flutter:如何将可访问性焦点集中到自定义应用栏

如何知道我的 Flutter Web 应用程序是在移动设备还是桌面设备上运行

win7双屏如何实现窗口从主屏移动到副屏?