一、目的
效果图如下
二、实现
Unity组件:
脚本如下:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ScrollRectHorizontalCenter : MonoBehaviour , IEndDragHandler,IDragHandler,IBeginDragHandler
{
/// <summary>
/// 是否正在居中
/// </summary>
private bool _isCentering = false;
/// <summary>
/// 居中过程移动速度
/// </summary>
public float MoveToCenterSpeed = 10f;
private ScrollRect _scrollView;
private Transform _content;
private List<float> _childrenPos = new List<float>();
private List<Text> _childrenText = new List<Text>();
private float _targetPos;
private Color seletedColor = new Color (249/255f,1,181/255f);
private Color unseleteColor = new Color (150/255f,128/255f,128/255f);
private int maxChild;
/// <summary>
/// 当前中心child索引
/// </summary>
private int _curCenterChildIndex = -1;
void Start()
{
_scrollView = GetComponent<ScrollRect>();
if (_scrollView == null)
{
Debug.LogError("ScrollRect is null");
return;
}
_content = _scrollView.content;
LayoutGroup layoutGroup = null;
layoutGroup = _content.GetComponent<LayoutGroup>();
if (layoutGroup == null)
{
Debug.LogError("LayoutGroup component is null");
}
_scrollView.movementType = ScrollRect.MovementType.Unrestricted;
float spacing = 0f;
//根据dir计算坐标,Horizontal:存x,Vertical:存y
float childPosX = _scrollView.GetComponent<RectTransform>().rect.width * 0.5f - GetChildItemWidth(0) * 0.5f;
spacing = (layoutGroup as HorizontalLayoutGroup).spacing;
_childrenPos.Add(childPosX);
Text _t = _content.GetChild (0).GetComponent<Text> ();
_childrenText.Add (_t);
for (int i = 1; i < _content.childCount; i++)
{
childPosX -= GetChildItemWidth(i) * 0.5f + GetChildItemWidth(i - 1) * 0.5f + spacing;
_childrenPos.Add(childPosX);
_t = _content.GetChild (i).GetComponent<Text> ();
_childrenText.Add (_t);
}
maxChild = _content.childCount;
_curCenterChildIndex = maxChild - 1;
_content.localPosition = new Vector3(_childrenPos[_curCenterChildIndex],_content.localPosition.y,_content.localPosition.z);
SetTexts ();
}
private float GetChildItemWidth(int index)
{
return (_content.GetChild(index) as RectTransform).sizeDelta.x;
}
private float GetChildItemHeight(int index)
{
return (_content.GetChild(index) as RectTransform).sizeDelta.y;
}
void Update ()
{
if (_isCentering)
{
Vector3 v = _content.localPosition;
v.x = Mathf.Lerp(_content.localPosition.x, _targetPos, MoveToCenterSpeed * Time.deltaTime);
_content.localPosition = v;
if (Math.Abs(_content.localPosition.x - _targetPos) < 0.01f)
{
_isCentering = false;
}
}
}
public void OnDrag(PointerEventData eventData)
{
SetTexts ();
}
public void OnEndDrag(PointerEventData eventData)
{
SetTexts ();
_isCentering = true;
}
public void OnBeginDrag(PointerEventData eventData)
{
_isCentering = false;
_curCenterChildIndex = -1;
}
private float FindClosestChildPos(float currentPos, out int curCenterChildIndex)
{
float closest = 0;
float distance = Mathf.Infinity;
curCenterChildIndex = -1;
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;
curCenterChildIndex = i;
}
}
return closest;
}
private void SetTexts()
{
_targetPos = FindClosestChildPos(_content.localPosition.x, out _curCenterChildIndex);
for (int i = 0; i < maxChild; i++)
{
Text _text = _childrenText [i];
if (i == _curCenterChildIndex) {
_text.fontSize = 28;
_text.color = seletedColor;
} else if (i == _curCenterChildIndex - 1 || i == _curCenterChildIndex + 1) {
_text.fontSize = 24;
_text.color = unseleteColor;
} else {
_text.fontSize = 18;
_text.color = unseleteColor;
}
}
}
public int GetCurCenterChildIndex()
{
return _curCenterChildIndex;
}
}