1 关键字

TextInput; inputFilter; 初始值

2 问题描述

2.1 运行环境

系统版本:3.2Release
开发板:rk3568

2.2 问题现象:

TextInput组件设置inputFilter(通过正则表达式设置输入过滤器。匹配表达式的输入将允许显示,不匹配的输入将被过滤。)但是对于TextInput组件的初始值,这个规则未生效。

...
TextInput({text:"12789"}) //预期显示12,实际显示12789
.inputFilter('[1-5]')
...

3 问题原因

3.1 正常机制

TextInput组件设定初始值,以及其后接受字符输入时,检验值是否符合inputFilter所限定的规则

3.2 异常机制

TextInput组件设定初始值时,未检验值是否符合inputFilter所限定的规则

4 解决方案

修改文件 foundation\arkui\ace_engine\frameworks\core\components_ng\pattern\text_field\text_field_pattern.cpp 的 TextFieldModelNG::SetInputFilter 方法:

void TextFieldModelNG::SetInputFilter(const std::string& value, const std::function<void(const std::string&)>& onError)
{
    ACE_UPDATE_LAYOUT_PROPERTY(TextFieldLayoutProperty, InputFilter, value);
    auto eventHub = ViewStackProcessor::GetInstance()->GetMainFrameNodeEventHub<TextFieldEventHub>();
    CHECK_NULL_VOID(eventHub);
    eventHub->SetOnInputFilterError(onError);
   +auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
   +auto pattern = frameNode->GetPattern<TextFieldPattern>();
   +pattern->InitEditingValueTextWithFilter();
}

TextFieldPattern.InitEditingValueTextWithFilter定义:
void TextFieldPattern::InitEditingValueTextWithFilter()
{
    auto content = textEditingValue_.text;
    ClearEditingValue();
    InsertValue(content);
    auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
    layoutProperty->UpdateNeedFireOnChangeWhenCreate(true);
}

5 定位过程

在输入框接受到用户输入时,执行方法TextFieldPattern::InsertValue(foundation\arkui\ace_engine\frameworks\core\components_ng\pattern\text_field\text_field_pattern.cpp)
这个方法内处理一些校验例如检测maxLength,inputFilter的逻辑,最后设置输入框显示在UI界面上值。

检测maxLength:

auto originLength = static_cast<uint32_t>(textEditingValue_.GetWideText().length());
if (originLength >= GetMaxLength()) {
        LOGW("Max length reached");
        return;
}

检测宽字符maxLength

auto wideInsertValue = StringUtils::ToWstring(insertValue);
if (originLength + wideInsertValue.length() >= GetMaxLength()) {
        valueToUpdate = StringUtils::ToString(wideInsertValue.substr(0, GetMaxLength() - originLength));
} else {
        valueToUpdate = insertValue;
 }

检测将被输入的字符是否符合inputFilter规则

EditingValueFilter(valueToUpdate, result);
...
void TextFieldPattern::EditingValueFilter(std::string& valueToUpdate, std::string& result)
{
    //获取用户设置的inputFilter属性
    auto inputFilter = textFieldLayoutProperty->GetInputFilterValue("");
    bool textChanged = false;
    //进行正则匹配
    if (!inputFilter.empty()) {
        textChanged |= FilterWithRegex(inputFilter, valueToUpdate, result);
    }
    ...
}

应用ets代码:

TextInput({text:"12789"}) //预期显示12,实际显示12789,
.inputFilter('[1-5]')

最终会编译为以下:

TextInput.create({text:"12789"})
TextInput.inputFilter('[1-5]')

inputFilter在napi层方法入口逻辑在JSTextField::SetInputFilter,因此,在用户设置inputFilter属性时,在对应方法(TextFieldModelNG::SetInputFilter)里针对初始值也做此检测处理。

6 知识分享

inputFilter通过正则表达式设置输入过滤器。匹配表达式的输入允许显示,不匹配的输入将被过滤。仅支持单个字符匹配,不支持字符串匹配。参数支持Object类型,可设置属性值:

  • value:设置正则表达式。
  • error(可选):正则匹配失败时,返回被过滤的内容。
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