【每日学点鸿蒙知识】自定义键盘光标、Cavas绘制、XComponent触发键盘抬起等

【每日学点鸿蒙知识】24.08.25

【每日学点鸿蒙知识】自定义键盘光标、Cavas绘制、XComponent触发键盘抬起等

1、基于自定义键盘如何设置光标位置?

可以参考如下代码:

复制代码
class MyKeyboardController {
  public onInputChanged?: (value: string) => void
  public inputController = new TextInputController()
  public carePosition = -1
  private inputValue = ''

  onKeyClicked(key: string) {
    const index = this.inputController.getCaretOffset().index
    if (key === 'A' || key === 'B') {
      this.setInputValue(this.inputValue.substring(0, index) + key + this.inputValue.substring(index))
      this.carePosition = index + 1
    } else if (key === '<') {
      if (index > 0) {
        this.setInputValue(this.inputValue.substring(0, index - 1) + this.inputValue.substring(index))
        this.carePosition = index - 1
      }
    }
  }

  setInputValue(value: string) {
    if (this.carePosition >= 0) {
      this.inputController.caretPosition(this.carePosition)
      this.carePosition = -1
    }
    if (this.inputValue === value) {
      return;
    }
    this.inputValue = value
    if (this.onInputChanged) {
      this.onInputChanged(value)
    }
  }
}

@Component
struct MyKeyboardA {
  controller?: MyKeyboardController
  private keys = ['A', 'B', '<']

  build() {
    Row() {
      ForEach(this.keys, (v: string) => {
        Text(v)
          .layoutWeight(1)
          .height(44)
          .borderWidth(1)
          .borderColor(Color.Gray)
          .borderRadius(4)
          .onClick(() => {
            this.controller?.onKeyClicked(v)
          })
      })
    }
    .height(300)
      .backgroundColor(Color.Gray)
  }
}

@Entry
@Component
export struct RichKeyPage {
  keyboardController = new MyKeyboardController()
  @State text: string = ''

  aboutToAppear(): void {
    this.keyboardController.onInputChanged = (value) => {
      this.text = value
    }
  }

  build() {
    Column({ space: 20 }) {
      TextInput({ text: this.text, controller: this.keyboardController.inputController })
        .width('100%')
        .height(44)
        .customKeyboard(this.myKeyboardA())
        .onChange((value) => {
          this.keyboardController.setInputValue(value)
        })
      Button('点击直接更改输入框内容')
        .width('100%')
        .height(44)
        .onClick(() => {
          this.text = '12345678'
        })
    }
  }

  @Builder
  myKeyboardA() {
    MyKeyboardA({ controller: this.keyboardController })
  }
}

2、如何实现镂空效果?

利用canvas绘制镂空圆形然后使用Stack组件叠加在需要透明展示的区域上,参考代码如下:

复制代码
@Entry
@Component
struct Page {
  @State message: string = 'Hello World';
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  @State circleCenterX: number = 0
  @State circleCenterY: number = 0
  @State circleRadius: number = 100

  build() {
    Row() {
      Column() {
        Stack() {
          Image($r('app.media.startIcon')).height(300)
          // 使用Canvas绘制遮罩覆盖在图片、相机等上面
          Canvas(this.context)
            .width('100%')
            .height('100%')
            .backgroundColor('#00000000')
            .onReady(() => {
              this.circleCenterX = this.context.width / 2
              this.circleCenterY = this.context.height / 2
              this.context.fillStyle = '#aa000000'
              // 绘制原型路径进行半透明填充
              this.context.beginPath()
              this.context.moveTo(0, 0)
              this.context.lineTo(0, this.context.height)
              this.context.lineTo(this.context.width, this.context.height)
              this.context.lineTo(this.context.width, 0)
              this.context.lineTo(0, 0)
              this.context.arc(this.circleCenterX, this.circleCenterY, this.circleRadius, 0, Math.PI * 2)
              this.context.fill()
              this.context.closePath()
            })
        }.width('1456px')
        .height('1456px')
      }
      .width('100%')
    }
    .height('100%')
  }
}

3、如何使用canvas绘制圆角矩形?

利用CanvasRenderingContext2D对象的arc绘制弧形路径,结合lineTo方法绘制直线进行封装,参考代码如下:

