Angular 材质 2 中的背景颜色不会在明暗主题之间切换 [英] Background color does not switch between light and dark themes in Angular material 2

查看:24
本文介绍了Angular 材质 2 中的背景颜色不会在明暗主题之间切换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an Angular 4 app using Material 2 (current version, 2.0.0-beta.11).

我已按照 文档 进行主题化并创建两个主题,一个浅色主题和一个深色主题.由于我不使用 md-sidenav 组件,我将 mat-app-background 类放在 body 元素上,它应用当前主题的背景颜色(浅灰色代表浅色主题,并且深色主题的深灰色.)

I have followed the documentation for theming and created two themes, a light theme and a dark theme. Since I do not use a md-sidenav component, I have put the mat-app-background class on the body element, which applies the current theme's background color (a light grey for a light theme, and a dark grey for a dark theme.)

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

The problem is that when my theme switcher is toggled (a simple button that adds or removes a class, nothing fancy, like this answer), the background color from the mat-app-background is not updated.

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

I am unable to create a plunker that successfully uses custom themes, but here's the basic gist:

index.html

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

app.component.html

app.component.html

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

app.component.ts

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);
}

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

When I click the button, it successfully toggles the theme: the class is applied, the button changes color from the light theme primary color to the dark theme primary color. But the background color remains the light theme's background color.

默认背景颜色固定"并且不受主题切换的影响.我错过了什么?有没有办法让背景颜色自动更新而无需混合/手动重新定义?

The default background color "sticks" and is unaffected by the theme switch. What am I missing? Is there a way for the background color to be automatically updated without a mixin/manual redefinition?

(注意:干净的 angular cli 项目,使用直接从 angular 材料文档中复制粘贴的主题.Angular 4.4.4,材料 2.0.0-beta.11.)

(Note: clean angular cli project, using the themes copy pasted directly from the angular material documentation. Angular 4.4.4, material 2.0.0-beta.11.)

推荐答案

我找到了答案 在 angular material 2 github 项目的一个封闭问题中间接承认,因此我将在下面概述正在发生的事情以及我如何应用变通方法来处理此功能".

I found the answer indirectly acknowledged in a closed issue on the angular material 2 github project, so I'll outline below what is going on and how I applied a workaround to handle this "feature."

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

That is to say, if you have your entire app nested inside of a md-sidenav (or mad-sidenav) component, you're fine since that's a Material component. But if you're not using that and instead go the route of applying mat-app-background as indicated in the documentation, you only get the initial-applied theme's styling.

为了使非材料组件元素(例如常规 html 元素)能够正常工作,您需要应用 scss mixin 来应用这些样式.此外,您需要手动设置所有非材料组件元素的样式.

In order to get this working for non-material-component elements (eg. regular html elements), you need to apply a scss mixin in order to apply these styles. Furthermore, you'll need to style all of your non-material-component elements manually.

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

To begin, I updated my theme.scss to include a mixin that targeted the main element. As in my initial post, the main wraps the entire app.component and is the class where I apply the dark-theme class.

@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
  }
}

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

Here I'm manually applying the theme's background color and foreground color as the background and font color, respectively, on the main element. It's important to note that I've tweaked the general styling of my main element to be the full height of the browser window.

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

To apply this, I @include the mixin within the themed class definition in the sass file. Importantly, I also had to assign my default theme to its own class; otherwise the default would always trigger the mixin and overwrite the active theme's styling with the default's.

// 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叠加以应用于下拉菜单和日期选择器等元素.(令人讨厌,但在测试版的这一点上,您必须手动完成.)

The reason I used the sass @at-root directive to re-target only the main element explicitly is because the themed class also needs to be applied to the CDK overlay in order to apply to elements like drop downs and the date picker. (Obnoxious, but at this point in the beta you have to do it manually.)

为了支持两种不同的主题类,我对 app.component.html 进行了微调,以在light-theme"和dark-theme"之间切换:

To support the two different theme classes, I adjusted the app.component.html trivially to toggle between 'light-theme' and 'dark-theme':

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

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

And, as mentioned, we need to also re-theme the CDK overlay, so I updated to the app.component.ts file to add the appropriate theme class to that as well:

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').)

(Note, theme-class was removed when the cdk project was merged into the angular material project. For newer projects, you need to manipulate the DOMTokenList directly, eg. overlayContainer.getContainerElement().classList.toggle('light-theme').)

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

With all of these changes applied, toggling between light and dark themes now works.

将您的应用嵌套在 sidenav 中而不使用 sidenav 部分可能会更容易.

It might just be easier to nest your app in a sidenav and just not use the sidenav part.

这篇关于Angular 材质 2 中的背景颜色不会在明暗主题之间切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