HarmonyOS学习路之开发篇—Java UI框架(自定义组件与布局 二)

news/2024/11/22 18:25:38/

自定义布局

当Java UI框架提供的布局无法满足需求时,可以创建自定义布局,根据需求自定义布局规则

常用接口

Component类相关接口

接口名称

作用

setEstimateSizeListener

设置测量组件的侦听器

setEstimatedSize

设置测量的宽度和高度

onEstimateSize

测量组件的大小以确定宽度和高度。

EstimateSpec.getChildSizeWithMode

基于指定的大小和模式为子组件创建度量规范。

EstimateSpec.getSize

从提供的度量规范中提取大小。

EstimateSpec.getMode

获取该组件的显示模式。

arrange

相对于容器组件设置组件的位置和大小

ComponentContainer类相关接口

接口名称

作用

setArrangeListener

设置容器组件布局子组件的侦听器

onArrange

通知容器组件在布局时设置子组件的位置和大小

如何实现自定义布局

使用自定义布局,实现子组件自动换行功能。

自定义布局的使用效果

 1. 创建自定义布局的类,并继承ComponentContainer,添加构造方法。

public class CustomLayout extends ComponentContainer {public CustomLayout(Context context) {this(context, null);}//如需支持xml创建自定义布局,必须添加该构造方法public CustomLayout(Context context, AttrSet attrSet) {super(context, attrSet);}
}

2. 实现ComponentContainer.EstimateSizeListener接口,在onEstimateSize方法中进行测量。

public class CustomLayout extends ComponentContainerimplements ComponentContainer.EstimateSizeListener {...public CustomLayout(Context context, AttrSet attrSet) {...setEstimateSizeListener(this);}@Overridepublic boolean onEstimateSize(int widthEstimatedConfig, int heightEstimatedConfig) {invalidateValues();//通知子组件进行测量measureChildren(widthEstimatedConfig, heightEstimatedConfig);//关联子组件的索引与其布局数据for (int idx = 0; idx < getChildCount(); idx++) {Component childView = getComponentAt(idx);addChild(childView, idx, EstimateSpec.getSize(widthEstimatedConfig));}//测量自身measureSelf(widthEstimatedConfig, heightEstimatedConfig);return true;}private void measureChildren(int widthEstimatedConfig, int heightEstimatedConfig) {for (int idx = 0; idx < getChildCount(); idx++) {Component childView = getComponentAt(idx);if (childView != null) {LayoutConfig lc = childView.getLayoutConfig();int childWidthMeasureSpec;int childHeightMeasureSpec;if (lc.width == LayoutConfig.MATCH_CONTENT) {childWidthMeasureSpec = EstimateSpec.getSizeWithMode(lc.width, EstimateSpec.NOT_EXCEED);} else if (lc.width == LayoutConfig.MATCH_PARENT) {int parentWidth = EstimateSpec.getSize(widthEstimatedConfig);int childWidth = parentWidth - childView.getMarginLeft() - childView.getMarginRight();childWidthMeasureSpec = EstimateSpec.getSizeWithMode(childWidth, EstimateSpec.PRECISE);} else {childWidthMeasureSpec = EstimateSpec.getSizeWithMode(lc.width, EstimateSpec.PRECISE);}if (lc.height == LayoutConfig.MATCH_CONTENT) {childHeightMeasureSpec = EstimateSpec.getSizeWithMode(lc.height, EstimateSpec.NOT_EXCEED);} else if (lc.height == LayoutConfig.MATCH_PARENT) {int parentHeight = EstimateSpec.getSize(heightEstimatedConfig);int childHeight = parentHeight - childView.getMarginTop() - childView.getMarginBottom();childHeightMeasureSpec = EstimateSpec.getSizeWithMode(childHeight, EstimateSpec.PRECISE);} else {childHeightMeasureSpec = EstimateSpec.getSizeWithMode(lc.height, EstimateSpec.PRECISE);}childView.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);}}}private void measureSelf(int widthEstimatedConfig, int heightEstimatedConfig) {int widthSpce = EstimateSpec.getMode(widthEstimatedConfig);int heightSpce = EstimateSpec.getMode(heightEstimatedConfig);int widthConfig = 0;switch (widthSpce) {case EstimateSpec.UNCONSTRAINT:case EstimateSpec.PRECISE:int width = EstimateSpec.getSize(widthEstimatedConfig);widthConfig = EstimateSpec.getSizeWithMode(width, EstimateSpec.PRECISE);break;case EstimateSpec.NOT_EXCEED:widthConfig = EstimateSpec.getSizeWithMode(maxWidth, EstimateSpec.PRECISE);break;default:break;}int heightConfig = 0;switch (heightSpce) {case EstimateSpec.UNCONSTRAINT:case EstimateSpec.PRECISE:int height = EstimateSpec.getSize(heightEstimatedConfig);heightConfig = EstimateSpec.getSizeWithMode(height, EstimateSpec.PRECISE);break;case EstimateSpec.NOT_EXCEED:heightConfig = EstimateSpec.getSizeWithMode(maxHeight, EstimateSpec.PRECISE);break;default:break;}setEstimatedSize(widthConfig, heightConfig);}
}

注意:

