【unity】自定义键盘插件

首先需要实现一个自定义的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<MyInputField >();
}

void inputAction()
{
        myinput.text = "";
        myinput.placeholder.GetComponent<Text>().text = Placeholder;
        myinput.OnFocused.RemoveAllListeners();
        myinput.OnFocused.AddListener(() =>
        {
            ClickText();
        });
        void ClickText()
        {
            KeyboardPara.InputStr = input.text;
            CnKeyboard cnKeyboard = keyboardObj.GetComponentInChildren<CnKeyboard>();

            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>(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<KeyboardParam> call = null; //回调函数

        private static CnKeyboard instance = null;

        bool isCn = false;
        Text LanText, PinYinText;
        string PinYinStr;   //拼音串
        string[] HanZiArr = new string[] { };  //汉子的结果值;
        List<Text> HanZiTextList = new List<Text>();

        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<RectTransform>();
            ComBtnPref = Resources.Load<GameObject>("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<Button>();
            ShiftBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine3/ShiftBtn").GetComponent<Button>();
            SpaceBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/SpaceBtn").GetComponent<Button>();
            CancelBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/right/CancelBtn").GetComponent<Button>();
            EnterBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/right/EnterBtn").GetComponent<Button>();
            LangugeBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/left/LangugeBtn").GetComponent<Button>();
            ClearBtn = KeyboardWindow.Find("KB_BG/KeyBtns/BtnLine4/left/ClearBtn").GetComponent<Button>();
            LanText = LangugeBtn.transform.Find("Text").GetComponent<Text>();
            ShiftBG = ShiftBtn.GetComponent<Image>();

            LastBtn = KeyboardWindow.Find("KB_BG/CnBG/Last").GetComponent<Button>();
            NextBtn = KeyboardWindow.Find("KB_BG/CnBG/Next").GetComponent<Button>();
            PinYinText = KeyboardWindow.Find("KB_BG/CnBG/Pinyin").GetComponent<Text>();
            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<Text>();
                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<GameObject>(ComBtnPref);
                TempObj.transform.SetParent(LineTran);
                TempObj.transform.localScale = Vector3.one;
                //自添加
                TempObj.transform.localEulerAngles = Vector3.zero;
                //\\
                ComBtn comBtnCtrl = TempObj.GetComponent<ComBtn>();
                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<KeyboardParam> call)
        {
            KeyboardPara = para;
            NewEditeString = KeyboardPara.InputStr;

            KeyboardWindow.localScale = Vector3.one;
            if (call != null)
                this.call = call;

            //中文初始化
            OnShiftOff();
            //isCn = true;
            LanText.text = isCn?"中/<color=#9A9A9A>En</color>" :"<color=#9A9A9A>中</color>/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 = "中/<color=#9A9A9A>En</color>";
                CnObj.SetActive(true);
                ClearCnPinYin();
            }
            else
            {
                LanText.text = "En/<color=#9A9A9A>中</color>";
                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/<color=#9A9A9A>中</color>";
            }
        }

        //空格点击事件
        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);
                }
            }
        }
    }
}

源码:后续资源上传后评论区添加

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值