zoukankan      html  css  js  c++  java
  • Unity控件ScrollView使用问题记录

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

    改完之后的效果:

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

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

    点击文章下方

    点击文章下方

    点击文章下方

    点击屏幕右下方

    如果本文值得您分享,请点击文章下方

  • 相关阅读:
    Server 对象
    Response 对象
    bzoj 5252: [2018多省省队联测]林克卡特树
    bzoj 2167: 公交车站
    bzoj 5315: [Jsoi2018]防御网络
    bzoj 5319: [Jsoi2018]军训列队
    bzoj 4161: Shlw loves matrixI
    bzoj 4942: [Noi2017]整数
    bzoj 2648: SJY摆棋子
    kd-tree 小结
  • 原文地址:https://www.cnblogs.com/stan-si/p/7459368.html
Copyright © 2011-2022 走看看