使用字体库的图标
为了对主题进行更深度的定制化,可能需要创建一些图标并将图标嵌入字体库,或者使用外部的图标字体库。作为示例,我们使用 Brands 样式的 Font Awesome 5 库。
-
为新的图标创建枚举类,实现
com.vaadin.server.FontIcon
接口:public enum FontAwesome5Brands implements FontIcon { JAVA(0XF4E4); public static final String FONT_FAMILY = "FontAwesome5Brands"; private final int codepoint; FontAwesome5Brands(int codepoint) { this.codepoint = codepoint; } @Override public String getFontFamily() { return FONT_FAMILY; } @Override public int getCodepoint() { return codepoint; } @Override public String getHtml() { return GenericFontIcon.getHtml(FONT_FAMILY, codepoint); } @Override public String getMIMEType() { throw new UnsupportedOperationException(FontIcon.class.getSimpleName() + " should not be used where a MIME type is needed."); } public static FontAwesome5Brands fromCodepoint(final int codepoint) { for (FontAwesome5Brands f : values()) { if (f.getCodepoint() == codepoint) { return f; } } throw new IllegalArgumentException( "Codepoint " + codepoint + " not found in FontAwesome 5"); } }
-
将新样式添加至 自定义主题。我们建议在自定义主题的主目录创建一个子目录
fonts
,例如,themes/helium-extended/fonts
。然后将样式和字体文件放在各自的子目录中,例如,fonts/fontawesome
。字体文件支持下列扩展名:
-
.eot
, -
.svg
, -
.ttf
, -
.woff
, -
.woff2
。
Brands 样式的
fontawesome
字体由 5 个文件组成:fa-brands-400.eot
、fa-brands-400.svg
、fa-brands-400.ttf
、fa-brands-400.woff
、fa-brands-400.woff2
。如需使用其他样式(Solid、Regular 等),则需要为每一种样式定义唯一的类名。同时,也需要分别实现
IconSets
和Providers
。 -
-
创建一个包含
@font-face
样式的文件和具有图标样式的 CSS 类。下面是fontawesome5.scss
文件的示例,其中FontAwesome5Brands
CSS 类名对应于FontIcon.getFontFamily()
方法返回的值:@mixin font-icon-style { speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* FontAwesome 5 Brands */ @mixin font-awesome-5-brands-style { font-family: 'FontAwesome5Brands'; @include font-icon-style; } @font-face { font-family: 'FontAwesome5Brands'; src: url('fa-brands-400.eot?hwgbks'); src: url('fa-brands-400.eot?hwgbks#iefix') format('embedded-opentype'), url('fa-brands-400.ttf?hwgbks') format('truetype'), url('fa-brands-400.woff?hwgbks') format('woff'), url('fa-brands-400.svg?hwgbks#icomoon') format('svg'); font-weight: normal; font-style: normal; } .FontAwesome5Brands { @include font-awesome-5-brands-style; }
-
在自定义主题的
helium-extended.scss
或其他文件中,引入该字体样式文件:@import "fonts/fontawesome5/fontawesome5";
-
然后,创建一个新的 图标集,这是一个实现了
Icons.Icon
接口的枚举:public enum FontAwesome5Icon implements Icons.Icon { JAVA("font-awesome5-brands-icon:JAVA"); protected String source; FontAwesome5Icon(String source) { this.source = source; } @Override public String source() { return source; } @Override public String iconName() { return name(); } }
-
创建新的
IconProvider
。为了管理自定义的图标集,Jmix 框架提供了
IconProvider
和IconResolver
。IconProvider
是一个标记接口,可以用图标路径提供资源(com.vaadin.server.Resource
)。IconResolver
bean 会获取所有实现了IconProvider
接口的 bean,并与之交互找到可以提供对应图标资源的类。因此,需要自己实现
IconProvider
:@Order(10) @Component("sample_FontAwesome5BrandsIconProvider") public class FontAwesome5BrandsIconProvider implements IconProvider { public static final String FONT_AWESOME_5_BRANDS_PREFIX = "font-awesome5-brands-icon:"; private final Logger log = LoggerFactory.getLogger(FontAwesome5BrandsIconProvider.class); @Override public Resource getIconResource(String iconPath) { Resource resource = null; iconPath = iconPath.split(":")[1]; try { resource = ((Resource) FontAwesome5Brands.class .getDeclaredField(iconPath) .get(null)); } catch (IllegalAccessException | NoSuchFieldException e) { log.warn("There is no icon with name {} in the FontAwesome5Brands icon set", iconPath); } return resource; } @Override public boolean canProvide(String iconPath) { return !Strings.isNullOrEmpty(iconPath) && iconPath.startsWith(FONT_AWESOME_5_BRANDS_PREFIX); } }
这里,我们使用
@Order
注解显式地为这个 bean 指定了顺序。 -
在
application.properties
文件注册图标集:jmix.ui.icons-config = ui.ex1.icon.FontAwesome5Icon
现在可以直接在界面 XML 描述中通过类和枚举值元素的方式使用新图标:
<button icon="font-awesome5-brands-icon:JAVA"/>
或者在 Java 控制器内:
cIconBtn.setIconFromSet(FontAwesome5Icon.JAVA);
图标覆盖
图标集的机制使得我们可以用其他集合中的图标覆盖某些图标。需要使用相同的图标(选项)创建并注册一个新的图标集(枚举),但是使用不同的图标路径(source
)。下面的示例中,用新创建的 MyIcon
枚举覆盖了标准 JmixIcon
图标集中的图标。
-
创建新的图标集
public enum NewIcon implements Icons.Icon { OK("classpath:/icon/custom-ok.png"); }
-
在
application.properties
注册新图标集:jmix.ui.icons-config = ui.ex1.icon.NewIcon
然后,OK 会使用新的图标而非默认自带的:
@Autowired
private Icons icons;
@Subscribe
protected void onInit(InitEvent event) {
okIconBtn.setIcon(icons.get(JmixIcon.OK));
}
如果不需要使用重新定义,仍然可以通过使用图标源而不是选项名称来使用标准图标:
<button caption="Custom" icon="font-icon:CHECK"/>
或者
oIconBtn.setIcon(JmixIcon.OK.source());