Unity——Scroll View 滑动居中(仅支持横版、横竖都支持的 看另外一篇)

一、目的

效果图如下

 

二、实现

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;
	}
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity中的ScrollView组件可以实现滑动效果,可以用于显示大量内容的列表或者滚动视图。用户可以通过手势或者鼠标滚轮来滑动视图,从而查看不同的内容。ScrollView组件需要包含一个Content子对象,用于存放要显示的内容。可以通过设置Content的大小和位置来控制滑动视图的范围和滚动条的位置。在代码中,可以通过调用ScrollViewScrollTo方法来控制滑动位置。 ### 回答2: Unity Scroll ViewUnity中提供的一种用于滚动界面的工具。使用Scroll View可以轻松实现在界面内显示过长的内容,从而增加界面的可读性和互动性。Scroll View可以用于多种类型的内容,例如文本、图像、列表等等。 在Unity中使用Scroll View非常简单。首先,在场景中创建一个Scroll View对象,然后将需要滚动的内容添加到Scroll View的视图框内。接着,设置Scroll View的属性,如滚动速度、边界等等。最后,在脚本中调用Scroll View的方法,即可实现滚动。 Scroll View滑动可以通过鼠标、触摸屏或键盘进行操作。在移动设备上,用户可以通过手指在屏幕上滑动实现滚动。而在PC上,则可以通过鼠标滚轮或方向键来进行滚动。 Scroll View除了支持基本的滚动功能外,还支持多种扩展功能。例如,可以通过代码来动态添加、删除和修改视图框中的内容;也可以通过代码来控制滚动条的显隐和位置等等。 总之,Scroll ViewUnity中非常实用的一个工具,可以用于各种类型的应用程序和游戏。掌握Scroll View的使用方法,可以大大提升界面的交互性和用户体验。 ### 回答3: UnityScrollViewUnity中常用的滑动控件,它通常用于展示大量的内容,同时也能够进行滚动浏览。下面我们来详细了解一下UnityScrollView的相关知识。 首先,在使用ScrollView前需要先在场景中选择一个空的GameObject,并将其添加上ScrollView组件。接下来在ScrollView组件中可以看到一个RectTransform,我们需要在其中添加一个Panel,这个Panel就是ScrollView滑动容器,所有需要展示的内容都要添加到这个Panel中。同时在ScrollView的组件中,需要设置Viewport的值,将其指向我们添加的Panel。 接下来就是设置ScrollView滑动属性,其中Scroll Rect组件表示滑动的属性,可以设置滑动的速度,以及在滑动时是否需要惯性效果。 Content Size Fitter组件表示ScrollView滑动区域的大小,可以根据内容的实际大小进行自适应设置。Horizontal Layout Group和Vertical Layout Group分别表示横向和纵向的布局方式,可以根据需要选择不同的布局方式。Scrollbar组件表示ScrollView中的滚动条,可以设置滚动条的样式和位置等。 在ScrollView中添加内容也很简单,只需要在Panel中添加需要展示的内容即可,同时需要注意设置好Content Size Fitter以及Layout Group等属性,确保内容能够正常显示和适应不同屏幕的大小。同时,ScrollView还提供了一些事件,例如On Value Changed事件,在滚动时会触发,可以用于实现一些自定义的逻辑。 总之,使用UnityScrollView可以快速地实现复杂的滚动功能,同时它的设置和使用也不难,只需要注意ScrollView的各个组件的设置以及添加内容时的一些细节即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值