When you use native APIs to develop an application based on the XComponent, you can request an independent frame rate for custom content in scenarios such as gaming and custom UI framework interconnection.
| Name | Description |
|---|---|
| OH_NativeXComponent_SetExpectedFrameRateRange(OH_NativeXComponent* component, OH_NativeXComponent_ExpectedRateRange* range) | Sets the expected frame rate range. |
| OH_NativeXComponent_RegisterOnFrameCallback(OH_NativeXComponent* component, void (*callback)(OH_NativeXComponent* component, uint64_t timestamp, uint64_t targetTimestamp)) | Sets the per-frame callback function and starts the per-frame callback. |
| OH_NativeXComponent_UnregisterOnFrameCallback(OH_NativeXComponent* component) | Unregisters the per-frame callback function and stops invoking the callback. |
For details about the APIs, see OH_NativeXComponent Native XComponent.
This section draws a graphic through the native Drawing module and presents it using the native Window module. For details, see Using Drawing to Draw and Display Graphics.
Add dependencies.
Add the following library to CMakeLists.txt.
target_link_libraries(entry PUBLIC libace_napi.z.so libnative_drawing.so libnative_window.so libace_ndk.z.so)
Import the required header files.
#include <ace/xcomponent/native_interface_xcomponent.h> #include <arpa/nameser.h> #include <bits/alltypes.h> #include <native_window/external_window.h> #include <native_drawing/drawing_bitmap.h> #include <native_drawing/drawing_color.h> #include <native_drawing/drawing_canvas.h> #include <native_drawing/drawing_pen.h> #include <native_drawing/drawing_brush.h> #include <native_drawing/drawing_path.h> #include <cstdint> #include <map> #include <sys/mman.h> #include <string> #include "napi/native_api.h"
#include <native_drawing/drawing_text_typography.h>
Define an ArkTS API file and name it XComponentContext.ts, which is used to connect to the native layer.
export default interface XComponentContext {
register(): void;
unregister(): void;
}; Define a demo page, which contains two XComponents.
import XComponentContext from '../interface/XComponentContext';
// ...
@Entry
@Component
struct Index {
private xComponentContext1: XComponentContext | undefined = undefined;
private xComponentContext2: XComponentContext | undefined = undefined;
build() {
Column() {
Row() {
// ...
XComponent({
id: 'xcomponentId_30',
type: XComponentType.SURFACE,
libraryname: 'entry'
})
.onLoad((xComponentContext) => {
this.xComponentContext1 = xComponentContext as XComponentContext;
}).width('640px')
// ...
}.height('40%')
Row() {
// ...
XComponent({
id: 'xcomponentId_120',
type: XComponentType.SURFACE,
libraryname: 'entry'
})
.onLoad((xComponentContext) => {
this.xComponentContext2 = xComponentContext as XComponentContext;
}).width('640px')
// ...
}.height('40%')
// ...
}
}
} Configure the frame rate and register the callback function at the native layer.
static void TestCallback(OH_NativeXComponent *component, uint64_t timestamp, uint64_t targetTimestamp)
{
// ...
int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, nativeWindow, &width, &height);
if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) {
render->Prepare();
render->Create();
if (id == "xcomponentId_30") {
int offset = 16;
render->ConstructPath(offset, offset, render->defaultOffsetY);
}
if (id == "xcomponentId_120") {
int offset = 4;
render->ConstructPath(offset, offset, render->defaultOffsetY);
}
// ...
}
}
void SampleXComponent::RegisterOnFrameCallback(OH_NativeXComponent *nativeXComponent)
{
// ...
OH_NativeXComponent_RegisterOnFrameCallback(nativeXComponent, TestCallback);
} napi_value SampleXComponent::NapiRegister(napi_env env, napi_callback_info info)
{
// ...
render->RegisterOnFrameCallback(nativeXComponent);
// ...
} napi_value SampleXComponent::NapiUnregister(napi_env env, napi_callback_info info)
{
// ...
OH_NativeXComponent_UnregisterOnFrameCallback(nativeXComponent);
// ...
} Register and deregister the callback function for each frame at the TS layer.
Row() {
Button('Start')
.id('Start')
.fontSize(14)
.fontWeight(500)
.margin({ bottom: 20, right: 6, left: 6 })
.onClick(() => {
if (this.xComponentContext1) {
this.xComponentContext1.register();
}
if (this.xComponentContext2) {
this.xComponentContext2.register();
}
})
.width('30%')
.height(40)
.shadow(ShadowStyle.OUTER_DEFAULT_LG)
Button('Stop')
.id('Stop')
.fontSize(14)
.fontWeight(500)
.margin({ bottom: 20, left: 6 })
.onClick(() => {
if (this.xComponentContext1) {
this.xComponentContext1.unregister();
}
if (this.xComponentContext2) {
this.xComponentContext2.unregister();
}
})
.width('30%')
.height(40)
.shadow(ShadowStyle.OUTER_DEFAULT_LG)
// ...
}