【UGUI扩展】扩展UGUI Button

来源:互联网 发布:临沂百度关键词优化 编辑:程序博客网 时间:2024/05/01 07:08


源:https://github.com/yangyxd/YxdGameFrame/tree/master/YxdGameFrame/Assets/GameFrame/Frame/UGUI

http://www.cnblogs.com/yangyxd/articles/5308274.html


这个UGUI button 扩展是基于这个项目整理的,斗胆以原创发布。

扩展后的效果:



可以通过这样的形式创建:



详细的完整代码如下:

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;using UnityEngine.Events;using UnityEngine.EventSystems;#if UNITY_EDITORusing UnityEditor;using UnityEngine.Serialization;#endifpublic class UIButtonExtension : UnityEngine.UI.Selectable,    IPointerClickHandler,    ISubmitHandler,    IPointerDownHandler,    IPointerUpHandler,    IPointerEnterHandler,    IPointerExitHandler{      /// <summary>        /// 长按等待时间        /// </summary>        public float onLongWaitTime = 1.5f;        /// <summary>        /// 不断的产生长按事件        /// </summary>        public bool onLongContinue = false;        [System.Serializable]        public class ButtonClickedEvent : UnityEvent { }        [FormerlySerializedAs("onClick")]        [SerializeField]        private ButtonClickedEvent m_OnClick = new ButtonClickedEvent();        [FormerlySerializedAs("onLongClick")]        [SerializeField]        private ButtonClickedEvent m_OnLongClick = new ButtonClickedEvent();        [FormerlySerializedAs("onDown")]        [SerializeField]        private ButtonClickedEvent m_OnDown = new ButtonClickedEvent();        [FormerlySerializedAs("onUp")]        [SerializeField]        private ButtonClickedEvent m_OnUp = new ButtonClickedEvent();        [FormerlySerializedAs("onEnter")]        [SerializeField]        private ButtonClickedEvent m_OnEnter = new ButtonClickedEvent();        [FormerlySerializedAs("onExit")]        [SerializeField]        private ButtonClickedEvent m_OnExit = new ButtonClickedEvent();        //private System.Reflection.PropertyInfo pro_isDown;        //private System.Reflection.PropertyInfo pro_isEnter;        protected UIButtonExtension() : base() { }        /// <summary>        /// 文本值        /// </summary>        public string text        {            get            {                Text v = getText();                if (v != null)                    return v.text;                return null;            }            set            {                Text v = getText();                if (v != null)                    v.text = value;            }        }        private bool isPointerDown = false;        private bool isPointerInside = false;        /// <summary>        /// 是否被按下        /// </summary>        public bool isDown        {            get            {                return isPointerDown;                /**                if (pro_isDown == null) {                    pro_isDown = typeof(Selectable).GetProperty ("isPointerDown", getRBFlag());                }                if (pro_isDown == null)                    return false;                bool b = (bool) pro_isDown.GetValue (this, null);                return b;                */            }        }        /// <summary>        /// 是否进入        /// </summary>        public bool isEnter        {            get            {                return isPointerInside;                /**                if (pro_isEnter == null) {                    pro_isEnter = typeof(Selectable).GetProperty ("isPointerInside", getRBFlag());                }                if (pro_isEnter == null)                    return false;                bool b = (bool) pro_isEnter.GetValue (this, null);                return b;                */            }        }        /// <summary>        /// 点击事件        /// </summary>        public ButtonClickedEvent onClick        {            get { return m_OnClick; }            set { m_OnClick = value; }        }        /// <summary>        /// 长按事件        /// </summary>        public ButtonClickedEvent onLongClick        {            get { return m_OnLongClick; }            set { m_OnLongClick = value; }        }        /// <summary>        /// 按下事件        /// </summary>        public ButtonClickedEvent onDown        {            get { return m_OnDown; }            set { m_OnDown = value; }        }        /// <summary>        /// 松开事件        /// </summary>        public ButtonClickedEvent onUp        {            get { return m_OnUp; }            set { m_OnUp = value; }        }        /// <summary>        /// 进入事件        /// </summary>        public ButtonClickedEvent onEnter        {            get { return m_OnEnter; }            set { m_OnEnter = value; }        }        /// <summary>        /// 离开事件        /// </summary>        public ButtonClickedEvent onExit        {            get { return m_OnExit; }            set { m_OnExit = value; }        }        private System.Reflection.BindingFlags getRBFlag()        {            return System.Reflection.BindingFlags.Static |                System.Reflection.BindingFlags.NonPublic |                System.Reflection.BindingFlags.GetProperty |                System.Reflection.BindingFlags.Instance |                System.Reflection.BindingFlags.GetField |                System.Reflection.BindingFlags.ExactBinding;        }        private UnityEngine.UI.Text getText()        {            Transform f = transform.FindChild("Text");            Text v = null;            if (f != null)            {                v = f.gameObject.GetComponent<Text>();            }            if (v == null && transform.childCount > 0)            {                GameObject obj = transform.GetChild(0).gameObject;                v = obj.GetComponent<Text>();            }            return v;        }        private void Press()        {            if (!IsActive() || !IsInteractable())                return;            m_OnClick.Invoke();        }        private void Down()        {            if (!IsActive() || !IsInteractable())                return;            m_OnDown.Invoke();            StartCoroutine(grow());        }        private void Up()        {            if (!IsActive() || !IsInteractable() || !isDown)                return;            m_OnUp.Invoke();        }        private void Enter()        {            if (!IsActive())                return;            m_OnEnter.Invoke();        }        private void Exit()        {            if (!IsActive() || !isEnter)                return;            m_OnExit.Invoke();        }        private void LongClick()        {            if (!IsActive() || !isDown)                return;            m_OnLongClick.Invoke();        }        private float downTime = 0f;        private IEnumerator grow()        {            downTime = Time.time;            while (isDown)            {                if (Time.time - downTime > onLongWaitTime)                {                    LongClick();                    if (onLongContinue)                        downTime = Time.time;                    else                        break;                }                else                    yield return null;            }        }        protected override void OnDisable()        {            isPointerDown = false;            isPointerInside = false;        }        public virtual void OnPointerClick(PointerEventData eventData)        {            if (eventData.button != PointerEventData.InputButton.Left)                return;            Press();        }        public override void OnPointerDown(PointerEventData eventData)        {            if (eventData.button != PointerEventData.InputButton.Left)                return;            isPointerDown = true;            Down();            base.OnPointerDown(eventData);        }        public override void OnPointerUp(PointerEventData eventData)        {            if (eventData.button != PointerEventData.InputButton.Left)                return;            Up();            isPointerDown = false;            base.OnPointerUp(eventData);        }        public override void OnPointerEnter(PointerEventData eventData)        {            base.OnPointerEnter(eventData);            isPointerInside = true;            Enter();        }        public override void OnPointerExit(PointerEventData eventData)        {            Exit();            isPointerInside = false;            base.OnPointerExit(eventData);        }        public virtual void OnSubmit(BaseEventData eventData)        {            Press();            // if we get set disabled during the press            // don't run the coroutine.            if (!IsActive() || !IsInteractable())                return;            DoStateTransition(SelectionState.Pressed, false);            StartCoroutine(OnFinishSubmit());        }        private IEnumerator OnFinishSubmit()        {            var fadeTime = colors.fadeDuration;            var elapsedTime = 0f;            while (elapsedTime < fadeTime)            {                elapsedTime += Time.unscaledDeltaTime;                yield return null;            }            DoStateTransition(currentSelectionState, false);        }     public static GameObject CreateUIElementRoot(string name, Vector2 size)    {        GameObject go = new GameObject(name);        RectTransform rect = go.AddComponent<RectTransform>();        rect.sizeDelta = size;        return go;    }    public static GameObject CreateUIElementRoot(string name, float w, float h)    {        return CreateUIElementRoot(name, new Vector2(w, h));    }    public static GameObject CreateUIText(string name, string text, GameObject parent)    {        GameObject childText = CreateUIObject(name, parent);        Text v = childText.AddComponent<Text>();        v.text = text;        v.alignment = TextAnchor.MiddleCenter;        SetDefaultTextValues(v);        RectTransform r = childText.GetComponent<RectTransform>();        r.anchorMin = Vector2.zero;        r.anchorMax = Vector2.one;        r.sizeDelta = Vector2.zero;        return childText;    }    public static GameObject CreateUIObject(string name, GameObject parent)    {        GameObject go = new GameObject(name);        go.AddComponent<RectTransform>();        SetParentAndAlign(go, parent);        return go;    }    public static void SetDefaultTextValues(Text lbl)    {        lbl.color = new Color(50f / 255f, 50f / 255f, 50f / 255f, 1f);    }    public static void SetParentAndAlign(GameObject child, GameObject parent)    {        if (parent == null)            return;        child.transform.SetParent(parent.transform, false);        SetLayerRecursively(child, parent.layer);    }    public static void SetLayerRecursively(GameObject go, int layer)    {        go.layer = layer;        Transform t = go.transform;        for (int i = 0; i < t.childCount; i++)            SetLayerRecursively(t.GetChild(i).gameObject, layer);    }    public static T findRes<T>(string name) where T : Object    {        T[] objs = Resources.FindObjectsOfTypeAll<T>();        if (objs != null && objs.Length > 0)        {            foreach (Object obj in objs)            {                if (obj.name == name)                    return obj as T;            }        }        objs = AssetBundle.FindObjectsOfType<T>();        if (objs != null && objs.Length > 0)        {            foreach (Object obj in objs)            {                if (obj.name == name)                    return obj as T;            }        }        return default(T);    }    public static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand)    {#if UNITY_EDITOR        GameObject parent = menuCommand.context as GameObject;        if (parent == null || parent.GetComponentInParent<Canvas>() == null)        {            parent = GetOrCreateCanvasGameObject();        }        string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent.transform, element.name);        element.name = uniqueName;        Undo.RegisterCreatedObjectUndo(element, "Create " + element.name);        Undo.SetTransformParent(element.transform, parent.transform, "Parent " + element.name);        GameObjectUtility.SetParentAndAlign(element, parent);        if (parent != menuCommand.context) // not a context click, so center in sceneview            SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(), element.GetComponent<RectTransform>());        Selection.activeGameObject = element;#endif    }    public static GameObject GetOrCreateCanvasGameObject()    {#if UNITY_EDITOR        GameObject selectedGo = Selection.activeGameObject;        // Try to find a gameobject that is the selected GO or one if its parents.        Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null;        if (canvas != null && canvas.gameObject.activeInHierarchy)            return canvas.gameObject;        // No canvas in selection or its parents? Then use just any canvas..        canvas = Object.FindObjectOfType(typeof(Canvas)) as Canvas;        if (canvas != null && canvas.gameObject.activeInHierarchy)            return canvas.gameObject;        // No canvas in the scene at all? Then create a new one.        return CreateNewUI();#elsereturn null;#endif    }#if UNITY_EDITOR    private static void SetPositionVisibleinSceneView(RectTransform canvasRTransform, RectTransform itemTransform)    {        // Find the best scene view        SceneView sceneView = SceneView.lastActiveSceneView;        if (sceneView == null && SceneView.sceneViews.Count > 0)            sceneView = SceneView.sceneViews[0] as SceneView;        // Couldn't find a SceneView. Don't set position.        if (sceneView == null || sceneView.camera == null)            return;        // Create world space Plane from canvas position.        Vector2 localPlanePosition;        Camera camera = sceneView.camera;        Vector3 position = Vector3.zero;        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform, new Vector2(camera.pixelWidth / 2, camera.pixelHeight / 2), camera, out localPlanePosition))        {            // Adjust for canvas pivot            localPlanePosition.x = localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x;            localPlanePosition.y = localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y;            localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x);            localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y);            // Adjust for anchoring            position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x;            position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y;            Vector3 minLocalPosition;            minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) + itemTransform.sizeDelta.x * itemTransform.pivot.x;            minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) + itemTransform.sizeDelta.y * itemTransform.pivot.y;            Vector3 maxLocalPosition;            maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) - itemTransform.sizeDelta.x * itemTransform.pivot.x;            maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) - itemTransform.sizeDelta.y * itemTransform.pivot.y;            position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x);            position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y);        }        itemTransform.anchoredPosition = position;        itemTransform.localRotation = Quaternion.identity;        itemTransform.localScale = Vector3.one;    }#endif    public static GameObject CreateNewUI()    {        // Root for the UI        var root = new GameObject("Canvas");        root.layer = LayerMask.NameToLayer("UI");        Canvas canvas = root.AddComponent<Canvas>();        canvas.renderMode = RenderMode.ScreenSpaceOverlay;        root.AddComponent<CanvasScaler>();        root.AddComponent<GraphicRaycaster>();#if UNITY_EDITOR        Undo.RegisterCreatedObjectUndo(root, "Create " + root.name);#endif        // if there is no event system add one...        CreateEventSystem(false, null);        return root;    }    public static void CreateEventSystem(bool select, GameObject parent)    {#if UNITY_EDITOR        var esys = Object.FindObjectOfType<EventSystem>();        if (esys == null)        {            var eventSystem = new GameObject("EventSystem");            GameObjectUtility.SetParentAndAlign(eventSystem, parent);            esys = eventSystem.AddComponent<EventSystem>();            eventSystem.AddComponent<StandaloneInputModule>();            Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name);        }        if (select && esys != null)        {            Selection.activeGameObject = esys.gameObject;        }#endif    }#if UNITY_EDITOR        [MenuItem("GameObject/UI/ButtonEx")]        static void CreateButtonEx(MenuCommand menuCmd)        {            // 创建游戏对象            float w = 160f;            float h = 30f;            GameObject btnRoot = CreateUIElementRoot("ButtonEx", w, h);            // 创建Text对象            CreateUIText("Text", "Button", btnRoot);            // 添加脚本            btnRoot.AddComponent<CanvasRenderer>();            Image img = btnRoot.AddComponent<Image>();            img.color = Color.white;            img.fillCenter = true;            img.raycastTarget = true;            img.sprite = findRes<Sprite>("UISprite");            if (img.sprite != null)                img.type = Image.Type.Sliced;            btnRoot.AddComponent<UIButtonExtension>();            btnRoot.GetComponent<Selectable>().image = img;            // 放入到UI Canvas中            PlaceUIElementRoot(btnRoot, menuCmd);        }#endif    }   


测试代码:

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.EventSystems;public class ButtonTest : UIButtonExtension{        public override void OnPointerClick(PointerEventData eventData)    {        //base.OnPointerClick(eventData);        Debug.Log("OnClick");    }    public override void OnPointerDown(PointerEventData eventData)    {        //base.OnPointerDown(eventData);        Debug.Log("OnDown");    }    public override void OnPointerEnter(PointerEventData eventData)    {        //base.OnPointerEnter(eventData);        Debug.Log("OnEnter");    }    public override void OnPointerExit(PointerEventData eventData)    {        //base.OnPointerExit(eventData);        Debug.Log("OnEixt");    }    public override void OnPointerUp(PointerEventData eventData)    {        //base.OnPointerUp(eventData);        Debug.Log("OnUp");    }}


效果图:


完!