自从传出鸿蒙Next版本不再是安卓套壳的消息之后,就觉得可能安卓和IOS两分天下的局势起码在国内要被打破了,正好由于工作原因得到了一个接触鸿蒙开发的机会,觉得自己还挺感兴趣的,所以就浅浅研究了一下,这里记录一下,在鸿蒙原生stage模型开发的工程中,如何使用iconfont,并且封装一个Iconfont组件,像在web端使用Iconfont一样简单使用
准备Iconfont
相信这一步,做过前端开发的大佬们都门儿清,就不再多说了,总之就是从iconfont网站上获取那个zip压缩包
如何在鸿蒙原生项目中使用iconfont
鸿蒙原生项目中通过文档,了解到提供了注册自定义字体的能力,所以第一步先注册自定义字体
注册自定义字体
在原生SDK中有一个叫@ohos.font
的包提供了一个名为registerFont
的方法,咱们在入口文件src/main/ets/EntryAbility.ets
文件的windowStage.loadContent
回调函数中去注册自定义字体,
在这之前需要先把上一步获取到的zip压缩包解压,在src/main/resource/rawfile
目录下新建一个icon
文件夹放进去。
- 导入模块
import font from '@ohos.font'
- 注册自定义字体
// 注册字体
font.registerFont({
familyName:$r('app.string.icon_font'),//字体名称,在之后的使用中用得到所以放在资源文件string里面,便于引用
familySrc:$rawfile('font/iconfont.ttf')//字体ttf文件路径,直接使用资源获取内置方法获取
})
这里的$r
和$rowfile
分别是鸿蒙开发中获取资源的两种内置方法,在此不做赘述。
- 使用自定义字体
const unicode = String.formCharCode(fontHexValue)//这里的fontHexValue是字体图标的十六进制值
Text(unicode)
.align(Alignment.Center)
.fontSize(20)
.fontFamily('iconFont')
发现这个字体的16进制值信息在zip压缩包中解压出来的iconfont.json
文件中,而我们平时的习惯是通过className使用iconfont,所以这里萌生了封装一个Icon组件的想法,实现在鸿蒙开发中,也能像web中通过className使用iconfont。
封装Icon组件
想要通过使用className使用iconfont,那么就要通过字体图标的className获取到对应图标的十六进制值,思路大概就是这样,具体实现如下
iconfont.json文件内容实例:
{
"id": "3625586",
"name": "喵喵狗狗",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "5387520",
"name": "二维码",
"font_class": "erweima",
"unicode": "eaf1",
"unicode_decimal": 60145
}
]
}
咱们能用到的就是glyphs
这个key下的这个对象数组,其中font_class
对应的就是icon的className,而unicode_decimal
对应的就是icon的十六进制值,思路就是通过className获取到相应图标的十六进制值,带入使用icon的方法中。
- 创建Icon组件
多的不说直接上
Icon.ets
代码:
import { common } from '@kit.AbilityKit';
import { buffer } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
const storage = LocalStorage.getShared();
@Entry(storage) // 为组件注入本地存储,我觉得可以理解为dva中的connect吧
@Component
export struct Icon{
@Prop name:string|number// className,就是从iconfont网站中复制到的那个className
@Prop iconSize:number = 16 // 字体大小
@Prop iconColor:string|Color//字体颜色,不过有些icon不支持自定义颜色
@State @Watch('onIconFontData') iconfontData:IconfontInfo|null = null; //监听字体数据变化
@State unicode:string = ''
aboutToAppear(): void {
this.getIconfontData(); // 加载字体json文件数据
}
onIconFontData(){
if(this.iconfontData){ // 当字体文件加载成功之后重新获取unicode
const unicode = this.getCharCode(this.iconfontData);
this.unicode = unicode;
}
}
getIconfontData(){
let context = getContext(this) as common.UIAbilityContext
try{
let value = context.resourceManager.getRawFileContentSync("font/iconfont.json");
let str = buffer.from(value.buffer).toString()
this.iconfontData = JSON.parse(str) as IconfontInfo;
} catch(error) {
let code = (error as BusinessError).code;
let message = (error as BusinessError).message;
console.error(`getRawFileContentSync failed, error code: ${code}, message: ${message}.`);
}
}
build() {
Text(this.unicode)
.fontFamily($r('app.string.icon_font'))// 注册的自定义字体的name就是registerFont方法中的familyName
.fontSize(this.iconSize)
.fontColor(this.iconColor)
}
getCharCode(iconfontInfo:IconfontInfo){
let unicode_decimal:number =0;
if(this.iconfontData){
const iconfontInfoList:IconfontItem[] = iconfontInfo.glyphs; //获取到icon的信息
const currentItem:IconfontItem|undefined = iconfontInfoList.find((value:IconfontItem)=>{
return 'icon-'+value.font_class===this.name;
})//通过className获取到相应图标的信息
if(currentItem){
unicode_decimal = currentItem.unicode_decimal; //十六进制值
}
}
const result:string = String.fromCharCode(unicode_decimal)//赋值给result
return result
}
}
interface IconfontInfo{
glyphs:IconfontItem[]
}
export interface IconfontItem{
icon_id:string,
name:string,
font_class:string,
unicode:string,
unicode_decimal:number
}
最后
本人就是个前端小菜鸟,也没有研究过安卓原生开发,属于摸着石头过河,如果有说的不对的地方,恳请各位大佬轻点喷