输入字符时光标总会跳转到最后
==============

#### 问题现象

用户将光标移动到内容中间，执行输入或删除操作后，光标总是跳到最后。

#### 背景知识

[TextInput](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-textinput)：单行文本输入框组件。

[onChange](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-textinput#onchange)：输入内容发生变化时，触发该回调。

[caretPosition](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-textinput#caretposition10)：设置光标位置。

#### 问题定位

1.  使用ArkUI Inspector查看组件实现方式，确认为TextInput组件。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e5/v3/2UpV3wjOQU-0Fbx4Wb_yXg/zh-cn_image_0000002658961877.png?HW-CC-KV=V1&HW-CC-Date=20260709T133947Z&HW-CC-Expire=86400&HW-CC-Sign=9FF3523806E1131C8DA692BDE0E8318CCA9827A811BB9B155614817A5C5C3ADD "点击放大")
    
2.  检查TextInput的onChange事件，没有使用caretPosition设置光标位置，根据onChange函数的定义，该回调会在输入值变化后被触发，所以中间执行插入或删除操作改变value值，导致数据需要重新格式化，也就是重新赋值，此时光标会位于输入值的末尾。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/78/v3/AdaHBNTxQ_u58r0qOjyB0A/zh-cn_image_0000002628602666.png?HW-CC-KV=V1&HW-CC-Date=20260709T133947Z&HW-CC-Expire=86400&HW-CC-Sign=041A6390E7C2C93BA1C35A4025BA3DAF13499E9DF22798000746C41AEE7A0032)
    

#### 分析结论

onChange函数的规格，未在value值变化之前获取光标位置并重新定位。

#### 修改建议

参考以下Demo正确展示光标位置：

@Entry
@Component
struct TextInputExample {
  controller: TextInputController = new TextInputController();
  @State inputValue: string = '';
  @State currentCaretOffset: number = 0;

  _//_ _自定义键盘组件_
  @Builder
  CustomKeyboardBuilder() {
    Column() {
      _//_ _数字键盘_
      Grid() {
        ForEach(\[1, 2, 3, 4, 5, 6, 7, 8, 9, '\*', 0, '#'\], (item: number | string) => {
          GridItem() {
            Button(\`${item}\`)
              .width(110)
              .backgroundColor('#ffffff')
              .fontColor('#000000')
              .onClick(() => {
                _//_ _在当前光标位置插入字符_
                this.inputValue = this.inputValue.slice(0, this.currentCaretOffset) +
                  item + this.inputValue.slice(this.currentCaretOffset);
                this.currentCaretOffset++;
              })
          }
        })
      }
      .maxCount(3)
      .columnsGap(10)
      .rowsGap(10)
      .padding(5)
    }
    .backgroundColor(Color.Gray)
    .margin({ bottom: 36 })
    .padding({ top: 16, bottom: 16 })
  }

  build() {
    Column() {
      TextInput({ controller: this.controller, text: $$this.inputValue })
        .onChange(() => {
          this.controller.caretPosition(this.currentCaretOffset);
        })
        .onEditChange((isEditing: boolean) => {
          if (isEditing) {
            _//_ _开始编辑时同步光标位置_
            const caret = this.controller.getCaretOffset();
            this.currentCaretOffset = caret.index;
          }
        })
        .onTextSelectionChange((selectionStart) => {
          _//_ _记录光标位置_
          this.currentCaretOffset = selectionStart;
        })
        .onPaste((pasteValue: string) => {
          _//_ _处理粘贴功能_
          if (pasteValue && pasteValue.length > 0) {
            this.inputValue = this.inputValue.slice(0, this.currentCaretOffset) +
              pasteValue + this.inputValue.slice(this.currentCaretOffset);
            this.currentCaretOffset += pasteValue.length;
          }
          _//_ _返回true表示已处理粘贴事件_
          return true;
        })
        .customKeyboard(this.CustomKeyboardBuilder())
        .margin(10)
        .width('100%')
        .padding(10)
        .borderRadius(30)
    }.padding(16)
  }
}

效果展示：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e5/v3/k7dVa3HWQ_ilxJHhXDMGDA/zh-cn_image_0000002658841937.png?HW-CC-KV=V1&HW-CC-Date=20260709T133947Z&HW-CC-Expire=86400&HW-CC-Sign=6AAF847D46E1C37093E0BAF77288E488B6E37BF076A5BD0F995CF4BD2237D60B "点击放大")