UI 的 Drag&Drop

发布于 2017-12-01  896 次阅读


UI的拖拽事件

为了实现下图的效果,我们需要拿到3个信息。

  1. 开始拖拽的位置
  2. 持续拖拽的位置
  3. 结束拖拽的位置

为了拿到这三个信息,Unity为我们提供了 IBeginDragHandlerIDragHandlerIEndDragHandler这三个接口。所以我们的制作思路也是围绕这三个接口的实现来进行展开。

IBeginDragHandler

继承此接口时,Unity需要我们实现OnBeginDrag()方法:

public void OnBeginDrag(PointerEventData eventData){}

在这里我们需要做3件事:

  1. 创建一个新的icon物体,并将自己的Image赋给它
  2. 找到Canvas,将icon设为其子物体(这样可以保证icon在最前面)
  3. 将eventData中的位置信息赋给icon

IDragHandler

继承此接口时,Unity需要我们实现OnDrag()方法

 public void OnDrag(PointerEventData eventData){}

在这里我们只需要做一件事就好了:持续将eventData中的位置信息赋给icon

IEndDragHandler

继承此接口时,Unity需要我们实现OnEndDrag()方法

 public void OnEndDrag(PointerEventData eventData){}

在这里我们也只需要做一件事:销毁icon

代码实现

 using UnityEngine;
 using UnityEngine.EventSystems;
 using UnityEngine.UI;

 [RequireComponent(typeof(Image))]
 public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
 {
     public bool dragOnSurfaces = true;
     
     private GameObject m_DraggingIcon;
     private RectTransform m_DraggingPlane;

     public void OnBeginDrag(PointerEventData eventData)
     {
         var canvas = FindInParents<Canvas>(gameObject);
         if (canvas == null)
             return;

         // We have clicked something that can be dragged.
         // What we want to do is create an icon for this.
         m_DraggingIcon = new GameObject("icon");

         m_DraggingIcon.transform.SetParent (canvas.transform, false);
         m_DraggingIcon.transform.SetAsLastSibling();
         
         var image = m_DraggingIcon.AddComponent<Image>();
         // The icon will be under the cursor.
         // We want it to be ignored by the event system.
         CanvasGroup group = m_DraggingIcon.AddComponent<CanvasGroup>();
         group.blocksRaycasts = false;

         image.sprite = GetComponent<Image>().sprite;
         image.SetNativeSize();
         
         if (dragOnSurfaces)
             m_DraggingPlane = transform as RectTransform;
         else
             m_DraggingPlane = canvas.transform as RectTransform;
         
         SetDraggedPosition(eventData);
     }

     public void OnDrag(PointerEventData data)
     {
         if (m_DraggingIcon != null)
             SetDraggedPosition(data);
     }

     private void SetDraggedPosition(PointerEventData data)
     {
         if (dragOnSurfaces && data.pointerEnter != null && data.pointerEnter.transform as RectTransform != null)
             m_DraggingPlane = data.pointerEnter.transform as RectTransform;
         
         var rt = m_DraggingIcon.GetComponent<RectTransform>();
         Vector3 globalMousePos;
         if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_DraggingPlane, data.position, data.pressEventCamera, out globalMousePos))
         {
             rt.position = globalMousePos;
             rt.rotation = m_DraggingPlane.rotation;
         }
     }

     public void OnEndDrag(PointerEventData eventData)
     {
         if (m_DraggingIcon != null)
             Destroy(m_DraggingIcon);
     }

     static public T FindInParents<T>(GameObject go) where T : Component
     {
         if (go == null) return null;
         var comp = go.GetComponent<T>();

         if (comp != null)
             return comp;
         
         Transform t = go.transform.parent;
         while (t != null && comp == null)
         {
             comp = t.gameObject.GetComponent<T>();
             t = t.parent;
         }
         return comp;
     }
 }

可直接下载项目:https://pan.baidu.com/s/1dE9nVHn

 

 

 

 

 

 


What doesn’t kill you makes you stronger.