主题
主题(Themes)用于管理应用程序的可视化展示。
一个主题由一些 CSS 文件和其他资源构成,比如图片、字体等。
Jmix 提供了基于 Vaadin Lumo 主题构建的 jmix-lumo 主题。
使用主题
应用程序主题通过 @Theme 注解提供,注解中使用主题文件夹的名称作为参数。@Theme 注解必须配置在实现了 AppShellConfigurator 接口的类上,通常为主应用程序类。
@Theme(value = "my-theme")
public class MyProjectApplication implements AppShellConfigurator {
...
}
主题的样式版本(variant)可以作为附加参数,例如 dark 或 light。
@Theme(value = "my-theme", variant = "dark")
public class MyProjectApplication implements AppShellConfigurator {
...
}
应用程序主题
在应用程序中,主题的文件夹在 src/main/frontend/themes。使用 Studio 创建的 Jmix 应用程序项目有一个预定义的主题文件夹,其名称与项目本身相同。
示例:
src
└── main
└── frontend
└── themes
└── my-project
├── my-project.css
├── styles.css
├── theme.json
└── view
├── login-view.css
├── main-view-top-menu.css
└── main-view.css
-
my-project- 主题文件夹。其名称作为 @Theme 注解的主题名称。 -
my-project.css- 该主题自定义样式的样式表。 -
styles.css- 主样式表,是该主题样式的入口点。 -
theme.json- 主题配置文件。默认情况下,将 jmix-lumo 定义为父主题。 -
view- 此文件夹包含模板项目提供的登录视图和主视图样式的 CSS 文件。
所有 CSS,包括 CSS 变量值和自定义组件样式,都可以包含在主 styles.css 文件中。然而,默认情况下,该文件仅包含导入指令,实际的 CSS 一般在单独的文件中,更易于管理:
@import url('my-project.css');
@import url('view/main-view.css');
@import url('view/main-view-top-menu.css');
@import url('view/login-view.css');
将项目的 CSS 放在 <theme_name>.css 文件(示例中为 my-project.css)。
|
使用 Vaadin 的在线 Lumo 主题编辑器 可以快速自定义应用程序的主题。 要选择所需的 UI 组件外观,可以使用右侧面板中的控件。然后,点击 Download 并将生成的 CSS 代码( |
可重用主题
应用程序的主题可以打包成独立的 JAR 文件,从而提供给多给项目使用。
主题项目的结构如下:
src
└── main
└── resources
└── META-INF
└── resources
└── themes
└── cobalt
├── styles.css
└── theme.json
-
cobalt- 主题文件夹,也用作主题名称 -
styles.css- 主样式文件。可以包含自定义样式和导入,示例:html { --lumo-border-radius: calc(var(--lumo-size-m) / 2); --lumo-primary-color: rgb(0, 85, 166); --lumo-primary-color-50pct: rgba(0, 85, 166, 0.5); --lumo-primary-color-10pct: rgba(0, 85, 166, 0.1); --lumo-primary-text-color: rgb(0, 85, 166); } -
theme.json- 主题配置文件。建议使用 jmix-lumo 作为父主题,这样自定义的主题可以使用 jmix-lumo 中的默认样式渲染 Jmix UI 组件和视图。示例:{ "parent": "jmix-lumo", "lumoImports":["typography","color","spacing","badge","utility"] }
主题项目中的 build.gradle 文件如下:
plugins {
id 'java'
id 'com.gradle.plugin-publish' version '1.2.1'
}
group = 'com.company'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
maven {
url 'https://global.repo.jmix.io/repository/public'
}
}
dependencies {
implementation 'io.jmix.flowui:jmix-flowui-themes:2.4.0' (1)
}
| 1 | 依赖 jmix-flowui-themes,其中包含 jmix-lumo 主题。 |
在项目中添加了这个主题 JAR 之后,可以使用 JAR 中打包的主题:
@Theme(value = "cobalt")
public class MyProjectApplication implements AppShellConfigurator {
...
}
或者也可以作为项目主题的父主题,示例:
{
"parent": "cobalt",
"lumoImports":["typography","color","spacing","badge","utility"]
}
这样项目中的主题会基于该主题扩展。
可插拔样式
当开发一个 自定义扩展组件 时,可以在 src/main/resources/META-INF/resources/ 目录创建包含自定义样式的文件。如需在最终的应用程序中包含这些样式,可以在 module.properties 文件中定义 jmix.ui.export-styles 属性。该属性的值是 src/main/resources/META-INF/resources/ 下的相对路径,例如,jmix.ui.export-styles = addon-styles/my-addon-styles.css:
.test {
color: red;
}
自定义样式会作为 <style type="text/css"> 添加到 <head> 元素中:
<style type="text/css">
.test {
color: red;
}
</style>
| 这种方式仅适用于少量无法用到特定 UI 组件的样式。例如,扩展组件内视图的 CSS 工具类。 |
运行时更改主题
为了实现在不同的样式版本之间切换,例如 light 和 dark,框架提供了一个与 JavaScript 文件结合使用的静态帮助类。
ThemeUtils 类提供了用于切换样式版本的方法,主要是在 Web Local Storage 中设置样式版本,然后调用 JavaScript 代码使其生效。
例如,可以在主视图中添加一个 dropdownButton 用于切换不同的主题:
<dropdownButton id="themeSwitcher"
text="Theme" icon="ADJUST"
classNames="ms-auto me-m"
dropdownIndicatorVisible="false">
<items>
<actionItem id="systemThemeItem">
<action id="systemThemeAction"
text="System" icon="ADJUST"/>
</actionItem>
<actionItem id="lightThemeItem">
<action id="lightThemeAction"
text="Light" icon="SUN_O"/>
</actionItem>
<actionItem id="darkThemeItem">
<action id="darkThemeAction"
text="Dark" icon="MOON_O"/>
</actionItem>
</items>
</dropdownButton>
@Subscribe("themeSwitcher.systemThemeItem.systemThemeAction")
public void onThemeSwitcherSystemThemeItemSystemThemeAction(final ActionPerformedEvent event) {
ThemeUtils.applySystemTheme();
}
@Subscribe("themeSwitcher.lightThemeItem.lightThemeAction")
public void onThemeSwitcherLightThemeItemLightThemeAction(final ActionPerformedEvent event) {
ThemeUtils.applyLightTheme();
}
@Subscribe("themeSwitcher.darkThemeItem.darkThemeAction")
public void onThemeSwitcherDarkThemeItemDarkThemeAction(final ActionPerformedEvent event) {
ThemeUtils.applyDarkTheme();
}
JavaScript 文件中的代码根据 Web Local Storage 中的值在 HTML 中使用特定的主题版本,并订阅 prefers-color-scheme:在用户通过操作系统设置(例如,浅色或深色模式)或 user agent 设置主题偏好时可以更新主题。
需要在主应用程序类中 import:
@JsModule("./src/theme/color-scheme-switching-support.js")
@SpringBootApplication
public class OnboardingApplication implements AppShellConfigurator {
为不同样式版本自定义组件样式
当允许用户在运行时切换浅色和深色主题时,可能需要为每个主题定义特定的样式,以保证界面适当的对比度和视觉外观。
如需按照当前激活的主题有条件地变更样式,需要在 CSS 中使用 html 元素上的 theme 属性。当主题变化时,Jmix 会向根 html 元素添加相应的 theme 属性。
-
对于浅色,属性为
theme="light"。 -
对于深色,属性为
theme="dark"。
可以在主题的 CSS 文件(例如 my-project.css 或 styles.css)中使用这些选择器,为特定主题覆盖组件样式。
假设有一个自定义样式名为 my-button 的按钮,并且希望在浅色和深色模式下具有不同的文本颜色:
/* Default style for light mode */
vaadin-button.my-button {
color: navy;
}
/* Override for dark mode */
html[theme='dark'] vaadin-button.my-button {
color: lightskyblue;
}
也可以覆盖 Lumo 内置的主题 CSS 属性(变量)。这样可以一次统一修改许多组件的外观。
例如,仅修改深色模式模式中的主色(primary color):
html[theme='dark'] {
--lumo-primary-color: rgb(100, 200, 255);
--lumo-primary-text-color: rgb(100, 200, 255);
}
|