APP滑动翻页,嵌套滑动列表实现

        双重滑动列表比较重要的点就是在于父子列表的滑动事件传递,不然在上的Scroll Rect会覆盖下层的,导致下层事件不响应。其次就是滑动后的页数位置判断,将UI能自动滑到对应的页数。

        首先来看最重要的事件传递,由于Scroll Rect没有自带可使用的滑动事件,于是我们就直接注册Unity的事件接口即可:

IBeginDragHandler, 鼠标按下时触发,
IDragHandler, 鼠标保持按下状态时会一直触发
IEndDragHandler 结束鼠标拖动,松开的时候会触发一次

这里有个坑注意一下,即使你只需要用到其中一个事件,也必须要有IDragHandle,不然不会触发滑动事件,具体代码实现如下:

public void OnBeginDrag(PointerEventData eventData)
    {
        PointerEventData pointerEventData = (PointerEventData)eventData;
        if (_thisScroll.horizontal)
        {   
            float angle = Mathf.Acos(Vector2.Dot(Vector2.up.normalized, pointerEventData.delta.normalized)) * Mathf.Rad2Deg; 
            if (angle < 45f || angle > 135f)
            {
                 pointerEventData.pointerDrag = _outsideScroll.gameObject;
                 _outsideScroll.OnBeginDrag(pointerEventData); 
            } 
            else
             { 
                pointerEventData.pointerDrag = _thisScroll.gameObject;  
                _thisScroll.OnBeginDrag(pointerEventData); 
            }
        }
        else if (_thisScroll.vertical)
        { 
            float angle = Mathf.Acos(Vector2.Dot(Vector2.right.normalized, pointerEventData.delta.normalized)) * Mathf.Rad2Deg; 
            if (angle < 45f || angle > 135f) 
            { 
                pointerEventData.pointerDrag = _outsideScroll.gameObject; 
                _outsideScroll.OnBeginDrag(pointerEventData); 
            } 
            else 
            { 
                pointerEventData.pointerDrag = _thisScroll.gameObject; 
                _thisScroll.OnBeginDrag(pointerEventData); 
            } 
        } 
        else 
        { 
            pointerEventData.pointerDrag = _outsideScroll.gameObject; 
            _outsideScroll.OnBeginDrag(pointerEventData);
        }
    }
    public void OnEndDrag(PointerEventData eventData) 
    {
        PointerEventData pointerEventData = (PointerEventData)eventData; 
        if (pointerEventData.pointerDrag == _outsideScroll.gameObject)
        {
            _outsideScroll.OnEndDrag(eventData);
        }
        else
        { 
            _thisScroll.OnEndDrag(eventData);
        } 
    }
    public void OnDrag(PointerEventData eventData) 
    { 
        PointerEventData pointerEventData = (PointerEventData)eventData;
        if (pointerEventData.pointerDrag == _outsideScroll.gameObject)
        {
            _outsideScroll.OnDrag(eventData);
        } 
        else 
        { 
            _thisScroll.OnDrag(eventData);
        } 
    }

主要逻辑就是通过开始拖拽事件判断角度,从而判断是横向滑动还是竖向滑动,并通向正确的Scroll Rect滑动事件。

然后外层挂载的滑动列表事件具体如下,主要是用来判断显示的页数,并自动滑到那一页。

            private ScrollRect rect;
            private List<float> posList = new List<float>();
            private int curIndex = -1;
            public float speed = 4;
            private bool _isDragging = false;
            public Action<int> onChildSelected = null;


            private void Awake()
            {
                ReferenceCollector referenceCollector = gameObject.GetComponent<ReferenceCollector>();

                rect = GetComponent<ScrollRect>();
                for (int i = 0; i < rect.content.transform.childCount; i++)
                {
                    posList.Add(i * (1.0f / (float)(rect.content.transform.childCount - 1)));
                }
            }

            private void Start()
            {
                PageTo(0);
            }

            private void Update()
            {
                if (curIndex >= 0 && !_isDragging)
                {
                    rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition,
                        posList[curIndex], Time.deltaTime * speed);
                }
            }

            public void OnBeginDrag(PointerEventData eventData)
            {
                _isDragging = true;
                rect.OnBeginDrag(eventData);
            }

            public void OnEndDrag(PointerEventData eventData)
            {
                rect.OnEndDrag(eventData);
                _isDragging = false;
                int index = 0;
                for (int i = 1; i < posList.Count; i++)
                {
                    if (Mathf.Abs(posList[i] - rect.horizontalNormalizedPosition) <
                        Mathf.Abs(posList[index] - rect.horizontalNormalizedPosition))
                    {
                        index = i;
                    }
                }

                PageTo(index);
            }

            public void OnDrag(PointerEventData eventData)
            {
                rect.OnDrag(eventData);
            }

            public void PageTo(int index)
            {
                if (curIndex != index)
                {
                    curIndex = index;
                    if (onChildSelected != null)
                    {
                        onChildSelected(curIndex);
                    }
                }
            }
        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值