首先需要实现一个自定义的input组件--MyInputField,因为unity默认的inputfield组件默认都是唤起系统键盘,所以需要重新写一个组件,继承自Input Field和IPointerClickHandler
public class MyInputField : InputField, IPointerClickHandler
{
public class ClickEvent : UnityEvent {}
private ClickEvent _onClickEvent = new ClickEvent();
public ClickEvent OnFocused
{
get { return _onClickEvent; }
set { _onClickEvent = value; }
}
public void OnPointerClick(PointerEventData eventData)
{
if (isFocused)
{
print("isFocused");
_onClickEvent?.Invoke();
}
}
}
使用自定义的MyInputField组件去唤起自定义键盘
public MyInputField myinput;//自定义输入
private static KeyboardParam KeyboardPara = new KeyboardParam(""); //键盘参数
public GameObject keyboardObj;//键盘预制体实例化的对象
void Awake()
{
if(myinput==null) myinput=transform.GetOrAddComnent();
}
void inputAction()
{
myinput.text = "";
myinput.placeholder.GetComponent().text = Placeholder;
myinput.OnFocused.RemoveAllListeners();
myinput.OnFocused.AddListener(() =>
{
ClickText();
});
void ClickText()
{
KeyboardPara.InputStr = input.text;
CnKeyboard cnKeyboard = keyboardObj.GetComponentInChildren();
if (cnKeyboard!=null)
cnKeyboard.ShowKeyboard(KeyboardPara, EditCallBack);
//EditCallBack回调,返回输入的值kbpara.OutputStr赋值给自定义输入框
void EditCallBack(KeyboardParam kbpara)
{
myinput.text = kbpara.OutputStr;
}
}
}
cnKeyboard脚本的初始化时间比较长,需要等待其Awake和Start执行完之后执行ShowKeyboard才不会出错,可以使用UniTask封装一下,将Awake和Start里面的逻辑封装一下,等这些操作完成之后再执行ShowKeyboard,以免操作过快未初始化完就调用导致的error。
using UnityEngine;
using hyjiacan.py4n;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace InnerKeyboard
{
//键盘参数类
public class KeyboardParam
{
public string InputStr;
public string OutputStr;
public KeyboardParam(string InStr, string OutStr = "")
{
InputStr = InStr;
OutputStr = OutStr;
}
}
//委托事件类
public class EventCommon
{
public delegate void CallBack(T para);
public delegate void NorEvent();
}
public class CnKeyboard : MonoBehaviour
{
private RectTransform KeyboardWindow;
private GameObject ComBtnPref;
private Transform Line0, Line1, Line2, Line3;
private Button BackSpaceBtn, ShiftBtn, SpaceBtn, CancelBtn, EnterBtn, LangugeBtn, ClearBtn;
private Image ShiftBG;
private string[][] Line0_KeyValue = {
new string[]{"`","1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "="},
new string[]{"·", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+" }};
private string[][] Line1_KeyValue = {
new string[]{"q","w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"},
new string[]{"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "{", "}", "|" }};
private string[][] Line2_KeyValue = {
new string[]{"a","s", "d", "f", "g", "h", "j", "k", "l", ";", "'"},
new string[]{"A", "S", "D", "F", "G", "H", "J", "K", "L", ":", "\""}};
private string[][] Line3_KeyValue = {
new string[]{"z","x", "c", "v", "b", "n", "m", ",", ".", "/"},
new string[]{"Z", "X", "C", "V", "B", "N", "M", "<", ">", "?"}};
private string NewEditeString = "";
[HideInInspector]
public bool isShift = false;
private bool isShiftLock = false;
private float ShiftTime = 0f;
private Color32 LockColor = new Color32(127, 171, 179, 255);
private event EventCommon.NorEvent OnShiftOn = null;
private event EventCommon.NorEvent OnShiftOff = null;
private KeyboardParam KeyboardPara = null;//键盘参数
private EventCommon.CallBack call = null; //回调函数
private static CnKeyboard instance = null;
bool isCn = false;
Text LanText, PinYinText;
string PinYinStr; //拼音串
string[] HanZiArr = new string[] { }; //汉子的结果值;
List HanZiTextList = new List();
int NowPage = 0, TotalPage = 0, PageSize = 10;
Button LastBtn, NextBtn;
GameObject CnObj;
public static CnKeyboard Instance
{
get { return instance; }
}
//初始化部分节点
private void Awake()
{
KeyboardWindow = this.transform.GetComponent();
ComBtnPref = Resources.Load("KeyItem");
Line0 = KeyboardWindow.Find("KB_BG/KeyBtns/ComBtnLine0");
Line1 = KeyboardWindow.Find("KB_BG/KeyBtns/ComBtnLine1");
Line2 = KeyboardWindow.Find("KB_BG/KeyBtns/ComBtnLine2");
Line3 = KeyboardWindow.Find("KB_BG/KeyBtns/ComBtnLine3");
BackSpaceBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine3/BackSpaceBtn").GetComponent();
ShiftBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine3/ShiftBtn").GetComponent();
SpaceBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/SpaceBtn").GetComponent();
CancelBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/right/CancelBtn").GetComponent();
EnterBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/right/EnterBtn").GetComponent();
LangugeBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/left/LangugeBtn").GetComponent();
ClearBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/left/ClearBtn").GetComponent();
LanText = LangugeBtn.transform.Find("Text").GetComponent();
ShiftBG = ShiftBtn.GetComponent();
LastBtn = KeyboardWindow.Find("KB_BG/CnBG/Last").GetComponent();
NextBtn = KeyboardWindow.Find("KB_BG/CnBG/Next").GetComponent();
PinYinText = KeyboardWindow.Find("KB_BG/CnBG/Pinyin").GetComponent();
CnObj = KeyboardWindow.Find("KB_BG/CnBG").gameObject;
for (int i = 0; i < PageSize; i++) {//选项添加
Text temp = KeyboardWindow.Find("KB_BG/CnBG/HanZis/HanZi" + i).GetComponent();
if (temp != null)
HanZiTextList.Add(temp);
}
}
void Start()
{
KeyboardWindow.localScale = Vector3.zero;
InitComBtn();
//事件绑定
BackSpaceBtn.onClick.AddListener(ClickBackSpace);
ShiftBtn.onClick.AddListener(ClickShift);
SpaceBtn.onClick.AddListener(ClickSpace);
CancelBtn.onClick.AddListener(ClickCancel);
EnterBtn.onClick.AddListener(ClickEnter);
LangugeBtn.onClick.AddListener(ClickLanguage);
ClearBtn.onClick.AddListener(ClickClear);
LastBtn.onClick.AddListener(ClickLast);
NextBtn.onClick.AddListener(ClickNext);
LastBtn.gameObject.SetActive(false);
NextBtn.gameObject.SetActive(false);
PinYinText.text = "";
instance = this;
}
//初始化按钮
private void InitComBtn()
{
InstantLineComBtns(Line0, Line0_KeyValue);
InstantLineComBtns(Line1, Line1_KeyValue);
InstantLineComBtns(Line2, Line2_KeyValue);
InstantLineComBtns(Line3, Line3_KeyValue);
}
//按行实例化按钮
private void InstantLineComBtns(Transform LineTran, string[][] KeyValues)
{
for (int i = 0; i < KeyValues[0].Length; i++)
{
GameObject TempObj = GameObject.Instantiate(ComBtnPref);
TempObj.transform.SetParent(LineTran);
TempObj.transform.localScale = Vector3.one;
//自添加
TempObj.transform.localEulerAngles = Vector3.zero;
//\\
ComBtn comBtnCtrl = TempObj.GetComponent();
if (comBtnCtrl != null)
{
comBtnCtrl.SetKeyValue(KeyValues[0][i], KeyValues[1][i]);
OnShiftOn += comBtnCtrl.OnShiftOn;
OnShiftOff += comBtnCtrl.OnShiftOff;
}
}
}
//输入内容追加
public void AddComBtnString(string str)
{
if (!isCn)
{
NewEditeString += str;
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
call?.Invoke(KeyboardPara);
if (isShift && !isShiftLock)
{
isShift = false;
ShiftBG.color = new Color(128, 128, 128, 255);
OnShiftOff();
}
}
else {
Regex reg = new Regex(@"[a-zA-Z]+");
if (reg.IsMatch(str))
{ //纯字母
PinYinStr += str;
PinYinText.text = PinYinStr;
HanZiArr = Pinyin4Net.GetHanzi(PinYinStr, false);
UpdateHanZi();
}
else {
NewEditeString += (HanZiArr.Length > 0 && HanZiArr[0] != null) ? (HanZiArr[0] + str) : str;
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
call?.Invoke(KeyboardPara);
}
}
}
//点击汉字
public void ClickHanZi(Text hz) {
NewEditeString += hz.text;
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
call?.Invoke(KeyboardPara);
ClearCnPinYin();
}
//清除中文输入残留
void ClearCnPinYin() {
PinYinStr = "";
PinYinText.text = PinYinStr;
HanZiArr = new string[] { };
UpdateHanZi();
LastBtn.gameObject.SetActive(false);
NextBtn.gameObject.SetActive(false);
}
//点击上一页
public void ClickLast()
{
if (NowPage > 0)
UpdateHanZi(--NowPage);
}
//点击下一页
public void ClickNext() {
if (NowPage < TotalPage)
UpdateHanZi(++NowPage);
}
//按页更新汉子选项
void UpdateHanZi(int page = 0) {
for (int i = 0; i < HanZiTextList.Count; i++) {
if (HanZiArr != null && HanZiArr.Length > page * PageSize + i) {
HanZiTextList[i].text = HanZiArr[page * PageSize + i];
HanZiTextList[i].gameObject.SetActive(true);
}
else
HanZiTextList[i].gameObject.SetActive(false);
}
NowPage = page;
TotalPage = HanZiArr.Length / PageSize + (HanZiArr.Length % PageSize > 0 ? 1 : 0) - 1;
if (NowPage == 0)
LastBtn.gameObject.SetActive(false);
else
LastBtn.gameObject.SetActive(true);
if (NowPage < TotalPage)
NextBtn.gameObject.SetActive(true);
else
NextBtn.gameObject.SetActive(false);
}
// 唤起键盘,默认为中文
public void ShowKeyboard(KeyboardParam para, EventCommon.CallBack call)
{
KeyboardPara = para;
NewEditeString = KeyboardPara.InputStr;
KeyboardWindow.localScale = Vector3.one;
if (call != null)
this.call = call;
//中文初始化
OnShiftOff();
//isCn = true;
LanText.text = isCn?"中/En " :"中 /En" ;
CnObj.SetActive(true);
ClearCnPinYin();
}
public void HideKeyboard()
{
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
KeyboardWindow.localScale = Vector3.zero;
call?.Invoke(KeyboardPara);
KeyboardPara = null;
}
//语言点击事件
private void ClickLanguage()
{
isCn = !isCn;
if (isCn)
{
LanText.text = "中/En ";
CnObj.SetActive(true);
ClearCnPinYin();
}
else
{
LanText.text = "En/中 ";
CnObj.SetActive(false);
}
}
//取消点击事件
private void ClickCancel()
{
NewEditeString = "";
if (KeyboardPara != null)
KeyboardPara.OutputStr = KeyboardPara.InputStr;
call?.Invoke(KeyboardPara);
KeyboardPara = null;
KeyboardWindow.localScale = Vector3.zero;
}
//确认点击事件
private void ClickEnter()
{
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
KeyboardWindow.localScale = Vector3.zero;
call?.Invoke(KeyboardPara);
KeyboardPara = null;
}
//shift点击事件
private void ClickShift()
{
if (!isCn)
{
if (Time.time - ShiftTime <= 0.5f)
{
ShiftTime = Time.time;
isShift = true;
isShiftLock = true;
ShiftBG.color = LockColor;
OnShiftOn();
}
else
{
if (isShift)
{
ShiftTime = Time.time;
isShift = false;
isShiftLock = false;
ShiftBG.color = new Color(128, 128, 128, 255);
OnShiftOff();
}
else
{
ShiftTime = Time.time;
isShift = true;
isShiftLock = false;
OnShiftOn();
}
}
}
else
{
ShiftTime = Time.time;
isShift = false;
isShiftLock = false;
ShiftBG.color = new Color(128, 128, 128, 255);
OnShiftOff();
isCn = false;
LanText.text = "En/中 ";
}
}
//空格点击事件
private void ClickSpace()
{
if (isCn)
NewEditeString += (HanZiArr.Length > 0 && HanZiArr[0] != null) ? (HanZiArr[0] + " ") : " ";
else
NewEditeString += " ";
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
call?.Invoke(KeyboardPara);
ClearCnPinYin();
}
//清除点击事件
private void ClickClear()
{
NewEditeString = "";
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
call?.Invoke(KeyboardPara);
}
//回退点击事件
private void ClickBackSpace()
{
if (isCn)
{
if (string.IsNullOrEmpty(PinYinStr))
{
if (!string.IsNullOrEmpty(NewEditeString))
{
NewEditeString = NewEditeString.Substring(0, NewEditeString.Length - 1);
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
call?.Invoke(KeyboardPara);
}
ClearCnPinYin();
}
else
{
PinYinStr = PinYinStr.Substring(0, PinYinStr.Length - 1);
PinYinText.text = PinYinStr;
HanZiArr = Pinyin4Net.GetHanzi(PinYinStr, false);
UpdateHanZi();
}
}
else {
if (!string.IsNullOrEmpty(NewEditeString))
{
NewEditeString = NewEditeString.Substring(0, NewEditeString.Length - 1);
if (KeyboardPara != null)
KeyboardPara.OutputStr = NewEditeString;
call?.Invoke(KeyboardPara);
}
}
}
}
}
源码:后续资源上传后评论区添加