「Unity3D」TextMeshPro使用TMP_InputField实现,输入框高度自动扩展与收缩

先看实现效果:

要实现这个效果,有三个方面的问题需要解决:

第一,输入框的高度扩展,内部子元素会随着锚点,拉伸变形------要解决这个问题,需要将内部元素改变父类,然后增加父类高度,再恢复父类,这样内部元素(如图中两个按钮),就不会随着高度增加,而拉伸变形。类似代码如下:

cs 复制代码
private void ChangeInputHeight(float heightChange)
{
    // disable the effect of parent size changes on child layouts
    this.finishRecordRT.SetParent(null);
    this.recordRT      .SetParent(null);

    if (heightChange != 0.0f)
    {
        this.inputFieldRT.SetRelativeSizeY(heightChange);
        this.inputBarHeightChange += heightChange;
    }
    else 
    {
        this.inputFieldRT.SetRelativeSizeY(-this.inputBarHeightChange);
        this.inputBarHeightChange = 0.0f;
    }

    this.finishRecordRT.SetParent(this.inputBarRT);
    this.recordRT      .SetParent(this.inputBarRT);
}

第二,注册inputField.onValueChanged 去监听,输入框的文本变化,并通过inputField.textComponent.textInfo的行变化,去判断换行发生。

cs 复制代码
private void OnInputFieldValueChanged(string text)
{
    var textInfo  = this.inputField.textComponent.textInfo;
    var lineCount = textInfo.lineCount;

    if (this.inputFieldPreTextLineCount != lineCount)
    {
        this.ChangeInputHeight(this.inputFieldLineHeight * (lineCount - this.inputFieldPreTextLineCount));
        this.inputFieldPreTextLineCount = lineCount;
    }
}

这里需要记录之前的行数,即inputFieldPreTextLineCount,然后对比变化后的行数,就可以知道是否换行,以及换了几行。

第三,InputField换行后(输入换行符),无法直接触发行数变化,需要输入一个字符后才行,所以需要自行判断,键入了换行符。但删除换行符后,就会触发行数变化,这个删除逻辑就是需要的。

cs 复制代码
    if (this.inputFieldPreTextLineCount != lineCount)
    {
        this.ChangeInputHeight(this.inputFieldLineHeight * (lineCount - this.inputFieldPreTextLineCount));
        this.inputFieldPreTextLineCount = lineCount;
    }
    else
    {
        // inputField.text equal to text, not equal to inputField.textComponent.text (textInfo)
        // when adds    chars, the textInfo.characterCount equal to the text.Length
        // when removes chars, the textInfo.characterCount is more than text.Length (because adds extra space \u200B)
        if (textInfo.characterCount == text.Length && text[^1] == '\n')
        {
            this.ChangeInputHeight(this.inputFieldLineHeight);
            ++this.inputFieldPreTextLineCount;
        }
    }

这里增加的逻辑就是:当行数没变的时候,需要检测text的最后一个字符,是否是换行符------如果是,就增加高度,而删除则可以通过行数变化处理,包括一次删除多行。

为什么要加一个textInfo.characterCount == text.Length的判断?

因为,只有在输入字符的时候,才会成立------而删除字符的时候不成立,这样就会剔除,删除换行符是最后一个,但还没删除它,此时行数也没变化。

而之所以,删除字符的时候不成立------是因为,在删除字符的时候,InputField 的代码显示,会增加看不见的标识字符,即**\u200B** ------因此,inputField.textComponent.text(textInfo) 与**text(inputField.text)**的内容会不一致。

相关推荐
Martina_03214 天前
AI生成3D场景导入 Unity/Unreal 后,NPC 总串层?用6步检查导航高度与跨层连接
人工智能·游戏·数学建模·3d·unity·自然语言处理·aigc
小贺儿开发4 天前
Unity 局域网遥控幻灯片展示工具 3.0
科技·http·unity·工具·ppt·通信·网页
WarPigs6 天前
Unity对象不应该使用null传播的问题
unity
每日出拳老爷子7 天前
【VR】【Unity】抓走转放系列21|一天搭完门和抽屉工具槽:小场景按这个次序拼装
unity·vr·驱动·排错·snap zone
淡海水8 天前
02-02-原理篇-分代GC
算法·unity·c#·游戏引擎·.net·gc
小贺儿开发8 天前
Unity 文物新生 会讲故事的文物展墙
人工智能·科技·unity·ai·视频·互动·演示
淡海水8 天前
02-03-原理篇-大对象堆
unity·c#·游戏引擎·.net·gc
WarPigs9 天前
Unity在Create菜单添加创建自定义脚本模板选项
unity
淡海水9 天前
02-01-原理篇-Mark-Sweep与变种算法
算法·unity·c#·游戏引擎·.net·gc
babywang09 天前
Unity笔记--塔防游戏中的ECS架构:从原理到实战的全面解析
unity·ecs架构