  1. 容器类组件在自定义测量过程不仅要测量自身,也要递归的通知各子组件进行测量。
  2. 测量出的大小需通过setEstimatedSize通知组件,并且必须返回true使测量值生效。

3. 测量时,需要确定每个子组件大小和位置的数据,并保存这些数据。

    private int xx = 0;private int yy = 0;private int maxWidth = 0;private int maxHeight = 0;private int lastHeight = 0;// 子组件索引与其布局数据的集合private final Map<Integer, Layout> axis = new HashMap<>();private static class Layout {int positionX = 0;int positionY = 0;int width = 0;int height = 0;}...private void invalidateValues() {xx = 0;yy = 0;maxWidth = 0;maxHeight = 0;axis.clear();}private void addChild(Component component, int id, int layoutWidth) {Layout layout = new Layout();layout.positionX = xx + component.getMarginLeft();layout.positionY = yy + component.getMarginTop();layout.width = component.getEstimatedWidth();layout.height = component.getEstimatedHeight();if ((xx + layout.width) > layoutWidth) {xx = 0;yy += lastHeight;lastHeight = 0;layout.positionX = xx + component.getMarginLeft();layout.positionY = yy + component.getMarginTop();}axis.put(id, layout);lastHeight = Math.max(lastHeight, layout.height + component.getMarginBottom());xx += layout.width + component.getMarginRight();maxWidth = Math.max(maxWidth, layout.positionX + layout.width + component.getMarginRight());maxHeight = Math.max(maxHeight, layout.positionY + layout.height + component.getMarginBottom());}

4. 实现ComponentContainer.ArrangeListener接口,在onArrange方法中排列子组件。

public class CustomLayout extends ComponentContainerimplements ComponentContainer.EstimateSizeListener,ComponentContainer.ArrangeListener {...public CustomLayout(Context context
, AttrSet attrSet
) {...setArrangeListener(this);}@Overridepublic boolean onArrange(int left, int top, int width, int height) {// 对各个子组件进行布局for (int idx = 0; idx < getChildCount(); idx++) {Component childView = getComponentAt(idx);Layout layout = axis.get(idx);if (layout != null) {childView.arrange(layout.positionX, layout.positionY, layout.width, layout.height);}}return true;}
}

5. 在xml文件中创建此布局,并添加若干子组件。

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:orientation="vertical"><!--请根据实际包名与文件路径引入--><com.huawei.harmonyosdemo.custom.CustomLayoutohos:height="match_content"ohos:width="match_parent"ohos:background_element="#555555"><Textohos:height="200"ohos:width="match_parent"ohos:background_element="#727272"ohos:margin="10"ohos:text="match_parent * 200"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/><Textohos:height="100"ohos:width="300"ohos:background_element="#727272"ohos:margin="10"ohos:text="item2"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/><Textohos:height="100"ohos:width="300"ohos:background_element="#727272"ohos:margin="10"ohos:text="item3"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/><Textohos:height="100"ohos:width="300"ohos:background_element="#727272"ohos:margin="10"ohos:text="item4"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/><Textohos:height="100"ohos:width="500"ohos:background_element="#727272"ohos:margin="10"ohos:text="500 * 100"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/><Textohos:height="100"ohos:width="300"ohos:background_element="#727272"ohos:margin="10"ohos:text="item6"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/><Textohos:height="600"ohos:width="600"ohos:background_element="#727272"ohos:margin="10"ohos:text="600 * 600"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/><Textohos:height="100"ohos:width="300"ohos:background_element="#727272"ohos:margin="10"ohos:text="item8"ohos:text_alignment="center"ohos:text_color="white"ohos:text_size="40"/></com.huawei.harmonyosdemo.custom.CustomLayout>
</DirectionalLayout>


http://www.ppmy.cn/news/401251.html

相关文章

一个7×7的卷积核可以用三个3×3的卷积核替代,一个5×5的卷积核可以有两个3×3的卷积核替代

从图上我们可以看出&#xff0c;一个3030的图像经过一个77&#xff08;49个参数&#xff09;的卷积核之后,输出的feature map的大小为2424&#xff0c;与经过三个33卷积核(27个参数)之后的的输出是一致的。经过一个55的卷积核&#xff08;25个参数&#xff09;之后,输出的featu…

【CV】VGG卷积核为什么取3*3 ? VGG使用3*3卷积核的优势是什么?

在VGG中&#xff0c;使用了3个3x3卷积核来代替7x7卷积核&#xff0c;使用了2个3x3卷积核来代替5*5卷积核&#xff0c;这样做的主要目的是在保证具有相同感知野的条件下&#xff0c;提升了网络的深度&#xff0c;在一定程度上提升了神经网络的效果。 比如&#xff0c;3个步长为…

3*3卷积核生成

1.卷积核 由于图像经过卷积操作后会减少两行两列&#xff0c;因此在生成卷积核的时候一般会对图像进行填充&#xff0c;填充的方式有加0&#xff0c;加1和复制边界三种方法。本文将会构建一个可以选择三种填充方式的卷积核模块 2.无填充模式卷积核生成 1.第一行数据写入FI…

关于一个7*7的卷积核可用3个3*3的卷积核代替的理解

最近在看常见网络的结构&#xff0c;比如AlexNet&#xff08;2012&#xff09;&#xff0c;VGG&#xff08;2014&#xff09;,GoogleNet&#xff08;2014&#xff09;&#xff0c;ResNet残差网络&#xff08;2015&#xff09;等等&#xff0c;其中VGG相比AlexNet做出的三个改进…

为什么两层3*3卷积核效果比1层5*5卷积核效果要好?

目录 1、感受野2、2层3 * 3卷积与1层5 * 5卷积3、2层3 * 3卷积与1层5 * 5卷积的计算量比较4、2层3 * 3卷积与1层5 * 5卷积的非线性比较5、2层3 * 3卷积与1层5 * 5卷积的参数量比较 1、感受野 感受野&#xff1a;卷积神经网络各输出特征像素点&#xff0c;在原始图片映射区域大小…

FPGA学习---3.IP核使用,Counter IP核

三 LPM——counter IP核使用 小结&#xff1a;counter&#xff08;IP核&#xff09;cin进位输入&#xff0c;clock时钟信号&#xff0c;cout进位输出&#xff0c;q当前计数值 FPGA设计方式 调用IP核 路径放到prj的ip文件夹下 名字叫counter就行 几位的计数器 计数到多少&a…

核与线程 CPU 4核8线程 的解释

1、物理CPU: 物理CPU就是计算机上实际配置的CPU个数。在linux上可以打开cat /proc/cpuinfo 来查看,其中的physical id就是每个物理CPU的ID,能找到几个physical id就代表计算机实际有几个CPU。 在linux下可以通过指令 grep ‘physical id’ /proc/cpuinfo | sort -u | wc -l …

10.1 LED灯实验(A7核和M4核)

文章目录 LED灯实验分析原理图芯片手册RCC章节GPIO章节 实现代码A7核gpio.hgpio.cmain.c M4核 实验现象 LED灯实验 分析 原理图 LED灯的丝印为LD1&#xff0c;LD2&#xff0c;LD3 通关原理图&#xff0c;可知三盏灯的引脚为LED1&#xff0c;LED2&#xff0c;LED3 引脚写高电平…