HarmonyOS 自定义UI之Component属性值获取 原创 精华
作者:刘清华
当系统自带的Component不能满足我们项目UI需求时,就需要自定义Component,这时就不可避免的会使用自定义属性,鸿蒙自定义属性不需要预先定义<自定义属性/>
标签。而是直接在布局中使用这个自定义属性,在使用的时候只需要在根布局上加上下面这个命名空间
<DirectionalLayout
...
xmlns:app="http://schemas.huawei.com/apk/res/ohos"
...
>
自定义属性
鸿蒙自定义属性值通过attrSet.getAttr(name).get().getXXX()
API获得,能够读取一些基本数据类型的数据,但是有一些值无法直接读取比如ResourceId、StringArray等,导致使用非常不方便,因此写了这个属性值获取工具类 ,方便开发者获取各种不同类型的属性值。
自定义的Component: 包含高度尺寸、字体大小、字体、字符串数组、布局id、背景图片属性。
<cn.carbswang.ohos.attrtool.CustomComponent
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="#cccccc"
app:itemHeight="55vp"
app:itemTextFont="myfont.ttf"
app:itemTextFontSiz="15fp"
app:itemArray="$strarray:hour"
app:itemLayout="$layout:ability_two"
app:itemBackground="$color:red" />
获取自定义属性值
自定义的CustomComponent
/**
* 自定义Component
*
* @since 2021-08-24
*/
public class CustomComponent extends Component {
public CustomComponent(Context context, AttrSet attrSet) {
super(context, attrSet);
init(context, attrSet);
}
/**
* 初始化 属性
* @param context 上下文
* @param attrSet 属性集
*/
private void init(Context context, AttrSet attrSet) {
int itemHeight = AttrTool.getDimension(attrSet, "itemHeight", AttrTool.vp2px(context, 50));
Font itemTextFont = AttrTool.getFont(context, attrSet, "itemTextFont");
int itemTextFontSiz = AttrTool.getDimension(attrSet, "itemTextFontSiz", AttrTool.fp2px(context, 15));
String[] itemArray = AttrTool.getStringArray(context, attrSet, "itemArray");
int itemLayout = AttrTool.getResourceId(attrSet, "itemLayout", 0);
Element itemBackground = AttrTool.getElement(attrSet, "itemBackground");
System.out.println("itemHeight: " + itemHeight);
if (itemTextFont != null) {
System.out.println("itemTextFont: " + itemTextFont);
}
System.out.println("itemTextFontSiz: " + itemTextFontSiz);
if (itemArray != null) {
System.out.println("itemArray: " + Arrays.toString(itemArray));
}
System.out.println("itemLayout: " + itemLayout);
System.out.println("itemBackground: " + itemBackground);
}
打印输出如下:
08-24 16:54:29.382 11212-11212/cn.carbswang.ohos.attrtool I System.out: itemHeight: 165
08-24 16:54:29.382 11212-11212/cn.carbswang.ohos.attrtool I System.out: itemTextFont: ohos.agp.text.Font@3a276dc
08-24 16:54:29.382 11212-11212/cn.carbswang.ohos.attrtool I System.out: itemTextFontSiz: 45
08-24 16:54:29.382 11212-11212/cn.carbswang.ohos.attrtool I System.out: itemArray: [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
08-24 16:54:29.382 11212-11212/cn.carbswang.ohos.attrtool I System.out: itemLayout: 16777227
08-24 16:54:29.382 11212-11212/cn.carbswang.ohos.attrtool I System.out: itemBackground: ohos.agp.components.element.ShapeElement@68bd3e5
ResourceId属性值获取
鸿蒙attrSet.getAttr(name).get()
并没有对应的API用于获取布局id,需要先获取String值:$layout:16777227,分号的后面代表布局id,我们只要截取分号后的字符串就行。
/**
* 获取资源Id
*
* @param attrSet 属性集
* @param name 属性name
* @param defValue 默认值
* @return 返回资源Id
*/
public static int getResourceId(AttrSet attrSet, String name, int defValue) {
if (!attrSet.getAttr(name).isPresent()) {
return defValue;
}
String value = attrSet.getAttr(name).get().getStringValue();
if (value.startsWith("$layout")) {
try {
return Integer.parseInt(value.substring(value.indexOf(":") + 1));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
return defValue;
}
StringArray属性值获取
鸿蒙attrSet.getAttr(name).get()
也没有对应的API用于获取StringArray字符串数组,需要先获取String值:$strarray:hour,分号的后面代表资源名称,我们只要截取这个再拼接Strarray_+hour
,
再通过类加载器得到ResourceTable资源类,里面有所有资源id。再反射得到Strarray_+hour
资源id,有了资源id就可以得到字符串数组了。
/**
* 获取字符串数组
*
* @param context 上下文
* @param attrSet 属性集
* @param name 属性name
* @return 返回字符串数组
*/
public static String[] getStringArray(Context context, AttrSet attrSet, String name) {
String str = getString(attrSet, name, "");
if (str.startsWith("$strarray:")) {
try {
String name2 = str.split(":")[1];
Class<?> aClass = context.getClassloader().loadClass(context.getBundleName() + ".ResourceTable");
Field field = aClass.getField("Strarray_" + name2);
if (field != null) {
int id = field.getInt("Strarray_" + name2);
return context.getResourceManager().getElement(id).getStringArray();
}
} catch (NoSuchFieldException | IllegalAccessException | NotExistException | WrongTypeException | IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
鸿蒙自定义字体获取
首先字体文件放在resources/rawfile/xxx.ttf
路径下,再通过new Font.Builder(file).build()
构建字体文件,就可以用于Text
控件了。
/**
* 获取字体
*
* @param context 上下文
* @param attrSet 属性集
* @param name 属性name
* @return 返回Font
*/
public static Font getFont(Context context, AttrSet attrSet, String name) {
String fileName = getString(attrSet, name, "");
return getFontFromRawFile(context, fileName);
}
/**
* 从resources/rawfile 读取字体文件
*
* @param context 上下文
* @param fileName 字体文件名称
* @return Font
*/
public static Font getFontFromRawFile(Context context, String fileName) {
String path = "resources/rawfile/" + fileName;
ResourceManager resManager = context.getResourceManager();
RawFileEntry rawFileEntry = resManager.getRawFileEntry(path);
Resource resource = null;
try {
resource = rawFileEntry.openRawFile();
} catch (IOException e) {
e.printStackTrace();
}
if (resource != null) {
File file = new File(context.getCacheDir(), fileName);
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
int index;
byte[] bytes = new byte[1024];
while ((index = resource.read(bytes)) != -1) {
outputStream.write(bytes, 0, index);
outputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
resource.close();
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Font.Builder builder = new Font.Builder(file);
return builder.build();
}
return null;
}
Element属性值获取
鸿蒙的Element根据不同的资源实例化成不同的子对象,颜色值被实例化成ShapeElement,图片资源被实例化成PixelMapElement。
/**
* 获取Element
*
* @param attrSet 属性集
* @param name 属性name
* @return 返回Element
*/
public static Element getElement(AttrSet attrSet, String name) {
if (attrSet.getAttr(name).isPresent()) {
return attrSet.getAttr(name).get().getElement();
}
return null;
}
更多原创内容请关注:开鸿 HarmonyOS 学院
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
小蒙这名字很亲切呀,支持一波。