客户端实现自定义标签
Android
继承 CCardWidget 并实现其抽象方法,主要方法为 onCreateView,在这里返回对应的自定义 View。
public class CustomCubeWidget extends CCardWidget {
private static final String TAG = "CustomCubeWidget";
private Map<String, Object> createMap;
private TextView root;
public CustomCubeWidget(Context context) {
super(context);
}
@Override
public View onCreateView(Map<String, Object> params, int width, int height) {
MPLogger.debug(TAG, "onCreateView:" + width + "," + height);
createMap = params;
for (String key : params.keySet()) {
MPLogger.debug(TAG, key + ":" + params.get(key));
}
if (root == null) {
root = new TextView(getContext());
setText(root, params.get("value") + "");
root.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Map<String, Object> eventParams = new HashMap<>();
eventParams.put("p1", "widget:" + System.currentTimeMillis());
CubeService.instance().getEngine().sendEvent(createMap, "on-WidgetToCube", eventParams);
}
});
}
return root;
}
@Override
public void onReuse(Map<String, Object> params, int width, int height) {
MPLogger.debug(TAG, "onReuse");
}
@Override
public void onUpdateData(Map<String, Object> params) {
MPLogger.debug(TAG, "onUpdateData");
}
@Override
public void onRecycleAndCached() {
MPLogger.debug(TAG, "onRecycleAndCached");
}
@Override
public boolean canReuse() {
MPLogger.debug(TAG, "canReuse");
return false;
}
@Override
public void onDestroy() {
MPLogger.debug(TAG, "onDestroy");
}
@JsMethod
public void cubeToWidget(JSONObject param, CubeJSCallback callback) {
if (root != null) {
setText(root, "接收到卡片调用自定义方法,参数:" + param.toJSONString());
}
callback.invoke("cubeToWidget callback data: " + System.currentTimeMillis());
}
private void setText(TextView tv, String msg) {
tv.setText("我是原生组件,点我通知卡片事件回调," + msg);
}
}iOS
继承 CCardWidget 并实现其协议方法,其中 onCreateView 和 updateData 为必须实现的方法,其他方法为可选。
#import "CustomCardView.h"
@interface CustomCardView ()
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation CustomCardView
//必须实现
/**
* UI 创建接口,表示当前组件要上屏的视图 UI
*
* @param data map 类型,组件在卡片上声明的数据,包括样式、事件和属性,对应的 key 为DATA_KEY_STYLES、DATA_KEY_EVENTS、DATA_KEY_ATTRS;
* @param size View 的大小,宽高
* @return 可用的 UIView
*/
- (UIView *)onCreateView:(NSDictionary *)data size:(CGSize)size {
NSLog(@"数据打印:%@", data);
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
customView.backgroundColor = [UIColor redColor];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size.width, 30)];
//数据来源是 data 提供
self.titleLabel.text = @"A";
[customView addSubview:self.titleLabel];
return customView;
}
//必须实现
/**
* 组件数据更新接口
* @param data
*/
- (void)onUpdateData:(NSDictionary *)data {
NSLog(@"数据打印:%@", data);
}
/**
* 从复用池中获取的已存在控件,被使用前的数据准备。
* @param data 初始化数据
* @param size 组件复用时的大小
*/
- (void)onReuse:(NSDictionary *)data size:(CGSize)size {
NSLog(@"数据打印:%@", data);
NSLog(@"Size打印:%@", size);
//数据来源是 data 提供
self.titleLabel.text = @"B";
}
/**
* 组件是否支持复用;
* 为了提高效率,扩展组件可以支持复用。例如当某个自定义的标签组件由于数据更新被移除当前视图,此时该组件如果支持复用,那么会放入复用池内,下次该组件显示时,会直接从复用池内获取;
* @return YES:复用;NO:不复用。
*/
- (BOOL)canReuse {
return YES;
}
/**
* 组件复用清理接口。如果组件支持复用(canReuse 返回 true),则组件在进入复用池后会调用
* onRecycleAndCached 方法,表示当前组件已经离屏放入缓存内,需要清理资源。
*/
- (void)onRecycleAndCache {
//清理自定义 View 上的 SubView 内容
self.titleLabel.text = @"";
}鸿蒙
调用 Component 创建自定义组件
@Component
export struct MyCustomComponent {
@State
node: CKNode = new CKNode();
@State
cardInstance: CubeCard | null = null;
@State
text: string = ""
aboutToAppear(): void {
if (this.node) {
this.node.component = this;
this.updateWidgetData()
this.node.onChange = (type: NodeChangeType, changeNode: CKNode, childNode: CKNode | null) => {
this.updateWidgetData()
};
}
}
build() {
if (this.node) {
Column() {
Text("我是原生组件,点我通知卡片事件回调,"+this.text).onClick((event) => {
let args: Record<string, object> = {}
args["p1"] = "widget:" + systemDateTime.getTime() as ESObject
CWidgetApi.getInstance().sendEventToJS(this.node, 'on-WidgetToCube', args)
})
}
.width(this.node.size.width)
.height(this.node.size.height)
.position(this.node.position)
}
}
updateWidgetData(): void {
this.text = this.node.attributes.get("value") as string
}
public cubeToWidget(instance: FalconInstance, args: object, func: IFalconCallback): void {
this.text = "接收到卡片调用自定义方法,参数:"+JSON.stringify(args)
func.invoke("cubeToWidget callback data: " + systemDateTime.getTime())
}
}创建 ComponentBuilder
@Builder
export function buildMyCustomComponent(builder: ComponentBuilder) {
MyCustomComponent({
node: builder.node,
cardInstance: builder.cardInstance
})
}客户端注册自定义标签
Android
第一个参数是自定义的标签,可随意定制,在卡片侧会写在 <> 内。建议加上前缀,防止和动态卡片本身的标签冲突。第二个参数是自定义标签实现类的全路径,注意不要混淆。
Collection<CubeWidgetInfo> widgetInfos = new LinkedList<>();
widgetInfos.add(new CubeWidgetInfo("custom-widget", CustomCubeWidget.class.getName()));
CubeService.instance().getEngine().registerWidgets(widgetInfos);iOS
第一个参数是自定义的标签,需要与卡片侧约定好,在卡片侧会写到 <> 内。建议加上前缀,防止和动态卡片本身的标签冲突。第二个参数是自定义标签实现类的类名。
CubeWidgetInfo *widgetInfo = [CubeWidgetInfo new];
widgetInfo.tag = @"custom-widget";
widgetInfo.className = [CustomCardView class];
NSMutableArray *widgetArray = [NSMutableArray array];
[widgetArray addObject:widgetInfo];
[[[CubeService sharedInstance] getEngine] registerWidgets:[NSArray arrayWithArray:widgetArray]];鸿蒙
CWidgetInfo 的第一个参数是自定义的标签,可随意定制,在卡片侧会写在 <> 内。建议加上前缀,防止和动态卡片本身的标签冲突。第二个是参数是 WrappedBuilder。
let customBuilder: WrappedBuilder<[ComponentBuilder]> = wrapBuilder(buildMyCustomComponent)
let customWidgetInfo: CWidgetInfo = new CWidgetInfo("custom-widget", customBuilder)
CubeEngine.getInstance().registerWidgets([customWidgetInfo])卡片侧调用自定义标签
在标签中,写入自定义的标签,此处为 custom-widget。
<template>
<div class="root">
<text class="message" :value="message" @click="onClick()"></text>
<custom-widget ref="widget" class="custom" :value="message2" @on-WidgetToCube="clientToCube(param)">
</custom-widget>
</div>
</template>
<script>
export default {
data: {
message : '我是卡片的text,点我调用自定义组件',
message2 : '我是传给自定义组件的value'
},
beforeCreate() {
this.message = '我是卡片的text,点我调用自定义组件'
this.message2 = '我是传给自定义组件的value'
},
didAppear() {
},
methods: {
onClick() {
console.info('invoke on-click event');
this.$refs.widget.cubeToWidget({
'auto':"我是发给自定义组件方法的参数"
},ret=>{
this.message = "接收到自定义组件方法的回调,参数:"+JSON.stringify(ret);
});
},
//原生调用自定义标签的方法(调用JS)
clientToCube(param){
console.info(param.p1)
this.message2 = "接收到自定义组件的事件回调,参数:"+JSON.stringify(param)
}
}
}
</script>
<style>
.root {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: white;
width: 100%;
height: 800rpx;
}
.custom {
color: black;
font-size: 20rpx;
width: 100%;
height: 600rpx;
}
.message {
color: black;
font-size: 20rpx;
width: 100%;
height: 200rpx;
}
</style>卡片侧调用自定义标签的对应方法
卡片调用
this.$refs.widget.cubeToWidget({
'auto':"我是发给自定义组件方法的参数"
},ret=>{
this.message = "接收到自定义组件方法的回调,参数:"+JSON.stringify(ret);
});客户端接收
Android
@JsMethod
public void cubeToWidget(JSONObject param, CubeJSCallback callback) {}iOS
//配置约定的方法
CK_EXPORT_METHOD(@selector(cubeToWidget:callBack:))
//自定义标签调用原生方法
- (void)cubeToWidget:(NSDictionary *)params callBack:(CubeModuleMethodCallback)callback {
}鸿蒙
public cubeToWidget(instance: FalconInstance, args: object, func: IFalconCallback): void {}客户端通知卡片侧回调
客户端通知
Android
CubeService.instance().getEngine().sendEvent(Map<String, Object> componentData, String eventName, @Nullable Map<String, Object> eventParams)iOS
/**
* self.data :onCreateView方法中的data
* eventName :卡片侧的方法名,例如:@"on-WidgetToCube"
* eventParams : 传给卡片的参数,例如:@{@"p1":@"自定义标签调用cube方法"}
*/
[[[CubeService sharedInstance] getEngine]
sendEvent:self.data
eventName:eventName
eventParams:eventParams];鸿蒙
CWidgetApi.getInstance().sendEventToJS(node: CKNode, methodName: string, args: Record<string, Object> | null)卡片接收通知
此时卡片中可以用 @eventName 来接收客户端的通知,具体可以参考以下代码示例。
<custom-widget ref="widget" class="custom" :value="message2" @on-WidgetToCube="clientToCube(param)">该文章对您有帮助吗?