鸿蒙9+ 目前不支持鸿蒙系统电视,但是往后肯定是必须会支持的,所以直接学arkts就完事了,目前的api9+对焦点控制还是不够直接简洁,估计还在完善中,但是可以通过自定义component来实现一下
首先踩坑:
- Row官方说自身属性是可获焦的,但是单独使用是没法获焦的,所以必须在里面添加一个可获焦的子view,但是通常所有的子view都是由获焦和离焦状态的,所以不能所有的子view都加上focusable=true,这里可以通过@Consume来同步整个组件内部的焦点状态, 注意这个修饰符达到同步的前提是参数名一模一样!!!
@Component
export struct RowFocusable {compWidth: Length ='90vp'compHeight: Length ='28vp'compBorderRadius: Length ='14vp'alignItems: VerticalAlign = VerticalAlign.Center
justifyContent: FlexAlign = FlexAlign.Center
@Consume focusState: number
@Builder doAddChild(){}
@BuilderParam addChild:()=>void=this.doAddChild;build(){Row(){//扯淡的玩意,容器布局的子节点没有获焦能力的话,容器布局就不会获焦,//但是子节点能获焦的话,那其他所有有焦点态的子节点也必须设置可获焦,那走焦的时候会在子节点之间走动,不合理,非常的不合理,//竟然没有父组件拦截焦点的方法Text('').focusable(true).onFocus(()=>{this.focusState = ComponentsConstants.FOCUS_STATE_FOCUSED}).onBlur(()=>{this.focusState = ComponentsConstants.FOCUS_STATE_NORMAL}).width('0vp')this.addChild()}.width(this.compWidth).height(this.compHeight).justifyContent(this.justifyContent).alignItems(this.alignItems).focusOnTouch(true).borderWidth(2).borderRadius(this.compBorderRadius).borderStyle(BorderStyle.Solid).onFocus(()=>{}).onBlur(()=>{}).stateStyles({focused:{.backgroundColor($r('app.color.transparent')},normal:{.backgroundColor($r('app.color.transparent')},})}}
自定义component 后面直接设置基础属性,像上面这种只有一个@BuildParam方法的可以直接这样写,在大括号后面接上需要添加的子组件即可:
@Component
export struct ImageButton {btnWidth: Length ='90vp'btnHeight: Length ='28vp'imgWidth: Length ='15vp'imgHeight: Length ='15vp'tvCfg: TextFocusConfig |undefined=undefinedimgCfg: ImageFocusConfig |undefined=undefined
@Provide focusState: number = ComponentsConstants.FOCUS_STATE_NORMAL
@Builder buildImage(){ImageFocusable({imgCfg:this.imgCfg}).width(this.imgWidth).height(this.imgHeight)}
@Builder buildText(){TextFocusable({tvCfg:this.tvCfg})}build(){RowFocusable({compWidth:this.btnWidth,compHeight:this.btnHeight }){this.buildImage()this.buildText()}}}//自定义,统一设置占位图
@Component
export struct ImageFocusable {
@Consume focusState: number
imgCfg: ImageFocusConfig|undefinedbuild(){Image(this.focusState==ComponentsConstants.FOCUS_STATE_FOCUSED?this.imgCfg.imgResFocused :this.imgCfg.imgResNormal).objectFit(ImageFit.Contain).enabled(true).alt($r('app.media.poster_placeholder'))}}//这里定义成config类,是为了方便组件层级太深时,更好的透传,比如上面ImageButtonexportclassImageFocusConfig{imgResNormal: ResourceStr
imgResFocused: ResourceStr
constructor(imgResNormal,imgResFocused){this.imgResNormal = imgResNormal
this.imgResFocused = imgResFocused
}}
@Component
export struct TextFocusable {
@Consume focusState: number
tvCfg: TextFocusConfig |undefinedbuild(){if(this.tvCfg !=null){Text(this.tvCfg!.text).fontColor(this.focusState == ComponentsConstants.FOCUS_STATE_FOCUSED?this.tvCfg!.focusColor :this.tvCfg.normalColor).textAlign(this.tvCfg.textAlign).maxLines(this.tvCfg.maxLine).textOverflow({overflow:this.tvCfg.textOverFlow}).align(Alignment.Center).width(this.tvCfg.width).height(this.tvCfg.height).fontSize(this.tvCfg.textSize)}}}exportclassTextFocusConfig{text: ResourceStr
textSize: Length
width: Length
height: Length
normalColor: ResourceColor
focusColor: ResourceColor
selectColor: ResourceColor
textAlign: TextAlign
maxLine: number
textOverFlow: TextOverflow
constructor()constructor(text?)constructor(text?, tvSize?)constructor(text?, tvSize?, width?, height?)constructor(text?, tvSize?, width?, height?, normalColor?, focusColor?, selectColor?)constructor(text?, tvSize?, width?, height?, normalColor?, focusColor?, selectColor?, textAlign?, maxLine?, textOverFlow?){this.text = text ??''this.textSize = tvSize ??'14vp'this.width = width ??'auto'this.height = height ??'auto'this.normalColor = normalColor ??$r('app.color.white_70')this.focusColor = focusColor ??$r('app.color.white_100')this.selectColor = selectColor ??$r('app.color.tv_color_selected')this.textAlign = textAlign ?? TextAlign.Start
this.maxLine = maxLine ??1this.textOverFlow = textOverFlow ?? TextOverflow.Ellipsis
}setText(text): TextFocusConfig {this.text = text
returnthis}setTextSize(size): TextFocusConfig {this.textSize = size
returnthis}setWith(w): TextFocusConfig {this.width = w
returnthis}setHeight(h): TextFocusConfig {this.height = h
returnthis}}
像自定义text这种组件,很多属性都没法直接设置,所以需要添加自己命名的属性,然后也没有焦点态的方法,所以只能通过@Consume focusState: number 来同步父子组件之间的焦点状态,另外封装成config的好处还是挺多的,自我挖掘吧
版权归原作者 熊佳龙 所有, 如有侵权,请联系我们删除。