Unity之滑页效果&基于ScrollRect实现

Unity之滑页效果&基于ScrollRect实现

效果图

请添加图片描述

设计思路

  1. 基于ScrollRect的基础功能,本身在ScrollRect下的Content内容就是可以滑动的,但是它的滑动不符合预期
  2. 我们把滑动的效果设置为预期效果,那就需要获得开始滑动,滑动中,滑动结束的函数进行改造
  3. 我们在开始滑动记录位置,滑动中的幅度值,滑动结束记录位置,然后滑动结束时控制滑动效果
  4. 达到下一页的阈值,计算好下一页的位置,那就让页面Lerp插值到指定位置,滑动结束

场景搭建

创建一个scrollRect,替换ScrollRect脚本,使用我们自己的脚本ScrollRectBase,该脚本继承了ScrollRect,对其中一些关键方法进行了重写,并暴露一些关键事件给外界注册。
在这里插入图片描述
在Content下创建我们的页面,页面数量自定义,我这里创了5个页面。
创建一个导航栏,用来指示我当前所滑到的页面位置。

代码


    #region 重构拖拽相关的逻辑  
    //ScrollRect里面就带有滑动相关的特性,拖拽时Content里面的内容就是会动的,我要做的是在拖拽结束时执行自己想要的效果,而不是它自带的效果,就是在拖拽结束时快速切换到指定的页面,而不是缓动直至慢慢停止
    public override void OnBeginDrag(PointerEventData eventData)
    {
        if (UseDrag)
        {
            OnBeginDragInternal(eventData);
        }
    }

    public void OnBeginDragInternal(PointerEventData eventData)
    {
        base.OnBeginDrag(eventData);
        if (UsePage)
        {
            OnBeginDragPage(eventData);
        }
    }

    public override void OnDrag(PointerEventData eventData)
    {
        if (UseDrag)
        {
            OnDragInternal(eventData);
        }
    }

    public void OnDragInternal(PointerEventData eventData)
    {
        base.OnDrag(eventData);
        if (UsePage)
        {
            OnDragPage(eventData);
        }
        if (Drag != null)
        {
            Drag(eventData);
        }
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        if (UseDrag)
        {
            OnEndDragInternal(eventData);
        }
    }

    public void OnEndDragInternal(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);
        if (UsePage)
        {
            OnEndDragPage(eventData);
        }
    }


    ///开始拖拽
    private void OnBeginDragPage(PointerEventData eventData)
    {
        bDragging = true;
        BeginDragPos = eventData.position.x;
    }

    //拖拽中
    private void OnDragPage(PointerEventData eventData)
    {
        Debug.Log(eventData.delta);
        Vector2 delta = eventData.delta;
        speed = delta.x;
    }

    //拖拽结束
    private void OnEndDragPage(PointerEventData eventData)
    {
        EndDragPos = eventData.position.x;

        float LofR = BeginDragPos - EndDragPos;
        if (Mathf.Abs(speed) > SpeedCritical || Mathf.Abs(BeginDragPos - EndDragPos) > 400f)//能够切到下一页的阈值,一个是速度达到20,一个是滑动距离大于400
        {
            if (LofR < 0f)
            {
                currentPage = GetNextPage(currentPage, true);
            }
            else
            {
                currentPage = GetNextPage(currentPage, false);
            }
            currentPage = Mathf.Clamp(currentPage, 0, Page_Count - 1);
        }

        bUpdateEnd = false;
        bDragging = false;
        speed = 0f;
        BeginDragPos = 0;
        EndDragPos = 0;
        UpdateScrollEndPos();
        if (EndDragItem != null)
        {
            EndDragItem(currentPage);
        }
    }

    //计算停止页面的位置
    private void UpdateScrollEndPos()
    {
        scrollendpos = currentPage * (1f / ((float)Page_Count - 1));
    }

    //更新页面
    private void OnUpdatePage()
    {
        //拖拽过程中不更新页面
        if (bDragging || bSendFinish)
        {
            return;
        }
        if (base.horizontal)
        {
            base.horizontalNormalizedPosition = Mathf.Lerp(base.horizontalNormalizedPosition, scrollendpos, 15f * Time.deltaTime);
            float num = Mathf.Abs(base.horizontalNormalizedPosition - scrollendpos);
            Vector2 sizeDelta = base.content.sizeDelta;
            if (num * sizeDelta.x < 2f)//最后距离不多了直接到位
            {
                base.horizontalNormalizedPosition = scrollendpos;
                bUpdateEnd = true;
            }
        }
        if (bUpdateEnd)
        {
            if (mPageAniFinish != null)
            {
                mPageAniFinish();
            }
            bSendFinish = true;
        }
    }

    private void Update()
    {
        if (UsePage)
        {
             OnUpdatePage();
        }
    }

工程项目

链接:https://pan.baidu.com/s/1zuNIDWQrjcWiEwBlU-yYbA
提取码:xhg8

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值