当前位置: 首页 > news >正文

unity 输入框 自己定义光标显示逻辑

       实现一个输入框 光标一直闪烁的功能,

        public GameObject Cursor; //模拟光标
        private RectTransform cursorRectTrans;

        private float m_CaretBlinkRate = 0.85f;
        protected bool m_CaretVisible;
        private Coroutine m_BlinkCoroutine = null;
        private float m_BlinkStartTime = 0.0f;

       public void Awake()
       {

                  inputField = GetComponent<InputField>();

                 m_CaretBlinkRate = inputField.caretBlinkRate;

       }

        void OnEnable()
        {
            bool currentVisibility = inputField.isFocused && inputField.isActiveAndEnabled;
            if (!currentVisibility)
            {
                isRealCursorVisible = currentVisibility;
                SetCaretVisible();
            }
        }


        void SetCaretVisible()
        {
            m_CaretVisible = true;
            m_BlinkStartTime = Time.unscaledTime;
            SetCaretActive();
        }

        /// <summary>
        /// 自定义光标
        /// </summary>
        void SetCaretActive()
        {
            if (m_CaretBlinkRate > 0.0f)
            {
                if(m_BlinkCoroutine != null)
                {
                    StopCoroutine(m_BlinkCoroutine);
                }

                m_BlinkCoroutine = StartCoroutine(CaretBlink());
            }
            else
            {
                m_CaretVisible = true;
            }
        }

        void StopBlinkCoroutine()
        {
            if (m_BlinkCoroutine != null)
            {
                m_CaretVisible = false;
                Cursor.gameObject.SetActive(false);
                StopCoroutine(m_BlinkCoroutine);
                m_BlinkCoroutine = null;
            }
        }
        IEnumerator CaretBlink()
        {
            // Always ensure caret is initially visible since it can otherwise be confusing for a moment.
            m_CaretVisible = true;
            yield return null;

            while (!inputField.isFocused && m_CaretBlinkRate > 0)
            {
                // the blink rate is expressed as a frequency
                float blinkPeriod = 1f / m_CaretBlinkRate;

                // the caret should be ON if we are in the first half of the blink period
                bool blinkState = (Time.unscaledTime - m_BlinkStartTime) % blinkPeriod < blinkPeriod / 2;
                if (m_CaretVisible != blinkState)
                {
                    m_CaretVisible = blinkState;
                }

                // Then wait again.
                yield return null;
            }
            m_BlinkCoroutine = null;
        }
        void Update()
        {
            //Debug.Log("当前光标位置:" + inputField.caretPosition);

            // 检测系统光标显隐变化 [1,5](@ref)
            bool currentVisibility = inputField.isFocused && inputField.isActiveAndEnabled;
            if (currentVisibility != isRealCursorVisible)
            {
                isRealCursorVisible = currentVisibility;
                if (!isRealCursorVisible)
                    SetCaretVisible();
                else
                    StopBlinkCoroutine();
            }

            if (!isRealCursorVisible && !inputField.isFocused)
            {
                Cursor.gameObject.SetActive(m_CaretVisible);
                UpdateCustomCursorPosition();
            }
            else
            {
                Cursor.gameObject.SetActive(false);
            }
        }

        void UpdateCustomCursorPosition()
        {
            // 获取文本组件及光标索引 [6,7](@ref)
            TextGenerator gen = inputField.textComponent.cachedTextGenerator;
            int caretPos = inputField.caretPosition;

            // 计算光标在文本中的局部坐标
            Vector2 cursorLocalPos;
            if (caretPos > 0 && caretPos <= gen.characterCountVisible)
            {
                UICharInfo charInfo = gen.characters[caretPos - 1];
                cursorLocalPos = new Vector2(charInfo.cursorPos.x, 0);
            }
            else
            {
                if(gen.characterCountVisible > 0)
                {
                    UICharInfo charInfo = gen.characters[gen.characterCountVisible - 1];
                    cursorLocalPos = new Vector2(charInfo.cursorPos.x + charInfo.charWidth,charInfo.cursorPos.y - (inputField.textComponent.fontSize * 0.5f + 5));
                    // 转换为屏幕坐标 [4](@ref)
                    Vector2 screenPos = inputField.textComponent.transform.TransformPoint(cursorLocalPos);
                    cursorRectTrans.transform.position = screenPos;
                }
                else
                {
                    cursorLocalPos = Vector2.zero; // 处理边界情况
                    cursorRectTrans.anchoredPosition = cursorLocalPos;
                }
            }


        }

http://www.xdnf.cn/news/959599.html

相关文章:

  • 结构化文件管理实战:实现目录自动创建与归类
  • 【性能篇I】为应用加速:整合 Redis 实现高速缓存
  • RAID存储技术概述
  • 湖北理元理律师事务所:债务清偿方案中的法律技术革新
  • FreeRtos下创建任务失败原因记录
  • 动态元素绑定事件总失效?通过AI 对话框的开发,详解绑定逻辑!
  • @Transactional 什么情况下会失效
  • Linux应用开发之网络套接字编程(实例篇)
  • VMware Workstation踩坑指南
  • Ubuntu 可执行程序自启动方法
  • apt命令介绍
  • 【音乐分析】根据拍号结合bpm计算bar_duration
  • 每日算法题(12-1)ACM输出九九乘法表-20250609
  • DeviceNet转Modbus-RTU协议网关详细解读
  • 医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
  • CCleaner Professional 下载安装教程 - 电脑清理优化工具详细使用指南
  • Kafka入门-监控与可视化
  • 今天做的力扣SQL
  • 二维FDTD算法仿真
  • C++ 类的定义与构造 / 析构函数解析
  • python3基础语法梳理(一)
  • 验证回文串
  • 【学习分享】shell脚本基础(全)
  • 深度解析云存储:概念、架构与应用实践
  • 外链域名年龄 vs 数量老域名的1个链接抵新域名的100个吗?
  • 【配置篇】告别硬编码:多环境配置、@ConfigurationProperties与配置中心初探
  • FDD损失函数 损失函数和梯度的关系
  • Day49 Python打卡训练营
  • 【前端】js Map集合的使用方法
  • C++11委托构造函数和继承构造函数:从入门到精通