【UI界面开发】基本组件——输入框

文章目录

  • 摘要
  • UGUI之InputField
    • Unity预制组成分析
    • Inspector窗口参数分析
      • 基本设置
      • 扩展设置
      • 事件
  • 自制InputField
    • 分部说明
    • 完整代码

摘要

  • 本文章主要总结UGUI中的InputField的功能,
  • 为了更好地学习它的基本功能,在后面会思考如何利用基本UI实现简易的InputField

UGUI之InputField

Unity预制组成分析

在这里插入图片描述

  • InputField由三个物体组成,其中两个子物体均只有Text组件。而实现功能的核心组件则挂在InputField上。
  • 因此可以知道InputField是基于Text的基本功能,并丰富交互的。

Inspector窗口参数分析

【UI界面开发】基本组件——输入框_第1张图片

  • Input Field依然保持有基本的交互视效功能,因此这里不再重复。这里仅展示InputField独有的部分。
  • 从上图中可以看出,InputField大体可以分成三部分:基本设置、扩展设置、事件

基本设置

  • 基本设置主要的目的是确定关联文本框,设置文本输入限制,包括默认文本,文本长度,文本类型。
  1. Text Component: 文本控件,它将对具体的文本实现实时编辑
  2. Text: 易知是一个string成员,它将直接编辑Text Component中的文本内容,作为默认文本。同样Text Component自身的编辑将不被作用
  3. Character Limit: 字符串长度限制,它是C#中的char类型,因此1表示16位而不是8位
  4. Content Type:文本类型,有标准型,整型,邮箱,密码等,它们会对文本进行处理,包括如整型的输入限制,邮箱类型的输入校验,以及密码类型的文本显示转化等。
  5. Line Type:文本行类型,包括单行,多行等

扩展设置

  • 扩展设置则是有关提醒视效的设置,包括光标闪烁频率,光标宽度,选中文本的背景色等等。

事件

  • 事件包括两个主要事件,一个是文本更改事件,一个是结束编辑事件
  1. 文本更改事件:文本更改过程中实时调用
  2. 结束编辑事件:按下回车等方式结束编辑后调用一次

自制InputField

分部说明

  • 自制的关键在于解决如何在运行的时候输入。一个值得尝试的方法是利用鼠标进入事件来控制组件的聚焦,同时开启一个协程利用Unity自带方案持续监听用户输入,当用户通过指定方式失焦后结束协程。
  • 首先这里不会再实现聚焦等通用交互,因为光标涉及到底层渲染,因此也不予以实现。
  1. 首先根据需求设置对应的参数
[SerializeField] private Text textComponent;
[SerializeField] private string text;
[SerializeField] private int characterLimit;
[SerializeField] private ContentType contentType;
[SerializeField] private LineType lineType;
[SerializeField] private bool readOnly;

public enum ContentType { Standard,Interger,Password};
public enum LineType { SingleLine,MultipleLine};

如图,我们将陆续实现上述功能
2. 实现基本的输入和删除功能
通过观察知道,当我们在控件上点击时进入编辑状态,在控件外点击鼠标或者在编辑后回车将退出编辑状态。这里我们仅实现点击,利用接口IPointerEnter和IPointerExit来实现设置当前聚焦状态。再利用Update去判断Input输入

//使得文本组件的文本与该组件文本一致,即禁止绕过该组件直接编辑文本框内容
if (textComponent != null) textComponent.text = text;
if (readOnly) return;

//按下左键,根据聚焦情况设置编辑状态
if(Input.GetMouseButtonDown(0))
{
      isEditing = isFocus;
      print(isEditing);
}

if (!isEditing) return;

//获取输入
if (Input.GetKeyDown(KeyCode.Backspace)&&text.Length>0)
    text = text.Substring(0, text.Length - 1);
else
    text += Input.inputString;

如图
3. 实现字符串长度限制
通过观察可以知道,UGUI中的InputField该参数为0时则不限制。
限制的实现比较简单,这里直接给出参考代码:

//限制长度
if(characterLimit!=0 && text.Length > characterLimit)
{
   text = text.Substring(0, characterLimit);
}

如图所示
4. 实现输入类型控制
我这里只定义了标准、整数、密码三种类型。其中标准类型不做任何限制,整型则只支持输入整型,密码则是会将数值转移存储,而表面的数值用星号代替。

 //获取输入
