unity中通过拖拽,自定义scroll view中子物体顺序
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的子物体的spacingprivate 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);}}
}