在HarmonyOS鸿蒙Next的TextInput上将电话号码格式化为XXX XXXX XXXX

在HarmonyOS鸿蒙Next的TextInput上将电话号码格式化为XXX XXXX XXXX 按示例6的方式实现,把光标定位到中段,删除号码中间的空格时,应该删除的是空格的前一位,目前删除的是空格,怎么解决

https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-textinput-V5#%E7%A4%BA%E4%BE%8B6


更多关于在HarmonyOS鸿蒙Next的TextInput上将电话号码格式化为XXX XXXX XXXX的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

可参考如下demo:

@Entry
@Component
struct phone_example {
  @State submitValue: string = ''
  @State text: string = ''
  public readonly NUM_TEXT_MAXSIZE_LENGTH = 13
  @State teleNumberNoSpace: string = ""
  @State nextCaret: number = -1 // 用于记录下次光标设置的位置
  @State actualCh: number = -1 // 用于记录光标在第i个数字后插入或者第i个数字前删除
  @State lastCaretPosition: number = 0
  @State lastCaretPositionEnd: number = 0
  controller: TextInputController = new TextInputController()

  isEmpty(str?: string): boolean {
    return str == 'undefined' || !str || !new RegExp("[^\\s]").test(str)
  }

  checkNeedNumberSpace(numText: string) {
    let isSpace: RegExp = new RegExp('[\\+;,#\\*]', 'g')
    let isRule: RegExp = new RegExp('^\\+.*')

    if (isSpace.test(numText)) {
      // 如果电话号码里有特殊字符,就不加空格
      if (isRule.test(numText)) {
        return true
      } else {
        return false
      }
    }
    return true;
  }

  removeSpace(str: string): string {
    if (this.isEmpty(str)) {
      return ''
    }
    return str.replace(new RegExp("[\\s]", "g"), '')
  }

  setCaret() {
    if (this.nextCaret != -1) {
      console.log("to keep caret position right, change caret to", this.nextCaret)
      this.controller.caretPosition(this.nextCaret)
      this.nextCaret = -1
    }
  }

  calcCaretPosition(nextText: string) {
    let befNumberNoSpace: string = this.removeSpace(this.text)
    this.actualCh = 0
    if (befNumberNoSpace.length < this.teleNumberNoSpace.length) { // 插入场景
      for (let i = 0; i < this.lastCaretPosition; i++) {
        if (this.text[i] != ' ') {
          this.actualCh += 1
        }
      }
      this.actualCh += this.teleNumberNoSpace.length - befNumberNoSpace.length
      console.log("actualCh: " + this.actualCh)
      for (let i = 0; i < nextText.length; i++) {
        if (nextText[i] != ' ') {
          this.actualCh -= 1
          if (this.actualCh <= 0) {
            this.nextCaret = i + 1
            break;
          }
        }
      }
    } else if (befNumberNoSpace.length > this.teleNumberNoSpace.length) { // 删除场景
      if (this.lastCaretPosition === this.text.length) {
        console.log("Caret at last, no need to change")
      } else if (this.lastCaretPosition === this.lastCaretPositionEnd) {
        // 按键盘上回退键一个一个删的情况
        for (let i = this.lastCaretPosition; i < this.text.length; i++) {
          if (this.text[i] != ' ') {
            this.actualCh += 1
          }
        }
        for (let i = nextText.length - 1; i >= 0; i--) {
          if (nextText[i] != ' ') {
            this.actualCh -= 1
            if (this.actualCh <= 0) {
              this.nextCaret = i
              break;
            }
          }
        }
      } else {
        // 剪切/手柄选择 一次删多个字符
        this.nextCaret = this.lastCaretPosition // 保持光标位置
      }
    }
  }

  //删除指定位置的字符
  removeCharAt(str: string, index: number) {
    if (index >= 0 && index < str.length) {
      return str.slice(0, index) + str.slice(index + 1);
    }
    return str; // 如果索引超出范围,返回原字符串
  }