复制代码
@Entry
@Component
struct Page {
  @State message: string = 'Hello World';
  private readonly settings: RenderingContextSettings = new RenderingContextSettings(true);
  private readonly ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  /**
   * 绘制圆角矩形
   * @param {* 必填} x x坐标
   * @param {* 必填} y y坐标
   * @param {* 必填} width 宽度
   * @param {* 必填} height 高度
   * @param {* 必填} radius 圆角半径
   * @param {* 非必填 默认值:'#456'} strokeColor 边框颜色
   * @param {* 非必填 无默认值} fillColor 填充颜色
   * @param {* 非必填 默认值:[]实线} lineDash 边框样式
   */
  drawRoundRect(x: number, y: number, width: number, height: number, radius: number, strokeColor?: string, fillColor?: string, lineDash?: []) {
    strokeColor = strokeColor || '#333';
    lineDash = lineDash || [];
    this.ctx.beginPath();
    // 是否是虚线如果有则设置
    this.ctx.setLineDash(lineDash);
    // 绘制第一段圆弧路径
    this.ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
    // 绘制第一段直线路径
    this.ctx.lineTo(width - radius + x, y);
    // 绘制第二段圆弧路径
    this.ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);
    // 绘制第二段直线路径
    this.ctx.lineTo(width + x, height + y - radius);
    // 绘制第三段圆弧路径
    this.ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI / 2);
    // 绘制第三段直线路径
    this.ctx.lineTo(radius + x, height + y);
    // 绘制第四段圆弧路径
    this.ctx.arc(radius + x, height - radius + y, radius, Math.PI / 2, Math.PI);
    // 绘制第四段直线路径
    this.ctx.lineTo(x, y + radius);
    // 设置画笔颜色
    this.ctx.strokeStyle = strokeColor;
    // 描边绘制
    this.ctx.stroke();
    if (fillColor) {
      // 如果有填充颜色泽填充
      this.ctx.fillStyle = fillColor;
      this.ctx.fill();
    }
    this.ctx.closePath();
  }

  build() {
    Row() {
      Column() {
        Canvas(this.ctx)
          .width('100%')
          .height('100%')
          .onReady(() => {
            this.drawRoundRect(50, 50, 100, 100, 10)
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

4、为什么XComponent有时候无法触发键盘的抬起事件?

问题描述:

  • 在使用Native XComponent关于键盘事件的接口时,发现alt按键的抬起状态无法获取;
  • 当前通过快捷键拉起其他应用或切换至其他应用时,因为窗口失焦,导致xComponent无法接收到按键的抬起事件,导致应用内按键异常。

解答:

  • 可以通过hdc shell hidumper -s 3101 -a -s观察到所有被订阅的按键,可以看到alt被订阅了。这种情况下alt的抬起事件会被其他订阅的应用消费掉。
  • 在窗口失焦时,应用感知不到键盘事件,这是属于规格,在后面将会开放一个新的接口能力,新接口将会在键盘/鼠标事件触发时,返回的参数里会提供当前键盘/鼠标上处于按压态的键位/按钮,提供了这些后,其他的由应用侧自行处理逻辑。

5、绑定类型的组件和foreach的正确连用方式?

问题描述:

bindSheet和foreach合用的问题,$$this.isShow会弹出两次半模态,如果是this.isShow,则会半模态弹出的次数是数组的长度数,如何在某一个foreach中的item点击的时候只弹出一个弹窗。

解答:

关键代码:给每一个弹窗都绑定一个@State修饰的变量,有很多个弹窗的话,这里用数组就很方便。

相关推荐
春日见1 天前
车辆动力学:前后轮车轴
java·开发语言·驱动开发·docker·计算机外设
PHOSKEY1 天前
光子精密QM系列闪测仪在鼠标电路板部件质量控制中的核心应用
计算机外设
墩墩冰1 天前
计算机图形学 分析选择缓冲区中的数字
计算机外设
UI设计兰亭妙微1 天前
中车株州所显示器界面设计
计算机外设·界面设计
墩墩冰1 天前
计算机图形学 多视区的显示
计算机外设
墩墩冰1 天前
计算机图形学 GLU库中的二次曲面函数
计算机外设
墩墩冰1 天前
计算机图形学 利用鼠标实现橡皮筋技术
计算机外设
企鹅侠客3 天前
鼠标键盘按键统计工具
计算机外设·键盘·鼠标
华一精品Adreamer4 天前
便携式显示器供应链与成本结构:挑战与机遇
计算机外设
开开心心就好4 天前
图片校正漂白工具永久免费,矫正实时预览
网络·人工智能·windows·计算机视觉·计算机外设·电脑·excel