鸿蒙之自定义占位组件

时间:2024-11-12 11:23:20

鸿蒙系统提供了大量的UI组件可以使用,通过不同的UI组件组合就可以完成复杂的UI布局。 比如:

容器类的组件如:RelativeContainer、Stack、Row、Column、Flex等

栅格分栏的组件如:GridRow、CridCol等

滚动与滑动组件如:List、Grid、Scroll、Swiper、WaterFlow等

导航类组件如:Navigation、NavRouter、Tabs等

以及很多展示具体UI的组件如:Button、Checkbox、Text、Image、Video等等。

可以发现系统提供的UI组件还是非常多的,

但这些都相当于是预设的组件,面对类似前端那种占位的情况就不太好解决了,所以可以使用如下组件解决:NodeContainer、ContentSlot。

NodeContainer

NodeContainer是一个基础组件,不支持尾随添加子节点。组件接受一个NodeController的实例接口。需要和NodeController组合使用。 示例代码如下: model:

import { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI';

declare class Params {
  text: string
}

builder:

@Builder
function buttonBuilder(params: Params) {
  Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly }) {
    Text(params.text)
      .fontSize(12)
    Button(`This is a Button`, { type: ButtonType.Normal, stateEffect: true })
      .fontSize(12)
      .borderRadius(8)
      .backgroundColor(0x317aff)
  }
  .height(100)
  .width(200)
}

NodeController:

class MyNodeController extends NodeController {
  private rootNode: BuilderNode<[Params]> | null = null;
  private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder);

  makeNode(uiContext: UIContext): FrameNode | null {
    if (this.rootNode === null) {
      this.rootNode = new BuilderNode(uiContext);
      this.rootNode.build(this.wrapBuilder, { text: "This is a Text" })
    }
    return this.rootNode.getFrameNode();
  }
}

Component:

@Entry
@Component
struct Index {
  private baseNode: MyNodeController = new MyNodeController()

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.SpaceEvenly }) {
      Text("This is a NodeContainer contains a text and a button ")
        .fontSize(9)
        .fontColor(0xCCCCCC)
      NodeContainer(this.baseNode)
        .borderWidth(1)
        .onClick(() => {
          console.log("click event");
        })
    }
    .padding({ left: 35, right: 35, top: 35 })
    .height(200)
    .width(300)
  }
}

ContentSlot

用于渲染并管理Native层使用C-API创建的组件。 支持混合模式开发,当容器是ArkTs组件,子组件在Native侧创建时,推荐使用ContentSlot占位组件。 代码如下:

import { nativeNode } from 'libNativeNode.so' // 开发者自己实现的so
import { NodeContent } from '@kit.ArkUI'

@Entry
@Component
struct Parent {
    private nodeContent: Content = new NodeContent();

    aboutToAppear() {
        // 通过C-API创建节点,并添加到管理器nodeContent上
        nativeNode.createNativeNode(this.nodeContent);
    }

    build() {
        Column() {
            // 显示nodeContent管理器里存放的Native侧的组件
            ContentSlot(this.nodeContent)
        }
    }
}

从以上代码可以看出与正常的UI渲染组件的区别,在需要使用占位组件时,可以参考以上方法。