Unity控件ScrollView使用问题记录

时间:2023-03-09 06:31:24
Unity控件ScrollView使用问题记录

Unity版本:5.6.2

控件Scroll View由4部分组成,如图:

1.含有Scroll Rect组件的根节点:Scroll View

2.含有Mask组件的节点:Viewport

3.所有内容的父节点Content,常含有布局控件

4.滚动条,包括横向和纵向
Unity控件ScrollView使用问题记录

具体的节点细节使用可以参看官方文档:
https://docs.unity3d.com/560/Documentation/Manual/script-ScrollRect.html

使用时遇到的问题记录:

1.显示区域怎么控制?
节点Scroll View中的组件Rect Transform的Width和Height控制着整个区域大小,组件Scroll Rect的滚动条设置也会影响显示区域的边界位置是否完整;

节点Viewport的组件Image中的Image Type属性会影响显示的区域;

节点Content的组件Rect Transform的布局和宽高影响了显示的区域。

2.如何去掉滚动条?

节点Scroll View中的组件Scroll Rect中的属性Horizontal Scrollbar和Vertical Scrollbar设置为None,并将其子节点Scrollbar Horizontal和Scrollbar Vertical删除。

3.内容如何布局?

在节点Content中加入对应的布局组件即可。

Unity控件ScrollView使用问题记录

4.出现无法滑动或者自动回弹到原地方的原因?

如果节点Content的宽度或者高度小于实际内容的宽度或者高度时,就会发生这样的情况。这时需要调整Content的宽高,或者加入组件Content Size Fitter把对应方向设置为Preferred Size来自适应宽高。

5.滑动结束后,往往不能把当前的元素的画面完整显示的情况,如何解决?
Unity控件ScrollView使用问题记录

这种情况需要给节点Scroll View挂载脚本来实现,脚本:ScrollRectCenterChild.cs代码如下:

注意:Content节点的RectTransform组件中的Pivot属性必须设置为0,1

Content节点的布局方式可以是Vertical Layout Group、Horizontal Layout Group 或者 Grid Layout Group,但都只支持一个方向的滑动居中。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System; public enum ScrollDir
{
Horizontal,
Vertical
} public class ScrollRectCenterChild : MonoBehaviour,IEndDragHandler,IDragHandler,IBeginDragHandler
{
public ScrollDir Dir = ScrollDir.Vertical;
private bool _isCentering = false;
public float MoveToCenterSpeed = 10f;
private ScrollRect _scrollView;
private Transform _content;
//用于保存子元素的坐标值
private List<float> _childrenPos = new List<float>();
private float _targetPos;
private int _curCenterChildIndex = -; public GameObject CurCenterChildItem
{
get
{
GameObject centerChild = null;
if (_content != null && <= _curCenterChildIndex && _curCenterChildIndex < _content.childCount)
{
centerChild = _content.GetChild(_curCenterChildIndex).gameObject;
}
return centerChild;
}
} 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 Awake()
{
_scrollView = GetComponent<ScrollRect>();
if (null == _scrollView)
{
Debug.LogError("ScrollRect is null.");
return;
}
_content = _scrollView.content; LayoutGroup layoutGroup = null;
layoutGroup = _content.GetComponent<LayoutGroup>();
if (null == layoutGroup)
{
Debug.LogError("LayoutGroup comment is null.");
return;
} float spacing = 0f; switch (Dir)
{
case ScrollDir.Horizontal:
float scrollViewRectWidth = _scrollView.GetComponent<RectTransform>().rect.width;
if (layoutGroup is HorizontalLayoutGroup)
{
float childPosX = scrollViewRectWidth * 0.5f - GetChildItemWidth() * 0.5f;
_childrenPos.Add(childPosX);
spacing = (layoutGroup as HorizontalLayoutGroup).spacing;
for (int i = ; i < _content.childCount; i++)
{
childPosX -= GetChildItemWidth(i) * 0.5f + GetChildItemWidth(i - ) * 0.5f + spacing;
_childrenPos.Add(childPosX);
}
}
else if (layoutGroup is GridLayoutGroup)
{
GridLayoutGroup grid = layoutGroup as GridLayoutGroup;
float childPosX = scrollViewRectWidth * 0.5f - grid.cellSize.x * 0.5f;
_childrenPos.Add(childPosX);
for (int i = ; i < _content.childCount; i++)
{
childPosX -= grid.cellSize.x + grid.spacing.x;
_childrenPos.Add(childPosX);
}
}
else
{
Debug.LogError("Horizontal ScrollView is using VerticalLayoutGroup.");
}
break;
case ScrollDir.Vertical:
float scrollViewRectHeight = _scrollView.GetComponent<RectTransform>().rect.height;
if (layoutGroup is VerticalLayoutGroup)
{
float childPosY = scrollViewRectHeight * 0.5f - GetChildItemHeight() * 0.5f;
_childrenPos.Add(childPosY);
spacing = (layoutGroup as VerticalLayoutGroup).spacing;
for (int i = ; i < _content.childCount; i++)
{
childPosY += GetChildItemHeight(i) * 0.5f + GetChildItemHeight(i - ) * 0.5f + spacing;
_childrenPos.Add(childPosY);
} }
else if (layoutGroup is GridLayoutGroup)
{
GridLayoutGroup grid = layoutGroup as GridLayoutGroup;
float childPosY = scrollViewRectHeight * 0.5f - grid.cellSize.y * 0.5f;
_childrenPos.Add(childPosY);
for (int i = ; i < _content.childCount; i++)
{
childPosY += grid.cellSize.y + grid.spacing.y;
_childrenPos.Add(childPosY);
}
}
else
{
Debug.LogError("Vertical ScrollView is using HorizontalLayoutGroup.");
}
break;
}
} void Update()
{
if (_isCentering)
{
Vector3 v = _content.localPosition;
switch (Dir)
{
case ScrollDir.Horizontal:
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;
}
break;
case ScrollDir.Vertical:
v.y = Mathf.Lerp(_content.localPosition.y, _targetPos, MoveToCenterSpeed * Time.deltaTime);
_content.localPosition = v;
if (Math.Abs(_content.localPosition.y - _targetPos) < 0.01f)
{
_isCentering = false;
}
break;
}
}
} public void OnDrag(PointerEventData eventData)
{ } public void OnEndDrag(PointerEventData eventData)
{
switch (Dir)
{
case ScrollDir.Horizontal:
_targetPos = FindClosestChildPos(_content.localPosition.x, out _curCenterChildIndex);
break;
case ScrollDir.Vertical:
_targetPos = FindClosestChildPos(_content.localPosition.y, out _curCenterChildIndex);
break;
}
_isCentering = true;
} public void OnBeginDrag(PointerEventData eventData)
{
_isCentering = false;
_curCenterChildIndex = -;
} private float FindClosestChildPos(float currentPos, out int curCenterChildIndex)
{
float closest = ;
float distance = Mathf.Infinity;
curCenterChildIndex = -;
for (int i = ; 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;
}
}

改完之后的效果:

Unity控件ScrollView使用问题记录

-------------------------------------------------------------------

如果对您有帮助,请按下述操作:

点击文章下方Unity控件ScrollView使用问题记录

点击文章下方Unity控件ScrollView使用问题记录

点击文章下方Unity控件ScrollView使用问题记录

点击屏幕右下方Unity控件ScrollView使用问题记录

如果本文值得您分享,请点击文章下方Unity控件ScrollView使用问题记录