鸿蒙项目开发中,各个page中通常都会有TitleBar,显示标题和返回按钮,但是各个界面又具有差异性,可能不需要展示返回、可能右侧需要文字或者图片。每个界面都去写一遍TitleBar很是繁琐,因此封装一个通用的TitleBar还是很有必要的。
1.话不多说,先展示样式
2.设计思路
开始想着这不简单么,直接Row()横向排上就好,该显示的显示,该隐藏的隐藏。开发过程发现Title会始终不居中,每个样式的标题都会离中间的位置有差距。所以需要调整,尝试了Flex,其实和Row()一样存在问题。最终选择Stack()作为根目录,覆盖的方式来实现。第一层先是标题,第二层是返回按钮+右侧图标或文字。顺序不可以调换,涉及到后续的点击事件触发,返回按钮点击事件直接router.back()。右侧文字和图标的点击事件需要传递进来触发。
3.封装代码
import router from '@ohos.router'
/**
* TitleBar-标题栏
*/
@Preview
@Component
export default struct TitleBar {
isShow: Boolean = true;//是否有返回按钮 默认:true
title: string = '' //中间标题
rightImg: Resource;//右侧图标
rightTxt: string = '';//右侧文字
onRightTxtClick?: () => void;//右侧文字点击事件
onRightImgClick?: () => void;//右侧图标点击事件
build() {
Stack() {
Text(this.title)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.maxLines(1)
.fontSize('22fp')
Row() {
Image($r('app.media.ic_arrow_left'))
.width('30vp')
.height('30vp')
.objectFit(ImageFit.Fill)
.margin({ left: '10vp' })
.onClick(() => {
router.back()
}).visibility(this.isShow ? Visibility.Visible : Visibility.Hidden)
Text(this.rightTxt === '' ? '' : this.rightTxt)
.height('20vp')
.margin({ right: 20 })
.fontSize('16fp')
.fontColor($r('app.color.color_white'))
.visibility(this.rightTxt === '' ? Visibility.None : Visibility.Visible)
.onClick(()=>{
this.onRightTxtClick();
})
Image(this.rightImg === undefined ? null : this.rightImg)
.width('20vp')
.height('20vp')
.margin({ right: 20 })
.visibility(this.rightImg === undefined ? Visibility.None : Visibility.Visible)
.onClick(()=>{
this.onRightImgClick();
})
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
}
.width('100%')
.height('60vp')
.backgroundColor($r('app.color.colorPrimary'))
}
}
细心的读者会发现我设置返回按钮隐藏是用的Visibility.Hidden,需要用Hdden,隐藏的时候会有占位,使用None的话会使布局错乱。
4.调用代码
TitleBar({ title: '事件上报',rightImg: $r('app.media.icon_zanc_list'),onRightImgClick:()=>{
showToast('点击了图标')
}})
TitleBar({isShow:false,title:'任务中心',rightTxt:'积分规则',onRightTxtClick:()=>{
showToast('点击了积分规则')
}})