Summary
Kuikly 自定义 View 开发助手。指导如何创建自定义 UI 组件,将原生 View 暴露给 Kuikly 侧使用。覆盖完整开发流程:Kuikly 侧组件定义、各平台 Native 侧实现(Android/iOS/鸿蒙ArkTS/H5/小程序)及使用。当用户需要自定义扩展 UI 组件时使用。
tencent-tds/kuiklyui-ai
Kuikly 自定义 View 开发助手。指导如何创建自定义 UI 组件,将原生 View 暴露给 Kuikly 侧使用。覆盖完整开发流程:Kuikly 侧组件定义、各平台 Native 侧实现(Android/iOS/鸿蒙ArkTS/H5/小程序)及使用。当用户需要自定义扩展 UI 组件时使用。
npx skills add tencent-tds/kuiklyui-ai --skill kuikly-expand-view
Kuikly 自定义 View 开发助手。指导如何创建自定义 UI 组件,将原生 View 暴露给 Kuikly 侧使用。覆盖完整开发流程:Kuikly 侧组件定义、各平台 Native 侧实现(Android/iOS/鸿蒙ArkTS/H5/小程序)及使用。当用户需要自定义扩展 UI 组件时使用。
Related neighbors and high-traction skills in the same topics — useful to compare before installing.
Guidance for distinctive, intentional visual design when building new UI or reshaping an existi…
866.4K installsBrowser automation CLI for AI agents. Use when the user needs to interact with websites, includ…
810.4K installsReview UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "chec…
617.3K installsBuild, deploy, evaluate, optimize, fine-tune, and manage Microsoft Foundry agents, models, and …
576.5K installsDebug Azure production issues on Azure using AppLens, Azure Monitor, resource health, and safe …
568.9K installsOther skills from tencent-tds/kuiklyui-ai · top by installs.
npx skills add tencent-tds/kuiklyui-ai
Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.
main
Files included with this skill beyond the listing page.
SKILL.md
11,475 B
SUMMARY.md
4,412 B
viewName 关联。viewName() 返回值必须与 Native 侧注册的名字完全一致。setProp(propKey, propValue) 接收 Kuikly 侧设置的属性和事件。call(method, params, callback) 响应 Kuikly 侧的方法调用。Use this workflow to create a expand View on the Kuikly (Kotlin) side.
Kuikly 组件由四部分组成:
viewName: 组件对应到原生组件的名字Attr: 组件的属性,用于指定该组件含有哪些属性Event: 用于接收来自原生组件发送的事件方法: 组件本身支持的方法,最终实现在原生侧步骤:
DeclarativeBaseView<XxxAttr, XxxEvent>viewName()、createAttr()、createEvent() 方法Attr 类继承 Attr,添加属性方法Event 类继承 Event,添加事件注册方法import com.tencent.kuikly.core.base.DeclarativeBaseView
class MyImageView : DeclarativeBaseView<MyImageAttr, MyImageEvent>() {
override fun createAttr(): MyImageAttr {
return MyImageAttr()
}
override fun createEvent(): MyImageEvent {
return MyImageEvent()
}
// 返回 Native 侧注册的组件名
override fun viewName(): String {
return "HRImageView"
}
// 组件方法(可选),实际实现在 Native 侧
fun test() {
performTaskWhenRenderViewDidLoad {
renderView?.callMethod("test", "params")
}
}
}
Attr 表示组件支持的属性集。
import com.tencent.kuikly.core.base.Attr
class MyImageAttr : Attr() {
/**
* 设置图片数据源
* @param src 图片 URL
* @return this(支持链式调用)
*/
fun src(src: String): MyImageAttr {
"src" with src // 将属性透传给原生组件
return this
}
/**
* 设置占位图
*/
fun placeholder(url: String): MyImageAttr {
"placeholder" with url
return this
}
/**
* 设置缩放模式
*/
fun scaleType(type: String): MyImageAttr {
"scaleType" with type
return this
}
}
Event 表示组件支持的事件。
import com.tencent.kuikly.core.base.event.Event
import com.tencent.kuikly.core.nvi.serialization.json.JSONObject
class MyImageEvent : Event() {
/**
* 图片加载成功回调
*/
fun loadSuccess(handler: (LoadSuccessParams) -> Unit) {
register(LOAD_SUCCESS) {
handler(LoadSuccessParams.decode(it))
}
}
/**
* 图片加载失败回调
*/
fun loadError(handler: (LoadErrorParams) -> Unit) {
register(LOAD_ERROR) {
handler(LoadErrorParams.decode(it))
}
}
companion object {
const val LOAD_SUCCESS = "loadSuccess"
const val LOAD_ERROR = "loadError"
}
}
// 事件参数解析类
data class LoadSuccessParams(
val src: String,
val width: Int,
val height: Int
) {
companion object {
fun decode(params: Any?): LoadSuccessParams {
val tempParams = params as? JSONObject ?: JSONObject()
return LoadSuccessParams(
src = tempParams.optString("src", ""),
width = tempParams.optInt("width", 0),
height = tempParams.optInt("height", 0)
)
}
}
}
data class LoadErrorParams(
val src: String,
val errorCode: Int
) {
companion object {
fun decode(params: Any?): LoadErrorParams {
val tempParams = params as? JSONObject ?: JSONObject()
return LoadErrorParams(
src = tempParams.optString("src", ""),
errorCode = tempParams.optInt("errorCode", 0)
)
}
}
}
组件方法是 Kuikly 侧暴露的 API,实际实现在 Native 侧。
class MyImageView : DeclarativeBaseView<MyImageAttr, MyImageEvent>() {
// ...
/**
* 重新加载图片(无返回值)
*/
fun reload() {
performTaskWhenRenderViewDidLoad {
renderView?.callMethod("reload", null)
}
}
/**
* 获取图片信息(异步回调)
*/
fun getImageInfo(callback: (width: Int, height: Int) -> Unit) {
performTaskWhenRenderViewDidLoad {
renderView?.callMethod("getImageInfo", null) { result ->
val json = result as? JSONObject
callback(json?.optInt("width") ?: 0, json?.optInt("height") ?: 0)
}
}
}
}
⚠️ 注意:
- View 的方法支持异步回调结果,即renderView?.callMethod("method", "params", callback),但不支持同步返回结果。
- View 方法不支持传递二进制数据,如需传输图片等二进制内容,请通过 Base64 编码后以 JSON 形式传递,或使用 Module 方法实现。
import com.tencent.kuikly.core.base.ViewContainer
fun ViewContainer<*, *>.MyImage(init: MyImageView.() -> Unit) {
addChild(MyImageView(), init)
}
override fun body(): ViewBuilder {
val ctx = this
return {
MyImage {
attr {
size(176f, 132f)
src("https://example.com/image.png")
placeholder("https://example.com/placeholder.png")
}
event {
loadSuccess { params ->
println("图片加载成功: ${params.src}, 尺寸: ${params.width}x${params.height}")
}
loadError { params ->
println("图片加载失败: ${params.errorCode}")
}
}
}
}
}
通过 ViewRef 可以获取组件实例,在 Pager 其他位置调用组件方法。
@Page("MyPage")
class MyPage : Pager() {
// 声明 ViewRef
private val imageRef = ViewRef<MyImageView>()
override fun body(): ViewBuilder {
return {
MyImage {
// 绑定 ref
ref(imageRef)
attr {
src("https://example.com/image.png")
}
}
Button {
attr { title("重新加载") }
event {
click {
// 通过 ref 调用方法
imageRef.view?.reload()
}
}
}
}
}
}
Use this workflow to implement the Native side of a expand View.
前提: 只需在业务需要支持的平台上实现 Native 侧 View,无需实现所有平台。
步骤:
setProp 方法处理属性和事件。call 方法处理方法调用。各平台实现详见 [VIEWIMPLEMENT.md](references/VIEWIMPLEMENT.md)
速查:各平台 View 基类与注册方式
| 平台 | 基类/协议 | 注册方式 | 注意事项 |
|---|---|---|---|
| Android | IKuiklyRenderViewExport |
registerExternalRenderView 中 renderViewExport(name) { View(ctx) } |
继承原生 View 并实现接口 |
| iOS | KuiklyRenderViewExportProtocol |
类名必须与 viewName 一致(运行时动态创建) | 属性方法命名 setCssxxx,方法命名 cssxxx |
| 鸿蒙 (ArkTS) | KuiklyRenderBaseView |
getCustomRenderViewCreatorRegisterMap 或 getCustomRenderViewCreatorRegisterMapV2 中注册 |
需实现 createArkUIView() 返回 ComponentContent |
| H5 | IKuiklyRenderViewExport |
registerExternalRenderView 中 renderViewExport(name) { View() } |
重写 ele 属性返回 DOM 元素 |
| 小程序 | IKuiklyRenderViewExport |
registerExternalRenderView + Transform.addComponentsAlias + base.wxml 模板 |
需创建 MiniXxxElement 并配置模板 |
| Kuikly 侧类型 | Native 侧接收类型 |
|---|---|
String |
String / NSString |
Int / Float / Double |
对应基础类型 / NSNumber |
Boolean |
Boolean / BOOL |
Event 回调 |
KuiklyRenderCallback |
在 Native 侧,事件通过 KuiklyRenderCallback 回调给 Kuikly 侧:
// 保存回调
private var loadSuccessCallback: KuiklyRenderCallback? = null
override fun setProp(propKey: String, propValue: Any): Boolean {
return when (propKey) {
"loadSuccess" -> {
loadSuccessCallback = propValue as KuiklyRenderCallback
true
}
else -> super.setProp(propKey, propValue)
}
}
// 触发回调
private fun onImageLoaded(src: String, width: Int, height: Int) {
loadSuccessCallback?.invoke(mapOf(
"src" to src,
"width" to width,
"height" to height
))
}
| ❌ 错误做法 | ✅ 正确做法 |
|---|---|
| View 名字 Kuikly 侧与 Native 侧不一致 | 确保 viewName() 返回值与 Native 注册名完全一致 |
| 自定义 View 未设置宽高导致不显示 | 自定义 View 跨端侧使用时必须显式设置宽高(如 size(w, h)),否则可能不会显示 |
| iOS 侧 View 类名与 Kuikly 侧 viewName 不一致 | iOS 通过类名动态创建 View,类名必须与 viewName() 一致 |
iOS 侧用 Swift 实现但未加 @objc 注解 |
Swift 实现的 View 需要 @objc 或 @objcMembers 修饰 |
鸿蒙侧忘记实现 createArkUIView() |
鸿蒙侧必须实现此方法返回 ComponentContent |
| 忘记在 Native 侧注册自定义 View | 自定义 View 必须注册后才能使用 |
在 performTaskWhenRenderViewDidLoad 之外调用 renderView |
View 方法必须在 performTaskWhenRenderViewDidLoad 回调中调用 |