unity双层滑动实现

实现功能:
当滑动列表中内容处于顶端的时候,向上滑动优先滑动整个滑动列表,当滑动列表移动到设置位置,即设定的最高处时,继续移动列表内内容。向下移动亦然,当内容处于滑动列表顶端时,移动整个滑动列表。

eventtriggerlistener脚本可在这篇查看unity防止ui点击事件被子物体拦截

using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

public class ScrollViewMove : MonoBehaviour
{
    public ScrollRect m_scorllView;
    public RectTransform m_rectView;

    private void Start()
    {
        //添加滑动事件
        Graphic horizontalGraphic = m_scorllView.GetComponent<Graphic>();
        if (horizontalGraphic != null && horizontalGraphic.raycastTarget)
        {
            EventTriggerListener.Get(m_scorllView.gameObject).onBeginDrag = OnScrollBeginDrag;
            EventTriggerListener.Get(m_scorllView.gameObject).onDrag = OnScrollDrag;
            EventTriggerListener.Get(m_scorllView.gameObject).onEndDrag = OnScrollEndDrag;
        }

        //设置最高高度,和出现滑动时的阈值
        m_minHeight = m_scorllView.GetComponent<RectTransform>().localPosition.y;
        m_LimitY = (m_maxHeight - m_minHeight) * MOVE_DISTANCE_SCALE;
    }

    #region 滑动条事件

    //起始滑动位置
    private float m_startScrollHeight = 0f;
    //结束滑动位置
    private float m_endScrollHeight = 0f;
    //限制切换动画的最小判断
    private float m_LimitY;
    private readonly float MOVE_DISTANCE_SCALE = 0.2f;

    //起始鼠标位置
    private float m_startMouseHeight = 0f;
    //中途鼠标位置
    private float m_partMouseHeight = 0f;

    //最大高度
    private float m_maxHeight = 0f;
    //最小高度
    private float m_minHeight = 0f;

    //是否为展开状态
    private bool m_isOpen = false;

    /// <summary>
    /// 滑动列表开始拖拽事件
    /// </summary>
    /// <param name="obj"></param>
    private void OnScrollBeginDrag(GameObject obj)
    {
        m_startScrollHeight = m_scorllView.GetComponent<RectTransform>().localPosition.y;
        m_startMouseHeight = Input.mousePosition.y;
    }

    /// <summary>
    /// 滑动列表拖拽事件
    /// 先判断走拖拽事件还是滑动列表滑动事件
    /// </summary>
    /// <param name="obj"></param>
    private void OnScrollDrag(GameObject obj)
    {
        m_partMouseHeight = Input.mousePosition.y;
        float m_offsetHeight = m_partMouseHeight - m_startMouseHeight;
        m_startMouseHeight = m_partMouseHeight;

        float scrollPosY = m_scorllView.GetComponent<RectTransform>().localPosition.y;
        if (scrollPosY >= m_maxHeight)
        {
            if (m_offsetHeight >= 0)
            {
                m_scorllView.vertical = true;
                return;
            }
            else
            {
                if (m_scorllView.verticalNormalizedPosition < 1)
                {
                    m_scorllView.vertical = true;
                    return;
                }
            }
        }
        else if (scrollPosY <= m_minHeight)
        {
            if (m_offsetHeight <= 0)
            {
                m_scorllView.vertical = true;
                return;
            }
            else
            {
                if (m_scorllView.verticalNormalizedPosition > 1)
                {
                    m_scorllView.vertical = true;
                    return;
                }
            }
        }
        m_scorllView.verticalNormalizedPosition = 1;
        m_scorllView.vertical = false;

        OnPosDrag(m_offsetHeight);
    }

