arkui-x框架,API Version 12

1、不做任何处理,默认蓝框现象

组件基本布局如下,仅摘录主要组件部分(更详细的代码实现可参考上一篇博客:arkui-x stack叠层解决焦点变换带来的布局问题-CSDN博客):

  @Builder
  AppListListBuilder() {
    List({scroller: this.listScroller}) {
      ForEach(this.appInfoListList, (infoList: ThirdPartyAppInfo[]) => {
        ListItem() {
          List() {
            ForEach(infoList, (info: ThirdPartyAppInfo) => {
              ListItem() {
                Stack() {
                  Text()  // 此为网格框,保证focus放大效果不超出网格
                    ......

                  Column() {
                    Stack() {
                      Text()
                        ......

                      Image('file://' + info.appIcon)
                        ......
                    }
                    .attributeModifier(this.isFocusItem[info.index] ? this.modifier : this.modifierNormal)
                    .margin({ bottom: 6 })

                    Text(info.appName)
                      ......
                  }
                  ......
                }
                .margin({ right: 4, bottom: 22 })
              }
            })
          }
          ......
        }
      })
    }
    ......
  }

核心是二维list里组件,简化如下:

Stack() {
        Text()  // 此为网格框,保证focus放大效果不超出网格
                    ......

        Column() {
                Stack() {
                      Text()
                        ......

                      Image('file://' + info.appIcon)
                        ......
                }
                .attributeModifier(this.isFocusItem[info.index] ? this.modifier : this.modifierNormal)
                .margin({ bottom: 6 })

                Text(info.appName)
                      ......
                }
                ......
        }

这样的focus效果,单板测试时,使用tab键切换焦点,选中对象会出现一个外围蓝框,如下视频:

2025-02-05-14-36-39-focus外围蓝框

2、使用focusable进行处理

2.1 设置Text(info.appName)的focusable为true,能正常

如下:

Stack() {
        Text()  // 此为网格框,保证focus放大效果不超出网格
                    ......

        Column() {
                Stack() {
                      Text()
                        ......

                      Image('file://' + info.appIcon)
                        ......
                }
                .attributeModifier(this.isFocusItem[info.index] ? this.modifier : this.modifierNormal)
                .margin({ bottom: 6 })

                Text(info.appName)
                      ......

                      .focusable(true)
                }
                ......
        }

这样把下方appName设置为可聚焦,tab键切换就没有蓝框问题了。但是这样,比较奇怪,期望的focus效果是上侧attributeModifier属性作用范围,Column --> Stack对用的组件,这样的改发没法自圆其说,但说明focusable这个属性是有效果的,可以继续作尝试。

2.2 设置Column --> Stack下的Image的focusable为true

Stack() {
        Text()  // 此为网格框,保证focus放大效果不超出网格
                    ......

        Column() {
                Stack() {
                      Text()
                        ......

                      Image('file://' + info.appIcon)
                        ......

                        .focusable(true)
                }
                .attributeModifier(this.isFocusItem[info.index] ? this.modifier : this.modifierNormal)
                .margin({ bottom: 6 })

                Text(info.appName)
                      ......                     
                }
                ......
        }

也有问题,蓝框变小,变为中心鼠标:

2025-02-05-14-43-02-中心图标蓝框

2.3 设置Column --> Stack下的Text的focusable为true

Stack() {
        Text()  // 此为网格框,保证focus放大效果不超出网格
                    ......

        Column() {
                Stack() {
                      Text()
                        ......

                        .focusable(true)

                      Image('file://' + info.appIcon)
                        ......
                }
                .attributeModifier(this.isFocusItem[info.index] ? this.modifier : this.modifierNormal)
                .margin({ bottom: 6 })

                Text(info.appName)
                      ......                     
                }
                ......
        }

蓝框没有了,出现更奇怪问题,变焦时,中心图标会被覆盖消失

2025-02-05-14-46-05-stack外围设置focus导致中心图标消失

2.4 解决方法, 还是套用stack叠层思想,在Column --> Stack里再增加一个text组件,设置其focusable为true

Stack() {
        Text()  // 此为网格框,保证focus放大效果不超出网格
                    ......

        Column() {
                Stack() {
                      Text()
                        ......

                      Image('file://' + info.appIcon)
                        ......

                      Text()  // 提供聚焦点,避免单板测试时出现focus默认的蓝框
                              .height(同stack下最大组件)
                              .width(同stack下最大组件)
                              .focusable(true)

                }
                .attributeModifier(this.isFocusItem[info.index] ? this.modifier : this.modifierNormal)
                .margin({ bottom: 6 })

                Text(info.appName)
                      ......                     
                }
                ......
        }

这样的修改能够自圆其说,新增的Text提供一个最上层的聚焦,且它本身透明,不会遮挡下层组件。单板测试,tab键切换也没有问题。

2.5 从focusable作用域考虑,更严谨一点,可以把外围Stack下的Text和最下侧Text(info.appName)的focusable设置为false

Stack() {
        Text()  // 此为网格框,保证focus放大效果不超出网格
                ......

                .focusable(false)

        Column() {
                Stack() {
                      Text()
                        ......

                      Image('file://' + info.appIcon)
                        ......

                      Text()  // 提供聚焦点,避免单板测试时出现focus默认的蓝框
                              .height(同stack下最大组件)
                              .width(同stack下最大组件)
                              .focusable(true)

                }
                .attributeModifier(this.isFocusItem[info.index] ? this.modifier : this.modifierNormal)
                .margin({ bottom: 6 })

                Text(info.appName)

                        ......

                        .focusable(false)
                }
                ......
        }

其他:通过调整focusable,也可以灵活的设置焦点生效的范围

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