[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};
}