动态组件使用指导

← 返回动态组件组件参考 · 全部使用指导

动态组件使用指导

不可见组件:在程序运行时创建组件——按钮、标签、布局……任何组件都可以,拓展组件也可以; 还能设置属性、调用方法、删除、调整顺序、移到别的布局,或用 JSON 模板一次创建一批。 适合组件个数由数据决定的界面:问卷的题目、购物车的商品、聊天气泡等。

本组件内化自第三方拓展 DynamicComponents(作者 Yusuf Cihan,MIT 许可证),积木与原拓展一致。

先看是不是用布局列表框更合适:只是「一行一条数据」的列表或网格,用布局列表框更省事, 数据绑定、点击事件都是现成的,而且滚动时组件会复用,数据再多也不卡。

要点

  • 每个动态组件创建时给一个编号(文本,不能重复),之后用编号取回、删除它;不关心编号时用生成编号(GenerateID)。
  • 组件只能创建在布局(或画布)里,不能直接创建在屏幕上,所以先在设计器里放一个空的布局当容器。
  • 组件类型写英文类型名,如 Button、Label、HorizontalArrangement;也可以传一个现有组件(创建同类型的新组件,拓展组件用这种办法)。
  • 动态组件的事件用「任意组件」积木接:在代码块编辑器左侧「任意组件」里拖出如「任意按钮.被点击」, 事件参数 component 就是被点的那个按钮,再用取编号(组件)(GetId)知道是哪一个。

快速上手:按数据生成一排按钮

设计器里放一个垂直布局 垂直布局_容器:

各案例独立使用;组合到同一屏幕时,将同名事件的处理合并到一个事件积木中。

global fruits = ["苹果", "香蕉", "橙子"]

when Screen1.Initialize() {
  foreach name in fruits {
    动态组件1.Create(垂直布局_容器, "Button", name)
    动态组件1.SetProperty(动态组件1.GetComponent(name), "Text", join("买", name))
  }
}

when 按钮_清空.Click() {
  foreach name in fruits {
    动态组件1.Remove(name)
  }
}

这些按钮是运行时才有的,设计器里没有它们的「被点击」积木,用「任意按钮.被点击」接事件, component 就是被点的那个按钮,用取编号(组件)(GetId)知道是哪一个(这里编号就是水果名):

when any Button.Click(component, notAlreadyHandled) {
  var fruit = 动态组件1.GetId(component)
  if fruit != "" {
    标签1.Text = join("已加入购物车:", fruit)
    any Button(component).Enabled = false
  }
}

用模板一次创建一张卡片

模板是 JSON:components 里每个组件写 id、type、properties,可以用 components 嵌套子组件; keys 列出占位符,{名字} 会被参数列表里对应的值替换:

when 按钮_添加.Click() {
  动态组件1.Schema(垂直布局_容器, 文本输入框_模板.Text, [文本输入框_标题.Text])
}

文本输入框_模板 里的模板示例:

{
  "metadata-version": "1",
  "name": "card",
  "keys": ["title"],
  "components": [
    {"id": "card_{title}", "type": "HorizontalArrangement", "properties": {"BackgroundColor": "&HFFE3F2FD"},
     "components": [
       {"id": "label_{title}", "type": "Label", "properties": {"Text": "{title}", "FontSize": "18"}}
     ]}
  ]
}

搭建与测试

在设计器拖入本组件和案例涉及的按钮、标签、布局等组件,按案例中的名称重命名。先运行最小案例,确认事件返回,再增加业务逻辑。示例中的素材先上传到项目,服务器地址、令牌、文件路径换成自己的值。

可见组件需要有非零宽高;不可见工具组件必须由属性或方法启动。设计器展示样式不等于运行时已加载数据或绑定目标。联机测试应使用包含本组件的 AI 伴侣;涉及系统入口或权限的行为还要编译安装后验证。

属性、方法与事件速查

完整参数类型、默认值和平台说明见组件参考。下表按调用入口列出用途;有完成事件的方法在事件中读取结果。