    /// <summary>
    /// 设置滑动位置
    /// </summary>
    /// <param name="offset"></param>
    private void OnPosDrag(float offset)
    {
        //设置滑动列表位置
        Vector3 scrollPos = m_scorllView.GetComponent<RectTransform>().localPosition;
        float endPosY = scrollPos.y + offset;
        if (endPosY > m_maxHeight)
        {
            offset = m_maxHeight - scrollPos.y;
        }
        else if (endPosY < m_minHeight)
        {
            offset = m_minHeight - scrollPos.y;
        }
        scrollPos = new Vector3(scrollPos.x, scrollPos.y + offset, scrollPos.z);

        m_scorllView.GetComponent<RectTransform>().localPosition = scrollPos;

        //设置滑动列表遮罩大小
        Vector2 viewPos = m_rectView.offsetMin;
        viewPos = new Vector2(viewPos.x, viewPos.y - offset);
        m_rectView.offsetMin = viewPos;
    }

    /// <summary>
    /// 滑动列表结束拖拽事件
    /// </summary>
    /// <param name="obj"></param>
    private void OnScrollEndDrag(GameObject obj)
    {
        m_endScrollHeight = m_scorllView.GetComponent<RectTransform>().localPosition.y;
        float offset = m_endScrollHeight - m_startScrollHeight;

        if (Mathf.Abs(offset) >= m_LimitY)
        {
            m_isOpen = (offset > 0);
        }

        ScrollDragAni(m_isOpen);
    }

    //动画播放时间
    private readonly float TWEEN_POS_TIME = 0.2f;

    /// <summary>
    /// 滑动条动画
    /// </summary>
    /// <param name="isOpen"></param>
    private void ScrollDragAni(bool isOpen)
    {
        Vector3 scrollPos = m_scorllView.GetComponent<RectTransform>().localPosition;
        if (isOpen)
        {
            DOTween.To(() => scrollPos.y,
                    (v) =>
                    {
                        Vector3 tmpVec = m_scorllView.GetComponent<RectTransform>().localPosition;
                        float offset = v - tmpVec.y;
                        OnPosDrag(offset);
                    }, m_maxHeight, TWEEN_POS_TIME).OnComplete(() => { m_isOpen = true; });
        }
        else
        {
            DOTween.To(() => scrollPos.y,
                    (v) =>
                    {
                        Vector3 tmpVec = m_scorllView.GetComponent<RectTransform>().localPosition;
                        float offset = v - tmpVec.y;
                        OnPosDrag(offset);
                    },  m_minHeight, TWEEN_POS_TIME).OnComplete(() => { m_isOpen = false; });
        }
    }

    #endregion
}

设置,在滑动列表中,将ViewPort设置成顶端锚点
在这里插入图片描述

相关推荐

  1. vue + element 实现鼠标左右滑动效果

    2024-03-31 22:30:01       39 阅读
  2. 【QT ScrollArea】手势滑动ScrollArea窗口实现

    2024-03-31 22:30:01       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-31 22:30:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-31 22:30:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-31 22:30:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-31 22:30:01       20 阅读

热门阅读

  1. 怎么使用Redis模拟Session

    2024-03-31 22:30:01       16 阅读
  2. DDPM pytorch代码详细注释

    2024-03-31 22:30:01       18 阅读
  3. 学习笔记之嵌入式八股文(C语言)

    2024-03-31 22:30:01       14 阅读
  4. 2024.2.3力扣每日一题——石子游戏7

    2024-03-31 22:30:01       15 阅读
  5. 6 字符串、元组和字典

    2024-03-31 22:30:01       13 阅读
  6. Unity 通过鼠标移动和LineRenderer组件实现画线功能

    2024-03-31 22:30:01       15 阅读
  7. stm32通过串口发送float数据的方法

    2024-03-31 22:30:01       13 阅读
  8. 求整数各个数位上的数字之和 C语言

    2024-03-31 22:30:01       14 阅读
  9. C++ //CCF-CSP计算机软件能力认证 201312-2 ISBN号码

    2024-03-31 22:30:01       15 阅读
  10. spring系列-动态注册bean

    2024-03-31 22:30:01       17 阅读