1.在每个content的子物体上挂载DragHandler脚本,并且添加Canvs Group组件,设置见图
2.DragHandler脚本内容:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using System.Collections;
public class DragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
private RectTransform rectTransform;
private Canvas canvas;
private Transform parentTransform;
private Vector2 startPosition;
private int startSiblingIndex;
private bool isDragging = false;
private CanvasGroup canvasGroup;
private int newIndex;
private int top;//content的顶端间距
private float spacing;//content的子物体的spacing
private float height;//子物体的高度
void Awake()
{
rectTransform = GetComponent<RectTransform>();
height = rectTransform.sizeDelta.y;
canvas = GetComponentInParent<Canvas>();
parentTransform = transform.parent;
VerticalLayoutGroup layout = parentTransform.GetComponent<VerticalLayoutGroup>();
top = layout.padding.top;
spacing = layout.spacing;
// 获取或添加 CanvasGroup 组件
canvasGroup = GetComponent<CanvasGroup>();
if (canvasGroup == null)
{
canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
}
public void OnBeginDrag(PointerEventData eventData)
{
if (eventData.button != PointerEventData.InputButton.Left) return;
// 记录初始位置和索引
startPosition = rectTransform.anchoredPosition;
startSiblingIndex = transform.GetSiblingIndex();
Debug.Log($"开始拖拽时:startSiblingIndex={startSiblingIndex}");
// 禁用射线阻挡
canvasGroup.blocksRaycasts = false;
isDragging = true;
}
public void OnDrag(PointerEventData eventData)
{
if (!isDragging) return;
// 更新位置(跟随鼠标)
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
parentTransform as RectTransform,
eventData.position,
canvas.worldCamera,
out localPoint);
rectTransform.anchoredPosition = new Vector2(startPosition.x, localPoint.y);
// 直接更新顺序(不使用占位符)
UpdateSortOrder();
}
public void OnEndDrag(PointerEventData eventData)
{
if (!isDragging) return;
isDragging = false;
// 恢复射线阻挡
canvasGroup.blocksRaycasts = true;
//标准化最终位置
if(newIndex == 0)
{
rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, -(top+ height/2));
}
else
{
RectTransform preChildTrec = parentTransform.GetChild(newIndex - 1)?.GetComponent<RectTransform>();
rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, preChildTrec.anchoredPosition.y - (spacing+height));
}
}
// 直接更新排序顺序
private void UpdateSortOrder()
{
newIndex = startSiblingIndex;
// 计算当前拖拽物体在父物体局部空间中的位置
Vector2 currentPos = rectTransform.anchoredPosition;
Debug.Log($"自己的y:{currentPos.y}");
// 遍历所有兄弟物体,找到合适的位置
for (int i = 0; i < parentTransform.childCount; i++)
{
// 跳过自己
if (parentTransform.GetChild(i) == transform) continue;
RectTransform sibling = parentTransform.GetChild(i)?.GetComponent<RectTransform>();
if (sibling != null)
{
Debug.Log($"子物体的名字:{sibling.name},y:{sibling.anchoredPosition.y}");
// 简单的基于Y坐标的位置判断
if (currentPos.y > sibling.anchoredPosition.y)
{
newIndex = i;
// 如果新索引大于当前索引,需要减1,因为自己不在列表中
if (newIndex > transform.GetSiblingIndex())
{
newIndex--;
}
Debug.Log($"newIndex = {newIndex}");
break;
}
}
}
// 确保索引在有效范围内
newIndex = Mathf.Clamp(newIndex, 0, parentTransform.childCount - 1);
// 更新自己的位置
if (newIndex != transform.GetSiblingIndex())
{
transform.SetSiblingIndex(newIndex);
}
}
}