入口 用途
版本(Version) 上游拓展的版本号(11),与原拓展一致。
版本名称(VersionName) 上游拓展的版本名(2.3.1),与原拓展一致。
修改编号(编号,新编号)(ChangeId) 把已创建组件的编号改成新编号(旧编号必须存在、新编号必须未被使用)。注意:所有包含旧编号的编号都会被替换,如把 Timmy 改名时 Timmy-truck 也会变。
创建(所在布局,组件类型,编号)(Create) 在指定布局(或画布)里创建一个新组件,并给它一个编号供以后引用;创建完成触发「组件已创建」。componentName 可以是组件类型名(如 Button)、一个现有组件(创建同类型的新组件,拓展也可以),或完整类名。不能直接创建在屏幕上,要先放一个布局。
临时创建(所在布局,组件类型)(CreateEphemeral) 在指定布局(或画布)里创建一个新组件并返回,不登记编号(用编号相关的积木找不到它)。不能直接创建在屏幕上。
立即创建(所在布局,组件类型,编号)(CreateSync) 立即在指定布局(或画布)里创建一个新组件并直接返回它(同步),同时登记编号;编号留空时自动生成。
生成编号(GenerateID) 生成一个随机的唯一编号(UUID),不关心编号时可用它创建组件。
取组件(编号)(GetComponent) 按编号取回组件;找不到时返回空文本。
组件元数据(组件)(GetComponentMeta) 取指定组件的元数据(类型、类名、分类、描述、版本等),结果是字典。
事件元数据(组件)(GetEventMeta) 取指定组件全部事件的元数据,结果是字典。
方法元数据(组件)(GetFunctionMeta) 取指定组件全部方法的元数据,结果是字典。
取编号(组件)(GetId) 取组件的编号(取回组件的反操作);不是本组件创建的返回空文本。
取位置(组件)(GetOrder) 取组件在所在布局里的位置,从 1 开始;没有所在布局时返回 0。
取属性(组件,名称)(GetProperty) 按属性名读组件的属性值(相当于属性读取积木),值为空时返回空文本。
属性元数据(组件)(GetPropertyMeta) 取指定组件全部属性的元数据和当前值,结果是字典。
调用方法(组件,名称,参数列表)(Invoke) 按方法名调用组件的方法,parameters 是参数列表,返回方法的结果(为空时返回空文本)。不需要结果时用「执行但忽略结果」积木包住。
是否动态创建(组件)(IsDynamic) 组件是否由本组件动态创建。
最近用的编号(LastUsedID) 最近一次创建组件用的编号。
移到布局(布局,组件)(Move) 把组件移到另一个布局里(排在最后)。
按编号删除(编号)(Remove) 按编号删除组件,编号随之注销,可以再用来创建新组件。
删除组件(组件)(RemoveComponent) 从屏幕上删除一个组件(设计时放的组件也可以);如果是动态创建的,同时注销它的编号。
替换编号(编号,新编号)(ReplaceId) 把一个编号精确替换为新编号(只改这一个)。
按模板创建(所在布局,模板,参数列表)(Schema) 按 JSON 模板批量创建组件(可嵌套),模板里的占位符用 parameters 列表的值替换;全部创建完触发「模板已创建」。模板格式见文档。
设置位置(组件,索引)(SetOrder) 设置组件在所在布局里的位置,从 1 开始;设为 0 移到最后。
批量设属性(组件,属性字典)(SetProperties) 用字典一次设置多个属性:键是属性名,值是属性值。
设属性(组件,名称,值)(SetProperty) 按属性名设置组件的属性(相当于属性设置积木),只能在设计器里设的属性也可以。
全部编号(UsedIDs) 本组件创建的全部组件编号(列表)。
组件已创建(组件,编号,类别)(ComponentBuilt) 组件创建完成后触发:component 是新组件,id 是它的编号,type 是组件类型名。
模板已创建(名称,参数列表)(SchemaCreated) 用「按模板创建」创建完一批组件后触发:name 是模板名,parameters 是传入的参数列表。

常见问题与验收

