文档管理中心

使用customKeyboard设置自定义键盘时,弹出失败

问题现象

自定义键盘通过focusController获取焦点的时候,弹出的键盘是系统键盘,而不是预期的自定义键盘。

问题代码示例参考如下:

@Entry
@Component
struct CustomKeyboardPage {
  controller: RichEditorController = new RichEditorController()
  @State keyboardVisible: boolean = false
  customKeyboard: CustomBuilder = () => {
    this.buildCustomKeyboard()
  }

  build() {
    Column({ space: 10 }) {
      RichEditor({ controller: this.controller })
        .id('RichEditor')
        .height(200)
        .backgroundColor('#99e2dddd')
        .width('90%')
        .borderRadius(15)
        .customKeyboard(this.keyboardVisible ? this.customKeyboard :
          undefined) // 这种写法点击「切换自定义键盘」无法正常调出自定义键盘,弹出的是系统键盘
      Button('切换自定义键盘').onClick(() => {
        this.keyboardVisible = true
        this.getUIContext().getFocusController().requestFocus('RichEditor')
      })
      Button('切换至系统键盘')
        .onClick(() => {
          this.keyboardVisible = false
        })
    }
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }

  // 自定义键盘
  @Builder
  buildCustomKeyboard() {
    Row() {
      Text('自定义键盘')
    }
    .justifyContent(FlexAlign.Center)
    .height('200')
    .width('100%')
    .backgroundColor('#990946cd')
  }
}

效果预览

背景知识

问题定位

  1. this.customKeyboard函数未用@Builder装饰器修饰。

    customKeyboard属性的第一个参数CustomBuilder用于自定义UI描述,必须结合@Builder使用。

  2. 由于customKeyboard属性不是实时渲染,在更改this.keyboardVisible变量后,customKeyboard需要更新渲染。

    该问题代码中this.getUIContext().getFocusController().requestFocus("RichEditor")是在当前帧生效。更改this.keyboardVisible变量后,customKeyboard还没有完成渲染,因此第一次依旧会弹出系统键盘。使用focusControl.requestFocus("RichEditor")让控件在下一帧获取焦点即可,此时customKeyboard已完成渲染。

分析结论

该问题代码存在以下两个问题:

  1. customKeyboard属性内this.customKeyboard函数未使用@Builder装饰器修饰,导致customKeyboard属性设置失效,无法弹出自定义键盘。
  2. this.getUIContext().getFocusController().requestFocus("RichEditor")获取焦点是在当前帧生效,由于更改keyboardVisible变量后,customKeyboard未更新渲染完成,导致第一次获取焦点无法弹出自定义键盘。

修改建议

  1. 采用@Builder装饰器自定义构建函数。修改customKeyboard函数代码:
    @Builder
    customKeyboard() {
      this.buildCustomKeyboard();
    }
  2. customKeyboard属性更新后再获取焦点。采用focusControl.requestFocus方法代替this.getUIContext().getFocusController().requestFocus方法获取组件焦点。
    Button('切换自定义键盘')
      .onClick(() => {
        this.keyboardVisible = true;
        focusControl.requestFocus('RichEditor');
      });

完整示例参考如下:

@Entry
@Component
struct CustomKeyboardPage {
  controller: RichEditorController = new RichEditorController();
  @State keyboardVisible: boolean = false;

  @Builder
  customKeyboard() {
    this.buildCustomKeyboard();
  }

  build() {
    Column({ space: 10 }) {
      RichEditor({ controller: this.controller })
        .id('RichEditor')
        .height(200)
        .backgroundColor('#99e2dddd')
        .width('90%')
        .borderRadius(15)
        .customKeyboard(this.keyboardVisible ? this.customKeyboard :
          undefined); // 这种写法点击「切换自定义键盘」无法正常调出自定义键盘,弹出的是系统键盘
      Button('切换自定义键盘')
        .onClick(() => {
          this.keyboardVisible = true;
          focusControl.requestFocus('RichEditor');
        });
      Button('切换至系统键盘')
        .onClick(() => {
          this.keyboardVisible = false;
        });
    }
    .width('100%')
    .justifyContent(FlexAlign.Center);
  }

  // 自定义键盘
  @Builder
  buildCustomKeyboard() {
    Row() {
      Text('自定义键盘');
    }
    .justifyContent(FlexAlign.Center)
    .height('200')
    .width('100%')
    .backgroundColor('#990946cd');
  }
}
搜索
请输入您想要搜索的关键词