*Unity ScrollRect中,拖拽移动Item的顺序*
目标需求
Unity在制作下拉菜单时,用户可通过拖拽Item,替换当前Item的位置。本教程使用UGUI
制作方法
创建脚本 ScrollRectManager,用于管理整个ScrollRect,我是将脚本 ScrollRectManager挂载到了 Canvas
完整代码
创建脚本 ScrollRectItem,作为Item,通过程序生成Item,动态添加脚本控制器
public class ScrollRectManager : MonoBehaviour
{
[SerializeField] Color[] m_Color = new Color[0];
public ScrollRect m_ScorllRect;
internal GridLayoutGroup m_GridLayoutGroup;
internal RectTransform m_RectTransformGrid;
Queue m_Item = new Queue();
internal float minY = 0;
internal float maxY = 0;
async void Start()
{
this.m_GridLayoutGroup = this.m_ScorllRect.content.GetComponent<GridLayoutGroup>();
this.m_RectTransformGrid = this.m_GridLayoutGroup.GetComponent<RectTransform>();
foreach (var color in m_Color)
{
ScrollRectItem item = new GameObject().AddComponent<Image>().AddComponent<ScrollRectItem>();
m_Item.Enqueue(item);
item.Show(color, this);
}
await Task.Delay(TimeSpan.FromSeconds(0.1f));
minY = -this.m_RectTransformGrid.rect.height + this.m_GridLayoutGroup.cellSize.y / 2;
maxY = -this.m_GridLayoutGroup.cellSize.y / 2;
}
private void OnDestroy()
{
while (m_Item.Count > 0) { Destroy(m_Item.Dequeue()); }
this.m_Item.Clear();
}
}
public class ScrollRectItem : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
RectTransform m_RectTransform;
ScrollRectManager m_ScrollRectManager;
Canvas m_CanvasThis;
GraphicRaycaster m_GraphicRaycaster;
public void OnDrag(PointerEventData eventData)
{
Vector2 localCursor;
//计算鼠标或触摸事件的局部位置
RectTransformUtility.ScreenPointToLocalPointInRectangle(this.m_ScrollRectManager.m_ScorllRect.content, eventData.position, eventData.pressEventCamera, out localCursor);
//重置位置
this.transform.localPosition = new Vector3(0, Mathf.Clamp(localCursor.y, this.m_ScrollRectManager.minY, this.m_ScrollRectManager.maxY), 0);
//重定义顺序 - 使用当前Item的位置,除以Item的高度+行间距,得到的值就是当前Item的Order
int order = (int)(this.transform.localPosition.y / -(this.m_ScrollRectManager.m_GridLayoutGroup.cellSize.y + this.m_ScrollRectManager.m_GridLayoutGroup.spacing.y));
if (order != this.transform.GetSiblingIndex())
{
this.transform.SetSiblingIndex(order);
}
}
public void OnPointerDown(PointerEventData eventData)
{
this.m_CanvasThis.sortingOrder = 2;
}
public void OnPointerUp(PointerEventData eventData)
{
this.m_CanvasThis.sortingOrder = 1;
///松开后,刷新列表
LayoutRebuilder.ForceRebuildLayoutImmediate(this.m_ScrollRectManager.m_GridLayoutGroup.transform as RectTransform);
}
public async void Show(Color m_Color, ScrollRectManager m_ScrollRectManager)
{
this.m_ScrollRectManager = m_ScrollRectManager;
this.transform.SetParent(this.m_ScrollRectManager.m_ScorllRect.content);
this.GetComponent<Image>().color = m_Color;
this.transform.name = UnityEngine.ColorUtility.ToHtmlStringRGB(m_Color);
this.m_RectTransform = this.GetComponent<RectTransform>();
this.m_RectTransform.pivot = new Vector2(0.5f, 0.5f);
this.m_CanvasThis = this.AddComponent<Canvas>();
this.m_GraphicRaycaster = this.AddComponent<GraphicRaycaster>();
await Task.Yield();
this.m_CanvasThis.overrideSorting = true;
this.m_CanvasThis.sortingOrder = 1;
}
}
最终效果
<iframe allowfullscreen="true" data-mediaembed="csdn" frameborder="0" id="yAUsFf2O-1717397477390" src="https://live.csdn.net/v/embed/395695"></iframe>ScrollRect Drag Item示例效果
备注
本案列仅仅是垂直单列的案列,其他列表可结合当前案列进行调整。
unitypackage
https://pan.baidu.com/s/11RzOJy6tHOEkftiHTJHyjw?pwd=wbzq
提取码:wbzq
unity版本:2022.3