【问题标题】:Background color does not switch between light and dark themes in Angular material 2背景颜色不会在 Angular 材质 2 中的明暗主题之间切换
【发布时间】:2017-09-30 05:09:23
【问题描述】:

我有一个使用 Material 2(当前版本,2.0.0-beta.11)的 Angular 4 应用程序。

我按照documentation进行主题化,创建了两个主题,一个浅色主题和一个深色主题。因为我不使用 md-sidenav 组件,所以我将 mat-app-background 类放在 body 元素上,它应用当前主题的背景颜色(浅灰色用于浅色主题,深灰色用于深色主题。)

问题是当我的主题切换器被切换时(一个添加或删除类的简单按钮,没什么特别的,like this answer),mat-app-background 的背景颜色没有更新。

我无法创建成功使用自定义主题的 plunker,但基本要点如下:

index.html

<body class="mat-app-background">
  <app-root></app-root>
</body>

app.component.html

<main [class.dark-theme]="isDarkTheme">
  <button md-raised-button color="primary" (click)="toggleTheme()">Toggle</button>
  <!-- other content -->
</main>

app.component.ts

isDarkTheme: boolean = false;
toggleTheme() { this.isDarkTheme = !this.isDarkTheme; }

主题.scss

@import '~@angular/material/theming';
@include mat-core();

// light (default) theme
$lt-primary: mat-palette($mat-indigo);
$lt-accent:  mat-palette($mat-pink, A200, A100, A400);
$lt-theme:   mat-light-theme($lt-primary, $lt-accent);
@include angular-material-theme($lt-theme);

// alternate dark theme
$dark-primary: mat-palette($mat-blue-grey);
$dark-accent:  mat-palette($mat-amber, A200, A100, A400);
$dark-warn:    mat-palette($mat-deep-orange);
$dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

.dark-theme {
  @include angular-material-theme($dark-theme);
}

当我单击按钮时,它成功切换了主题:应用了类,按钮将颜色从浅色主题原色更改为深色主题原色。但背景颜色仍然是浅色主题的背景颜色。

默认背景颜色“固定”并且不受主题切换的影响。我缺少什么?有没有办法让背景颜色自动在没有混合/手动重新定义的情况下更新?

(注意:干净的 Angular cli 项目,使用直接从 Angular 材质文档粘贴的主题副本。Angular 4.4.4,材质 2.0.0-beta.11。)

【问题讨论】:

    标签: angular angular-material2


    【解决方案1】:

    我在 angular material 2 github 项目的已关闭问题中找到了答案 indirectly acknowledged,因此我将在下面概述正在发生的事情以及我如何应用解决方法来处理此“功能”。

    Angular Material 2 主题仅适用于 Material 组件。

    也就是说,如果您将整个应用程序嵌套在 md-sidenav(或 mad-sidenav)组件中,那么您就可以,因为这是一个 Material 组件。但是,如果您不使用它,而是按照文档中的说明应用 mat-app-background您只会获得初始应用主题的样式。

    为了在非材质组件元素(例如常规 html 元素)上使用此功能,您需要应用 scss mixin 以应用这些样式。此外,您需要手动设置所有非材质组件元素的样式。

    首先,我更新了我的 theme.scss 以包含一个针对 main 元素的 mixin。与我最初的帖子一样,main 包装了整个 app.component,并且是我应用深色主题类的类。

    @mixin html-theme($theme) {
      & {
        $background: map-get($theme, background);
        $foreground: map-get($theme, foreground);
    
        background-color: mat-color($background, background);
        color: mat-color($foreground, text);
    
        // other html element styling here
      }
    }
    

    在这里,我手动将主题的背景色和前景色分别应用到主元素上作为背景色和字体色。请务必注意,我已将主要元素的一般样式调整为浏览器窗口的全高。

    为了应用这个,我@include sass 文件中主题类定义中的 mixin。重要的是,我还必须将我的默认主题分配给它自己的类;否则默认值总是会触发 mixin 并用默认值覆盖活动主题的样式。

    // light (default) theme
    .light-theme {
      $lt-primary: mat-palette($mat-indigo);
      $lt-accent:  mat-palette($mat-pink, A200, A100, A400);
      $lt-theme:   mat-light-theme($lt-primary, $lt-accent);
    
      @include angular-material-theme($lt-theme);
    
      @at-root main.light-theme {
        @include html-theme($lt-theme);
      }
    }
    
    // alternate dark theme
    .dark-theme {
      $dark-primary: mat-palette($mat-blue-grey);
      $dark-accent:  mat-palette($mat-amber, A200, A100, A400);
      $dark-warn:    mat-palette($mat-deep-orange);
      $dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
    
      @include angular-material-theme($dark-theme);
    
      @at-root main.dark-theme {
        @include html-theme($dark-theme);
      }
    }
    

    我使用 sass @at-root 指令明确地重新定位 main 元素的原因是因为主题类还需要应用于 CDK 覆盖,以便应用于下拉菜单和日期等元素选择器。 (令人讨厌,但在测试版的这一点上,您必须手动完成。)

    为了支持两个不同的主题类,我简单地调整了 app.component.html 以在“light-theme”和“dark-theme”之间切换:

    <main [class.dark-theme]="isDarkTheme" [class.light-theme]="!isDarkTheme">
    

    而且,如前所述,我们还需要重新设置 CDK 覆盖的主题,因此我更新了 app.component.ts 文件以向其中添加适当的主题类:

    isDarkTheme = false;
    
    constructor(private overlayContainer: OverlayContainer) {
      this.setOverlayClass();
    }
    
    toggleTheme() {
      this.isDarkTheme = !this.isDarkTheme;
      this.setOverlayClass();
    }
    
    private setOverlayClass() {
      this.overlayContainer.themeClass = (this.isDarkTheme ? 'dark-theme' : 'light-theme');
    }
    

    (注意,cdk 项目合并到 angular material 项目时,theme-class 被删除。对于较新的项目,您需要直接操作DOMTokenList,例如overlayContainer.getContainerElement().classList.toggle('light-theme')。)

    应用所有这些更改后,现在可以在明暗主题之间切换。

    将您的应用程序嵌套在 sidenav 中并且不使用 sidenav 部分可能会更容易。

    【讨论】:

      【解决方案2】:

      这个聚会很晚了,但是如果您的 Angular 应用程序没有嵌套在父 Material 组件中,它将不会采用您设置的主题属性。正如@RoddyoftheFrozenPass 所提到的,这可以通过将您的应用程序封装在side-nav 之类的材质组件中来解决,但是将mat-app-background 类添加到body 中的index.html 元素会更容易。

      https://material.angular.io/guide/theming

      【讨论】:

        猜你喜欢
        • 2020-11-08
        • 2021-09-01
        • 1970-01-01
        • 2017-12-25
        • 1970-01-01
        • 1970-01-01
        • 2018-05-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多