【小源笔记】第二期 | 如何为应用适配焦点控制 原创

Haoc_小源同学
发布于 2022-10-25 17:02
浏览
1收藏

前言

在一些依靠遥控器操作的设备例如智慧屏,按键走焦是主要的交互方式,通过焦点可以告诉用户当前聚焦的位置

当前支持焦点控制的组件有Button、Text、Image、List、Grid

如何适配

除Button还有Toggle组件外,其他组件默认都是不可获焦的,一个组件想要获得焦点,需要focusable 属性等于 true。以系统settings应用为例,首页是一个List列表容器,要给每个ListItem子项添加焦点事件,只需要给ListItem组件的子组件添加focusable(true)即可。例如首页最顶部是一个搜索框,搜索框的ListItem的子组件为Row容器组件,由于Row组件不支持焦点事件,可以给Row容器下的子组件Image或Text任一组件添加focusable属性设置为true,便可以通过键盘的TAB键或方向键进行获焦了。可获焦的组件可以触发按键事件进行操作,通过给组件添加onKeyEvent事件,在事件触发时执行相应的函数代码,例如这里判断当键盘按了回车键时就跳转页面。

List({ space: this.listSpaces }) {
  // search
  ListItem() {
    Row() {
      Image($r("app.media.ic_search"))
        ...
        .focusable(true)
        .onFocus(() => {
          this.searchFocused = true
        })
        .onBlur(() => {
          this.searchFocused = false
        })
        .onKeyEvent((event: KeyEvent) => {
          if (event.keyCode === KEYCODE_ENTER || event.keyCode === KEYCODE_NUMPAD_ENTER) {
            router.push({
              url: 'pages/searchPage'
            })
          }
        });

      Text($r("app.string.searchHint"))
        ...
    }
    ...

  ListItem() {
    List() {
      ListItem() {
        // WLAN
        SettingItemComponent({
          ...
        })
      }

      ListItem() {
        // blueTooth
        SettingItemComponent({
          ...
        })
      }

      ListItem() {
        // mobileData
        SettingItemComponent({
          ...
        })
      }
      ...
    }
    ...
  }

  ...
}

同理,为WLAN、蓝牙等ListItem添加焦点事件只需要为自定义组件SettingItemComponent下支持焦点控制的组件添加对应的属性及事件即可

@Component
export struct SettingItemComponent {
  ...
  @State isFocused: boolean = false;

  build() {
    Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
      Row() {
        Image(this.settingIcon)
          ...
          .focusable(true)
          .onFocus(() => {
            this.isFocused = true
          })
          .onBlur(() => {
            this.isFocused = false
          })
          .onKeyEvent((event: KeyEvent) => {
            if (event.keyCode === 2054 || event.keyCode === 2119) {
              SettingListModel.onSettingItemClick(this.targetPage);
            }
          })

        Text(this.settingTitle)
          ...
      }
      ...

      Row() {
        Text(this.settingEndText)
          ...

        Image('/res/image/ic_settings_arrow.svg')
          ...
      }
      ...
    }
    .linearGradient(this.isTouched || this.isFocused ? {
                                                         angle: 90,
                                                         direction: GradientDirection.Right,
                                                         colors: [[$r("app.color.DCEAF9"), 0.0], [$r("app.color.FAFAFA"), 1.0]]
                                                       } : {
                                                             angle: 90,
                                                             direction: GradientDirection.Right,
                                                             colors: [[$r("sys.color.ohos_id_color_foreground_contrary"), 1], [$r("sys.color.ohos_id_color_foreground_contrary"), 1]]
                                                           })
    ...
  }
}

参考资料

OpenAtom OpenHarmony

OpenAtom OpenHarmony

OpenAtom OpenHarmony

焦点-遥控器及焦点-智慧屏-HarmonyOS应用开发

结语

目前焦点事件支持的组件较少,同时存在一些问题,例如:

1、从当前应用进入到另一个应用,再退回当前应用时焦点消失,需要等一会才会出现

2、在当前页面打开一个弹窗,正常逻辑应该是焦点跑到弹窗上,但是实际情况却是在弹窗下的页面也能走焦

3、页面不能跟随焦点的移动方向进行滑动,当焦点不在当前页面时,页面仍保持不动

4、应用首次启动第一个组件便是获焦态,正常逻辑应为操控键盘或者遥控器才出现焦点

5、Button自带的获焦态样式只有tab键可以触发,方向键不可以,然而遥控器是没有tab键的

【小源笔记】为笔者开发过程中的一些经验分享,旨在解决官方文档过于晦涩难懂或者示例代码不够详细的问题,同时方便笔者日后回顾以及其他开发者更快上手,欢迎评论留言~

往期推荐:

【小源笔记】第一期 | 如何通过替换Full-SDK解决找不到部分API

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
3
收藏 1
回复
举报
回复
    相关推荐