写点什么

【每日学点 HarmonyOS Next 知识】状态变量、动画 UI 残留、Tab 控件显示、ob 前缀问题、文字背景拉伸

作者:轻口味
  • 2025-03-13
    北京
  • 本文字数:4146 字

    阅读完需:约 14 分钟

【每日学点HarmonyOS Next知识】状态变量、动画UI残留、Tab控件显示、ob前缀问题、文字背景拉伸

1、HarmonyOS 怎么用一个变量观察其他很多个变量的变化?

有一个提交按钮的颜色,需要很多个值非空才变为红色,否则变为灰色,可不可以用一个变量统一观察这很多个值,去判断按钮该显示什么颜色,比如 Button().backgroundColor(this.color),this.color 的值取决于很多个输入框的值


想将子组件与父组件的变量绑定起来,实现其中一个变量改变,对应的变量也做同步的改变,可以做如下操作:将子组件的变量需要用 @Link 修饰,且不能初始化将父组件的变量需要用 @State 修饰。传值的时候使用 $符号修饰。


import Prompt from '@system.prompt'@Entry@Componentstruct Index {  //父组件的变量需要用@State修饰  @State inputUserName:string ='张三'  @State inputUserPsw:string ='张三'  build() {    Row() {      Column() {        Text(this.inputUserName).fontSize(20)        // 使用子组件传值的时候用$传递        LoginInput({hint:'请输入账号',inputVale:$inputUserName})        LoginInput({hint:'请输入账号',inputVale:$inputUserPsw})
} .width('100%') } .height('100%') }
}@Componentstruct LoginInput { private hint: string = '请输入账号密码'; //子组件的变量需要用@Link修饰,且不能初始化 @Link inputVale: string; build() { TextInput({placeholder:this.hint,text:this.inputVale}) .onChange((value)=>{ this.inputVale= value; Prompt.showToast({message:value}) }) }}
复制代码

2、HarmonyOS 动画过程中 UI 残留?

等长没有异常。只有 3->2 出现 出现后点击屏幕任意点 刷新消失


参考以下示例通过 onChange 实现切换时自定义 tabBar 和 TabContent 的联动:


// xxx.ets@Entry@Componentstruct TabsExample {  @State fontColor: string = '#182431'  @State selectedFontColor: string = '#007DFF'  @State currentIndex: number = 0  private controller: TabsController = new TabsController()
@Builder tabBuilder(index: number, name: string) { Column() { Text(name) .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor) .fontSize(16) .fontWeight(this.currentIndex === index ? 500 : 400) .lineHeight(22) .margin({ top: 17, bottom: 7 }) Divider() .strokeWidth(2) .color('#007DFF') .opacity(this.currentIndex === index ? 1 : 0) }.width('100%') }
build() { Column() { Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) { TabContent() { Column().width('100%').height('100%').backgroundColor('#00CB87') }.tabBar(this.tabBuilder(0, 'green'))
TabContent() { Column().width('100%').height('100%').backgroundColor('#007DFF') }.tabBar(this.tabBuilder(1, 'blue'))
TabContent() { Column().width('100%').height('100%').backgroundColor('#FFBF00') }.tabBar(this.tabBuilder(2, 'yellow'))
TabContent() { Column().width('100%').height('100%').backgroundColor('#E67C92') }.tabBar(this.tabBuilder(3, 'pink')) } .vertical(false) .barMode(BarMode.Fixed) .barWidth(360) .barHeight(56) .animationDuration(400) .onChange((index: number) => { this.currentIndex = index }) .width(360) .height(296) .margin({ top: 52 }) .backgroundColor('#F1F3F5') }.width('100%') }}
复制代码

3、HarmonyOS Tabs 控件 底部显示不全?

Tabs 控件 底部显示不全 TabContent() 中的页面,底部显示不全


Scroll(this.scroller)的高度设百分比,和上面的相加为 100%即可,参考 DEMO:


@Entry@Componentstruct newPage {  @State fontColor: string = '#182431'  @State selectedFontColor: string = '#007DFF'  @State currentIndex: number = 0  private controller: TabsController = new TabsController()  scroller: Scroller = new Scroller()  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
@Builder tabBuilder(index: number, name: string) { Column() { Text(name) .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor) .fontSize(16) .fontWeight(this.currentIndex === index ? 500 : 400) .lineHeight(22) .margin({ top: 17, bottom: 7 }) Divider() .strokeWidth(2) .color('#007DFF') .opacity(this.currentIndex === index ? 1 : 0) }.width('100%') }
build() { Column() { Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) { TabContent() { Column() { Row() { Text('首页').align(Alignment.Center) } .justifyContent(FlexAlign.Center) .height('10%') //上面的设10% .width('100%') .padding({ left: 10, right: 10 }) .backgroundColor(Color.Green)
Scroll(this.scroller) { Column() { ForEach(this.arr, (item: number) => { Text(item.toString()) .width('90%') .height(150) .backgroundColor(0xFFFFFF) .borderRadius(15) .fontSize(16) .textAlign(TextAlign.Center) .margin({ top: 10 }) }, (item: string) => item) }.width('100%') }.height('90%') //Scroll设90% .scrollable(ScrollDirection.Vertical) // 滚动方向纵向
.friction(0.6) .edgeEffect(EdgeEffect.None) } } .tabBar(this.tabBuilder(0, 'green'))
TabContent() { Column().width('100%').height('100%').backgroundColor('#007DFF') }.tabBar(this.tabBuilder(1, 'blue'))
} .vertical(false) .barMode(BarMode.Fixed) .barWidth(360) .barHeight(56) .animationDuration(400) .onChange((index: number) => { this.currentIndex = index }) .width('100%') .height('100%')
.backgroundColor('#F1F3F5') }.width('100%').height('100%') }}
复制代码

4、HarmonyOS 被 @ObservedV2 和 @Trace 标记的类及字段,使用 JSON.stringify 之后字段名称都加上了“__ob_”开头的字段?

使用 JSON.stringify 序列化之后字段名称都改变了,导致无法反序列化回来。


关于序列化后会有__ob_前缀的问题,可以在序列前替换掉__ob_前缀,demo 如下


import  { plainToClass } from "class-transformer";@ObservedV2class Son {  @Trace age: number = 100;}class Father {  son: Son = new Son();}@Entry@Componentstruct Index {  father: Father = new Father();  aboutToAppear(): void {    let a = JSON.stringify(this.father);    let b: Father = plainToClass(Father,this.father);    //{"son":{"__ob_age":100}}替换成{"son":{"age":100}}    console.log(JSON.stringify(convertKeysToCamelCase(this.father)))  }
build() { Column() { // 当点击改变age时,Text组件会刷新 Text(`${this.father.son.age}`) .onClick(() => { this.father.son.age++; }) } }}
// utils.etsexport function underscoreToCamelCase(underscoreString:string):string { // 捕获__ob_替换成'' return underscoreString.replace(/(__ob_)/g, (match:string, letter:string):string=> { console.log(letter) return ''; });}export function convertKeysToCamelCase(obj:ESObject):ESObject { if (obj && typeof obj === 'object') { const newObj:ESObject = {}; Object.keys(obj).forEach((key)=> { if (obj.hasOwnProperty(key)) { const newKey = underscoreToCamelCase(key); newObj[newKey] = convertKeysToCamelCase(obj[key]); } }) return newObj; } else { return obj; }}
复制代码

5、HarmonyOS 文字背景局部拉伸问题?

  1. backgroundImageResizable 设置无作用,Image 设置 resizable 是可以的

  2. 如何让同级控件宽度自适应文字宽度


获取文本长度的方式参考文档,让 backgroundImageSize 改为文字的宽度:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-measure-V5#ZH-CN_TOPIC_0000001884917586__measuremeasuretext


实现方式 demo:


import measure from '@ohos.measure'
@Entry@Componentstruct IR240513200608052 { @State message: string = 'Hello World啊哈哈哈哈哈哈哈哈哈'; @State textWidth: number = measure.measureText({ textContent: this.message })
build() { Column() { Text(this.message) .backgroundImage($r('app.media.startIcon')) .backgroundImageResizable({ slice: { top: 3, left: 3, bottom: 3, right: 3 } }) .backgroundImageSize({ width: this.textWidth }) }.height('100%').width('100%') }}
复制代码


发布于: 刚刚阅读数: 5
用户头像

轻口味

关注

🏆2021年InfoQ写作平台-签约作者 🏆 2017-10-17 加入

Android、音视频、AI相关领域从业者。 欢迎加我微信wodekouwei拉您进InfoQ音视频沟通群 邮箱:qingkouwei@gmail.com

评论

发布
暂无评论
【每日学点HarmonyOS Next知识】状态变量、动画UI残留、Tab控件显示、ob前缀问题、文字背景拉伸_HarmonyOS_轻口味_InfoQ写作社区