检查项 操作与预期
初始化 对照案例检查是否已经调用加载、注册、连接或显示方法;仅拖入组件不会替你执行这些步骤。
结果返回 将成功事件和失败事件都接到标签,记录事件参数;异步操作完成前不读取结果属性。
输入配置 检查素材名大小写、网址是否为直接资源地址、文件是否存在、编号和索引是否在范围内。
平台与权限 按组件参考中的平台说明测试;授权被拒绝时应有明确提示,不继续假定操作成功。
最小案例 先验证页面中的最小案例,再验证第二个场景;重复操作、取消、返回屏幕后结果应符合事件说明。

完整 .aia 源码与操作指导

下载 .aia 源码

用动态组件搭建一份可填写和保存的巡检表单。上方是真实动态输入框和设备资料卡,主界面只保留创建、保存、查看记录与添加资料卡;编号管理和接口细节在“表单管理与高级设置”中。

巡检表单与设备资料卡

导入方法:项目 → 导入项目(.aia)→ 选择下载的 .aia 源码文件。 创建可实际填写的巡检输入框,保存内容和时间,重新打开查看上次记录;设备资料卡按模板添加并可点击查看详情。编号、移动、排序等管理功能收进高级设置。 覆盖检查 30/30,正式编辑器首次载入和保存重开均零错误,后台导入与安装包编译通过。真机/伴侣尚未实测。

先运行这个实际案例

  1. 点击“创建巡检输入框”,在上方输入框填写记录,再点“保存当前巡检记录”。
  2. 重新打开案例,点“查看上次保存记录”,核对保存时间和内容。动态界面重新创建,本地记录保留。
  3. 输入资料标题,点“添加设备资料卡”,点击卡片按钮查看实际编号和文字。
  4. 打开高级设置再学习动态按钮、移动、排序、改名和删除。

高级面板默认收起,原完整功能入口仍可打开使用。源码为中文app.json和Screen1.ai-blocks,AIA包含全部素材和完整积木。正式编辑器、后台导入及安装包检查以更新后的最终归档报告为准;真机/伴侣尚未实测。

API / 功能 操作入口 预期结果
Thread、Version、VersionName 设计器Main;启动和读取 Android使用Main时立即创建,鸿蒙目前同步;版本实际读取
CreateSync、Create、CreateEphemeral、GenerateID、ComponentBuilt 同步输入框、普通按钮、临时标签 真实动态控件;普通按钮用自动编号,事件来自实际创建;临时标签不登记业务编号
GetComponent、GetId、IsDynamic、LastUsedID、UsedIDs、GetProperty 读取区 实际组件/业务编号/文字;临时标签的IsDynamic按登记语义返回假,并非不存在
SetProperty、SetProperties、Invoke 设置、批量、调用 实际文字、字号、背景;调用真实MoveCursorToEnd,无返回结果不能当成功事件
ChangeId、ReplaceId 新编号输入后分别点对应按钮 ChangeId替换包含旧编号的子编号,ReplaceId只改当前编号;组件本身仍在,业务编号读回变化
Move、SetOrder、GetOrder 移到另一栏;先创建普通按钮再移到第一项 真实布局移动与1起始顺序;零或越界在鸿蒙移到末尾,不用于本案例
GetComponentMeta、GetEventMeta、GetFunctionMeta、GetPropertyMeta 元数据 实际运行时描述字典,组件类型不同内容不同
Remove、RemoveComponent 按编号删除输入框、按组件删除临时标签 控件真实消失,编号列表读回;不删除其他案例或保存数据
Schema、SchemaCreated 参数模板卡片、非法空参数 真实嵌套布局、标签、按钮;实际模板事件;参数个数不匹配显示错误且不新增卡片
任意组件点击、输入与恢复 动态按钮、输入框实际输入、读取、重开 动态按钮详情读实际编号;重新打开清空本次动态界面,无虚构持久化

所有返回值均用于界面反馈,错误由底部错误区展示。设计器采用明确非默认配置,初始化与界面同步。API 覆盖检查按最终 AIA 检查方法、事件、属性读取与设置及设计器配置,不能替代真实设备验证。

文档反馈