  build() {
    Column() {
      Row() {
        TextInput({ text: `${this.text}`, controller: this.controller }).type(InputType.PhoneNumber).height('48vp')
          .onChange((number: string) => {
            this.teleNumberNoSpace = this.removeSpace(number);
            console.log(':::number', number.substring(8, 9))
            let befNumberNoSpace: string = this.removeSpace(this.text)
            //判断 删除场景 去空字符串小于等于11 变动的字符串小于13 判断是否有特殊字符
            if (this.text.length > number.length && this.teleNumberNoSpace.length <= 11
              && number.length < this.NUM_TEXT_MAXSIZE_LENGTH && this.checkNeedNumberSpace(number)) {
              //判断是否删除了空白字符
              let parts = number.split(' ')
              if (parts.length - 1 != 2) {
                //删除第二个空白字符场景
                if (number.substring(8, 9) != ' ') {
                  //012 4567 9012
                  console.log(":::删除后的字符", this.removeCharAt(number, 7))
                  number = this.removeCharAt(number, 7)
                }
                //删除第一个空白字符场景
                if (number.substring(3, 4) != ' ') {
                  //012 4567 9012
                  console.log(":::删除后的字符", this.removeCharAt(number, 7))
                  number = this.removeCharAt(number, 2)
                }
              }
            }
            //更新去空后的电话号码
            this.teleNumberNoSpace = this.removeSpace(number);

            let nextText: string = ""
            if (this.teleNumberNoSpace.length > this.NUM_TEXT_MAXSIZE_LENGTH - 2) {
              nextText = this.teleNumberNoSpace
            } else if (this.checkNeedNumberSpace(number)) {
              if (this.teleNumberNoSpace.length <= 3) {
                nextText = this.teleNumberNoSpace
              } else {
                let split1: string = this.teleNumberNoSpace.substring(0, 3)
                let split2: string = this.teleNumberNoSpace.substring(3)
                nextText = split1 + ' ' + split2
                if (this.teleNumberNoSpace.length > 7) {
                  split2 = this.teleNumberNoSpace.substring(3, 7)
                  let split3: string = this.teleNumberNoSpace.substring(7)
                  nextText = split1 + ' ' + split2 + ' ' + split3
                }
              }
            } else {
              nextText = number
            }
            console.log("onChange Triggered:" + this.text + "|" + nextText + "|" + number)
            if (this.text === nextText && nextText === number) {
              // 此时说明数字已经格式化完成了 在这个时候改变光标位置不会被重置掉
              this.setCaret()
            } else {
              this.calcCaretPosition(nextText)
            }
            this.text = nextText

          })
          .onTextSelectionChange((selectionStart, selectionEnd) => {
            // 记录光标位置
            console.log("selection change: ", selectionStart, selectionEnd)
            this.lastCaretPosition = selectionStart
            this.lastCaretPositionEnd = selectionEnd
          })
      }
    }
    .width('100%')
    .height("100%")
  }
}

更多关于在HarmonyOS鸿蒙Next的TextInput上将电话号码格式化为XXX XXXX XXXX的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,可以通过TextInput组件的onChange事件来实现电话号码的格式化。首先,监听用户输入的内容,然后根据输入的长度和格式进行格式化处理。例如,可以在输入框内容变化时,将输入的电话号码格式化为XXX XXXX XXXX的格式。

具体实现步骤如下:

  1. 监听输入变化:使用onChange事件监听TextInput的输入变化。
  2. 去除非数字字符:将输入内容中的非数字字符(如空格、括号等)去除。
  3. 格式化电话号码:根据去除非数字字符后的内容,按照XXX XXXX XXXX的格式进行分割和插入空格。
  4. 更新输入框内容:将格式化后的电话号码更新到TextInput中。

以下是一个简单的代码示例:

import { TextInput } from '@ohos.xyz'; // 假设的鸿蒙Next TextInput组件

function formatPhoneNumber(input) {
    // 去除所有非数字字符
    const cleaned = input.replace(/\D/g, '');
    // 根据长度进行格式化
    if (cleaned.length > 10) {
        return cleaned.slice(0, 3) + ' ' + cleaned.slice(3, 7) + ' ' + cleaned.slice(7, 11);
    } else if (cleaned.length > 6) {
        return cleaned.slice(0, 3) + ' ' + cleaned.slice(3, 7);
    } else if (cleaned.length > 3) {
        return cleaned.slice(0, 3) + ' ' + cleaned.slice(3);
    }
    return cleaned;
}

function PhoneInput() {
    const [phoneNumber, setPhoneNumber] = useState('');

    const handleInputChange = (event) => {
        const formattedNumber = formatPhoneNumber(event.value);
        setPhoneNumber(formattedNumber);
    };

    return (
        <TextInput
            value={phoneNumber}
            onChange={handleInputChange}
            placeholder="请输入电话号码"
        />
    );
}

在这个示例中,formatPhoneNumber函数负责将输入的电话号码格式化为XXX XXXX XXXX的格式,而handleInputChange函数则负责监听输入变化并更新输入框的内容。

在HarmonyOS鸿蒙Next中,可以通过监听TextInputonChange事件,结合正则表达式对电话号码进行格式化。以下是一个示例代码:

function formatPhoneNumber(input) {
  // 移除所有非数字字符
  let cleaned = input.replace(/\D/g, '');
  // 格式化电话号码为XXX XXXX XXXX
  if (cleaned.length > 3 && cleaned.length <= 7) {
    cleaned = cleaned.slice(0, 3) + ' ' + cleaned.slice(3);
  } else if (cleaned.length > 7) {
    cleaned = cleaned.slice(0, 3) + ' ' + cleaned.slice(3, 7) + ' ' + cleaned.slice(7, 11);
  }
  return cleaned;
}

TextInput({ placeholder: '请输入电话号码' })
  .onChange((value) => {
    const formatted = formatPhoneNumber(value);
    // 更新TextInput的值
    this.setState({ phoneNumber: formatted });
  })

此代码将用户输入的电话号码格式化为XXX XXXX XXXX的格式,并实时更新TextInput的值。

回到顶部