参考链接: http://www.cnblogs.com/suoluo/p/5535420.html
实现代码:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.EventSystems;
/// <summary>
/// Vertical center on child.
/// 这里面我用的是VerticalLayoutGroup进行自动布局
/// 用了ContentSizeFitter和LayoutElemen进行了自动填充的布局
/// 这里面的居中计算是根据anchoredPosition3D来计算的
/// </summary>
public class VerticalCenterOnChild : MonoBehaviour , IDragHandler, IEndDragHandler
{
//将子物体拉到中心位置时的速度
public float centerSpeed = 9f;
//注册该事件获取当拖动结束时位于中心位置的子物体
public delegate void OnCenterHandler (GameObject centerChild);
public event OnCenterHandler onCenter;
private ScrollRect _scrollView;
private RectTransform _container;
private List<float> _childrenPos = new List<float> ();
private float _targetPos;
private bool _centering = false;
void Awake ()
{
_scrollView = GetComponent<ScrollRect> ();
if (_scrollView == null)
{
Debug.LogError ("CenterOnChild: No ScrollRect");
return;
}
_container = _scrollView.content;
VerticalLayoutGroup grid;
grid = _container.GetComponent<VerticalLayoutGroup> ();
if (grid == null)
{
Debug.LogError ("CenterOnChild: No GridLayoutGroup on the ScrollRect's content");
return;
}
_scrollView.movementType = ScrollRect.MovementType.Unrestricted;
//计算第一个子物体位于中心时anchoredPosition3D.y的值
float childPosy = _container.anchoredPosition3D.y;
_childrenPos.Add (childPosy);
//这里我用了LayoutElement来布局,获取item的高度(可以根据不同的布局情况来获item高度)
float itemHeight = grid.GetComponentInChildren<LayoutElement>().preferredHeight;
//往上移动,计算每个item居中时的pivot到anchors的距离
for (int i = 0; i < _container.childCount - 1; i++)
{
childPosy += itemHeight + grid.spacing;
_childrenPos.Add (childPosy);
}
}
void Update ()
{
if (_centering)
{
Vector3 v = _container.anchoredPosition3D;
v.y = Mathf.Lerp (_container.anchoredPosition3D.y, _targetPos, centerSpeed * Time.deltaTime);
_container.anchoredPosition3D = v;
if (Mathf.Abs (_container.anchoredPosition3D.y - _targetPos) < 0.01f)
{
_centering = false;
}
}
}
public void OnEndDrag (PointerEventData eventData)
{
_targetPos = FindClosestPos (_container.anchoredPosition3D.y);
_centering = true;
}
public void OnDrag (PointerEventData eventData)
{
_centering = false;
}
//找到最近的点
private float FindClosestPos (float currentPos)
{
int childIndex = 0;
float closest = 0;
float distance = Mathf.Infinity;
//与记录的四个位置对比
for (int i = 0; i < _childrenPos.Count; i++)
{
float p = _childrenPos[i];
float d = Mathf.Abs (p - currentPos);
if (d < distance)
{
distance = d;
closest = p;
childIndex = i;
}
}
GameObject centerChild = _container.GetChild (childIndex).gameObject;
if (onCenter != null)
onCenter (centerChild);
return closest;
}
}
同样的,如果要改成谁水方向的话,只需要改成水平布局,获取item的宽度,以及改变 _container.anchoredPosition3D.x就行,其他不变