HarmonyOS鸿蒙Next中如何封装系统组件使其自带hdsEffect效果,并在外层能随意调整样式?

HarmonyOS鸿蒙Next中如何封装系统组件使其自带hdsEffect效果,并在外层能随意调整样式? 有了新的hdsEffect效果后,要在row,column,button组件上增加发光效果和受光效果,不想在每个页面的每个使用该系统组件的地方都加上对应的代码,也不想每次使用都引入deviceInfo来判断这个api。于是我封装了一下,效果是有了,但是样式没法在使用的地方进行更改了,难不成需要对每个属性都复写一遍吗?

我封装了一个Column组件如下

import { MyModifier } from '../modifier'
import { hdsEffect } from '@kit.UIDesignKit';
import { deviceInfo } from '@kit.BasicServicesKit';
import { ViewStyle } from '../common/constants/Constants'

@Extend(Column)
function onTouchLight(cb: (type: hdsEffect.PointLightSourceType) => void) {
  .onTouch((event: TouchEvent) => {
    if (deviceInfo.sdkApiVersion >= 20) {
      if (event.type === TouchType.Down) {
        cb(hdsEffect.PointLightSourceType.BRIGHT)
      } else if (event.type === TouchType.Up || event.type === TouchType.Cancel) {
        cb(hdsEffect.PointLightSourceType.NONE)
      }
    }
  })
}

@Component
export struct MyColumn {
  @BuilderParam customBuilderParam: () => void = this.customBuilder;
  @Prop @Watch('showAniFun') showAni: boolean = false
  @State translateY: number = 50;
  @State opacityNum: number = 0;
  @State index: number = 0
  @State alignItems: HorizontalAlign = HorizontalAlign.Start
  @State justifyContent: FlexAlign = FlexAlign.Start
  @State modifier: MyModifier = new MyModifier()
  @State H: string | Resource = ''
  @State W: string | Resource = ''
  @State OL: string | CustomBuilder | ComponentContent = ''

  @Builder
  customBuilder() {

  }

  build() {
    Column() {
      this.customBuilderParam()
    }
    .onTouchLight((type: hdsEffect.PointLightSourceType) => {
      this.modifier.sourceType = type
    })
    .backgroundColor(ViewStyle.BgColor)
    .opacity(this.opacityNum)
    .translate({ y: this.translateY })
    .attributeModifier(this.modifier)
    .alignItems(this.alignItems)
    .justifyContent(this.justifyContent)
    .height(this.H)
    .width(this.W)
    .overlay(this.OL)
  }

  showAniFun() {
    if (this.showAni == true) {
      this.opacityNum = 0
      this.translateY = 50
      this.getUIContext()?.animateTo({ duration: 250, curve: 'ease-out', delay: 50 * this.index }, () => {
        this.opacityNum = 1
        this.translateY = 0
      })
    } else {
      this.opacityNum = 0
      this.translateY = 50
    }
  }

  aboutToAppear(): void {
    this.getUIContext()?.animateTo({ duration: 250, curve: 'ease-out' }, () => {
      this.opacityNum = 1
      this.translateY = 0
    })
  }

  aboutToDisappear(): void {
    this.opacityNum = 0
    this.translateY = 50
  }
}

modifier如下

import { deviceInfo } from '@kit.BasicServicesKit';
import { hdsEffect } from '@kit.UIDesignKit';


export class MyModifier implements AttributeModifier<CommonAttribute> {
  showHDS: boolean = true
  sourceType: hdsEffect.PointLightSourceType = hdsEffect.PointLightSourceType.NONE

  applyNormalAttribute(instance: CommonAttribute): void {
    if (deviceInfo.sdkApiVersion >= 20 && this.showHDS === true) {
      instance.visualEffect(new hdsEffect.HdsEffectBuilder().pointLight({
        illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT,
        sourceType: this.sourceType
      }))
    }
  }
}

封装是好了,但是在页面使用的时候,没法去随意使用其他属性,只能使用我预设好的一些属性。

后面该如何写?求大佬指导。


更多关于HarmonyOS鸿蒙Next中如何封装系统组件使其自带hdsEffect效果,并在外层能随意调整样式?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

使用尾随闭包能在内部的组件里绑定当前页面的对象,但是无法设置封装组件的属性。不使用尾随闭包通过传递组件方式,传递的组件无法使用$$来双向绑定,这这么破

cke_193.png

更多关于HarmonyOS鸿蒙Next中如何封装系统组件使其自带hdsEffect效果,并在外层能随意调整样式?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,通过@Styles装饰器定义可复用的组件样式,结合@Extend装饰器扩展系统组件,封装时使用@BuilderParam动态注入hdsEffect效果。外层通过@State变量控制样式参数,实现灵活调整。

在HarmonyOS Next中,要实现封装系统组件自带hdsEffect效果并保持外部样式灵活性,建议采用以下方案:

  1. 使用@BuilderParam传递样式:将样式配置作为Builder参数传入,允许外部自定义。

    [@Component](/user/Component)
    export struct MyColumn {
      [@BuilderParam](/user/BuilderParam) styleBuilder: () => void = () => {};
    
      build() {
        Column() {
          // 内容
        }
        .attributeModifier(this.modifier)
        .apply(this.styleBuilder) // 应用外部样式
      }
    }
    
  2. 链式调用支持:在自定义组件中暴露原始组件的方法,通过this返回组件实例。

    build() {
      Column() {
        // 内容
      }
      .attributeModifier(this.modifier)
      // 不封闭样式链,允许外部继续调用样式方法
    }
    
  3. 属性代理模式:通过@Prop接收样式值,但更推荐使用@Styles@Extend定义可复用样式组合,将hdsEffect封装在样式扩展中。

    [@Styles](/user/Styles) function hdsColumnStyle() {
      .attributeModifier(new MyModifier())
      // 其他基础样式
    }
    
    // 使用时
    Column()
      .hdsColumnStyle()
      .width(100) // 外部可继续调整
    
  4. 条件渲染hdsEffect:在modifier中增加开关,允许外部通过属性控制是否启用效果。

    export class MyModifier {
      [@Prop](/user/Prop) enableHds: boolean = true;
      // ... 根据enableHds条件应用效果
    }
    

这样既封装了hdsEffect的通用逻辑,又通过ArkUI的响应式设计保持了样式的灵活性。

回到顶部