1. 程式人生 > >Unity控件ScrollView使用問題記錄

Unity控件ScrollView使用問題記錄

是否 ems img htm code script oat lsi 官方文檔

Unity版本:5.6.2

控件Scroll View由4部分組成,如圖:

1.含有Scroll Rect組件的根節點:Scroll View

2.含有Mask組件的節點:Viewport

3.所有內容的父節點Content,常含有布局控件

4.滾動條,包括橫向和縱向
技術分享

具體的節點細節使用可以參看官方文檔:
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中加入對應的布局組件即可。

技術分享

4.出現無法滑動或者自動回彈到原地方的原因?

如果節點Content的寬度或者高度小於實際內容的寬度或者高度時,就會發生這樣的情況。這時需要調整Content的寬高,或者加入組件Content Size Fitter把對應方向設置為Preferred Size來自適應寬高。

5.滑動結束後,往往不能把當前的元素的畫面完整顯示的情況,如何解決?
技術分享

這種情況需要給節點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 = -1; public GameObject CurCenterChildItem { get { GameObject centerChild = null; if (_content != null && 0 <= _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) * 0.5f; _childrenPos.Add(childPosX); spacing = (layoutGroup as HorizontalLayoutGroup).spacing; for (int i = 1; i < _content.childCount; i++) { childPosX -= GetChildItemWidth(i) * 0.5f + GetChildItemWidth(i - 1) * 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 = 1; 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) * 0.5f; _childrenPos.Add(childPosY); spacing = (layoutGroup as VerticalLayoutGroup).spacing; for (int i = 1; i < _content.childCount; i++) { childPosY += GetChildItemHeight(i) * 0.5f + GetChildItemHeight(i - 1) * 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 = 1; 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 = -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; } }

改完之後的效果:

技術分享

您的打賞是對我的最大支持和肯定

技術分享技術分享

Unity控件ScrollView使用問題記錄