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

查看:80
本文介绍了背景颜色无法在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.)

问题是,当切换主题切换器时(一个简单的按钮可以添加或删除类,没有什么花哨的地方,

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.

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

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

index.html

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

theme.scss

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

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

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?

(注意:使用直接从有角材料文档中粘贴的主题副本清洁角cli项目.Angular4.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.)

推荐答案

我找到了答案

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)组件中,则可以,因为那是Material组件.但是,如果您不使用它,而是按照文档中的说明使用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才能应用这些样式.此外,您需要手动设置所有非材料成分元素的 all 样式.

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.

要应用此方法,我在sass文件中的主题类定义中混合.重要的是,我还必须将默认主题分配给自己的班级.否则,默认设置将始终触发混合,并使用默认设置覆盖活动主题的样式.

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覆盖,以便应用于下拉菜单和日期等元素选择器. (令人讨厌,但是在Beta版中,您必须手动执行此操作.)

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以在浅色主题"和深色主题"之间切换:

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项目合并到角材料项目中时,theme-class被删除.对于较新的项目,您需要操纵

(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天全站免登陆