if (Input.GetKeyDown(KeyCode.Backspace))
{
   if(realText.Length > 0)
   realText = text.Substring(0, text.Length - 1);
}
else
{
	//如果是整型类型,则要限制输入
	if (contentType == ContentType.Interger)
	{
   		var input = Input.inputString;
   		int v;
   		if (int.TryParse(input, out v))//如果可以转化为整数则写入
       		realText += input;
	}
	else realText += Input.inputString;
}

//限制长度
if(characterLimit!=0 && realText.Length > characterLimit)
{
    realText = realText.Substring(0, characterLimit);
}

//将真实值根据设置显示出来
if (contentType == ContentType.Password)
{
     //密码则输出同等位数的星号
     text = new string('*', realText.Length);
}
else text = realText;

以上是重构后的代码
5. 实现行数设置
我只提供了简单的单行文本和多行文本。基本实现思路是是否支持接收换行符。

var input = Input.inputString;
//判断是否是特殊字符
if (Input.GetKeyDown(KeyCode.Return))
{
   if (lineType == LineType.MultipleLine) { realText += '\n'; }
}
else
{
    //如果是整型类型,则要限制输入
    if (contentType == ContentType.Interger)
    {
       int v;
       if (int.TryParse(input, out v))//如果可以转化为整数则写入
            realText += input;
    }
    else realText += input;
}

以上是重构并新增行数类型功能的部分
6. 实现事件部分
如下所示,我新增了两个委托成员

public Action<string> onValueChaned { set; get; }
public Action<string> onEndEdit { set; get; }

其中onValueChanged将在每次字符串发生任何变化时执行一次。而onEndEdit则在退出编辑状态时执行一次。其中参数是最新的字符串内容

完整代码

public class CInputField : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler
    {
        [SerializeField] private Text textComponent;
        [SerializeField] private string text;
        [SerializeField] private int characterLimit;
        [SerializeField] private ContentType contentType;
        [SerializeField] private LineType lineType;
        [SerializeField] private bool readOnly;

        private bool isFocus;
        private bool isEditing;
        private string realText;

        public Action<string> onValueChaned { set; get; }
        public Action<string> onEndEdit { set; get; }

        public void OnPointerEnter(PointerEventData eventData)
        {
            isFocus = true;
        }

        public void OnPointerExit(PointerEventData eventData)
        {
            isFocus = false;
        }

        private void Awake()
        {
            if (characterLimit < 0) characterLimit = 0;
        }
        private void Update()
        {
            //使得文本组件的文本与该组件文本一致,即禁止绕过该组件直接编辑文本框内容
            if (textComponent != null) textComponent.text = text;

            if (readOnly) return;

            //按下左键,根据聚焦情况设置编辑状态
            if(Input.GetMouseButtonDown(0))
            {
                //执行结束事件
                if(isEditing&&!isFocus)
                {
                    print("End Edit!");
                    onEndEdit?.Invoke(realText);
                }
                isEditing = isFocus;
                print(isEditing);
            }

            if (!isEditing) return;

            //获取输入
            if (Input.GetKeyDown(KeyCode.Backspace))
            {
                if(realText.Length > 0)
                    realText = text.Substring(0, text.Length - 1);
            }
            else
            {
                var input = Input.inputString;
                //判断是否是特殊字符
                if (Input.GetKeyDown(KeyCode.Return))
                {
                    if (lineType == LineType.MultipleLine) { realText += '\n'; }
                }
                else
                {
                    //如果是整型类型,则要限制输入
                    if (contentType == ContentType.Interger)
                    {
                        int v;
                        if (int.TryParse(input, out v))//如果可以转化为整数则写入
                            realText += input;
                    }
                    else realText += input;
                }
            }

            //限制长度
            if(characterLimit!=0 && realText.Length > characterLimit)
            {
                realText = realText.Substring(0, characterLimit);
            }

            //执行变化事件
            if(text!=realText)
            {
                print("value changed!");
                onValueChaned?.Invoke(realText);
            }

            //将真实值根据设置显示出来
            if (contentType == ContentType.Password)
            {
                //密码则输出同等位数的星号
                text = new string('*', realText.Length);
            }
            else text = realText;
        }

        public enum ContentType { Standard,Interger,Password};
        public enum LineType { SingleLine,MultipleLine};
    }

你可能感兴趣的:(#,UI界面开发,ui,unity)