【每日学点HarmonyOS Next知识】状态变量、动画UI残留、Tab控件显示、ob前缀问题、文字背景拉伸
1、HarmonyOS 怎么用一个变量观察其他很多个变量的变化?
有一个提交按钮的颜色,需要很多个值非空才变为红色,否则变为灰色,可不可以用一个变量统一观察这很多个值,去判断按钮该显示什么颜色,比如Button().backgroundColor(this.color),this.color的值取决于很多个输入框的值
想将子组件与父组件的变量绑定起来,实现其中一个变量改变,对应的变量也做同步的改变,可以做如下操作:将子组件的变量需要用@Link修饰,且不能初始化将父组件的变量需要用@State修饰。传值的时候使用$符号修饰。
import Prompt from '@system.prompt'
@Entry
@Component
struct 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%')
}
}
@Component
struct 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
@Component
struct 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
@Component
struct 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";
@ObservedV2
class Son {
@Trace age: number = 100;
}
class Father {
son: Son = new Son();
}
@Entry
@Component
struct 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.ets
export 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 文字背景局部拉伸问题?
- backgroundImageResizable设置无作用,Image设置resizable是可以的
- 如何让同级控件宽度自适应文字宽度
获取文本长度的方式参考文档,让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
@Component
struct 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%')
}
}