背景颜色无法在Angular材质2中的明暗主题之间切换

Rod*_*eas 4 angular-material2 angular

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

我遵循了主题文档,并创建了两个主题:浅色主题和深色主题。由于我不使用md-sidenav组件,因此将mat-app-background类放在body元素上,该元素应用当前主题的背景色(浅主题为浅灰色,暗主题为深灰色)。

问题在于,当切换主题切换器时(一个简单的按钮可以添加或删除一个类,没有什么花哨的地方,例如此答案),mat-app-background不会更新的背景颜色。

我无法创建成功使用自定义主题的插件,但这是基本要点:

index.html

<body class="mat-app-background">
  <app-root></app-root>
</body>
Run Code Online (Sandbox Code Playgroud)

app.component.html

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

app.component.ts

isDarkTheme: boolean = false;
toggleTheme() { this.isDarkTheme = !this.isDarkTheme; }
Run Code Online (Sandbox Code Playgroud)

theme.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);
}
Run Code Online (Sandbox Code Playgroud)

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

默认的背景色为“ sticks”,不受主题开关的影响。我想念什么?有没有一种方法可以自动更新背景颜色,而无需进行混合/手动重新定义?

(注意:使用直接从有角材料文档中粘贴的主题副本清洁角cli项目。角4.4.4,材料2.0.0-beta.11。)

Rod*_*eas 7

我在角度材料2 github项目的一个封闭问题中找到了间接承认的答案,因此,我将在下面概述发生的情况以及如何应用变通方法来处理此“功能”。

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
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我手动将主题的背景色和前景色分别用作主要元素上的背景色和字体色。重要的是要注意,我将主要元素的总体样式调整为浏览器窗口的全高。

为此,我@include在sass文件中主题类定义中的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);
  }
}
Run Code Online (Sandbox Code Playgroud)

之所以使用sass @at-root指令来main显式仅重新定位元素,是因为主题类还需要应用于CDK覆盖,才能应用于下拉菜单和日期选择器之类的元素。(令人讨厌的,但是在测试版中,这时您必须手动执行。)

为了支持两个不同的主题类,我微调了app.component.html以在“浅色主题”和“深色主题”之间切换:

<main [class.dark-theme]="isDarkTheme" [class.light-theme]="!isDarkTheme">
Run Code Online (Sandbox Code Playgroud)

而且,如前所述,我们还需要重新设置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');
}
Run Code Online (Sandbox Code Playgroud)

(注意,theme-classcdk项目合并到角材料项目中时已删除。对于较新的项目,您需要直接操作DOMTokenList,例如overlayContainer.getContainerElement().classList.toggle('light-theme')。)

通过应用所有这些更改,现在可以在浅色和深色主题之间切换。

将您的应用程序嵌套在sidenav中可能更容易,而不必使用sidenav部分。