using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; [RequireComponent(typeof(ScrollRect))] public class UIScrollFocusHelper: MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public GameObject itemTemplate; public Transform focusItemTrans; private ScrollRect _scrollRect; private GameObject _content; private bool _isVertical; private List _itemList; private Delegate _focusItemFunc; private Delegate _unFocusItemFunc; #region DragHandler public void OnBeginDrag(PointerEventData eventData) { } public void OnDrag(PointerEventData eventData) { if (_itemList == null) { return; } for (int i = 0; i < _itemList.Count; i++) { var item = _itemList[i]; var posX = item.GetComponent().position.x; var distance = Mathf.Abs(posX - focusItemTrans.GetComponent().position.x); if (distance < _GetLimitDistance()) { if (_focusItemFunc != null) { if (_focusItemFunc is Action action) { action.Invoke(item); } } } else { if (_unFocusItemFunc != null) { if (_unFocusItemFunc is Action unFocusAction) { unFocusAction.Invoke(item); } } } } } public void OnEndDrag(PointerEventData eventData) { } #endregion #region UnityEvent Function private void Awake() { _scrollRect = gameObject.GetComponent(); if (!_scrollRect) { DebugUtil.LogError("UIScrollFocusHelper Error!!! 请检查节点是否绑定ScrollRect组件!!! "); return; } _content = _scrollRect.transform.Find("Viewport/Content").gameObject; bool isVertical = true; if (_scrollRect.horizontal) { if (_scrollRect.vertical) { DebugUtil.LogError("UIScrollFocusHelper Error!!! 仅支持ScrollRect单方向拖动!!! "); return; } isVertical = false; } _isVertical = isVertical; var layoutGroup = _GetContentLayoutGroup(); if (layoutGroup) { if (_isVertical) { layoutGroup = (VerticalLayoutGroup)layoutGroup; } else { layoutGroup = (HorizontalLayoutGroup)layoutGroup; } } } #endregion private LayoutGroup _GetContentLayoutGroup() { if (!_content) { DebugUtil.LogError("UIScrollFocusHelper Error!!! 请检查ScrollRect的Content节点!!! "); } var layoutGroup = _content.GetComponent(); return layoutGroup; } private float _GetLimitDistance() { var rect = itemTemplate.GetComponent().rect; return rect.width * 0.5f; } #region API public void SetData(List list) { _itemList = list; } public void SetFocusItemFunc(Action action) { _focusItemFunc = action; } public void SetUnFocusItemFunc(Action action) { _unFocusItemFunc = action; } #endregion }