当前位置:   article > 正文

Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)_unity判断scrollrect停止滑动

unity判断scrollrect停止滑动

简介

由于项目需要+有网友咨询,所以做了个横向滑页+某一横向滑页中有竖向滑页的demo,实现有点绕弯子,但基本功能还是比较完善,发上来共享一下。
  • 1

效果

这里写图片描述

思路

第一步的思路是自己判断触屏拖动位置,然后控制界面横向或者纵向滑动。
然后,
由于UGUI组件重叠时会屏蔽事件
比如Button会屏蔽掉PointerDown

(PS:当然也可以采取继承UGUI组件的方式释放屏蔽事件,
这里对UGUI源码不熟,采取自己写一个事件分发器方便一点)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

项目配置

这里就不赘述咯,我的前一篇blog有详细配置说明:

1.首先建立两个ScrollRect
  • 1
  • 2
  • 3

这里写图片描述

2.分别给两个ScrollRect配置格子的ScrollBar,然后关掉以下设置
  • 1

这里写图片描述

3.在最外层的ScrollRect配置ScrollControl代码
(PS:代码后续给出)
  • 1
  • 2

这里写图片描述

4.配置InputControl
(PS:新建一个Gameobjct就可以咯,也可以挂在已有物体上)
  • 1
  • 2

这里写图片描述
这里写图片描述

5.运行,检查效果...
  • 1

代码

代码写的比较急,很多不规范的地方,使用者请看懂逻辑之后自行重构,直接使用者有坑勿怪
  • 1

InputControl

using UnityEngine;

public delegate void MouseDownEvent(Vector2 mousePosition);
public delegate void MouseUpEvent(Vector2 mousePosition);
public delegate void MouseDragEvent(Vector2 dragVector);
public delegate void MouseClickEvent(Vector2 mousePosition);

public class InputControl : MonoBehaviour
{

    private static InputControl mInstance;

    /// <summary>
    /// 逗比单例模式
    /// </summary>
    public static InputControl Instance
    {
        get
        {
            return mInstance;
        }
    }

    private bool isPress;
    private bool isClick;
    private bool tempPress;
    private Vector2 oldMousePosition;
    private Vector2 tempMousePosition;

    public event MouseDownEvent EVENT_MOUSE_DOWN;
    public event MouseUpEvent EVENT_MOUSE_UP;
    public event MouseDragEvent EVENT_MOUSE_DRAG;
    public event MouseClickEvent EVENT_MOUSE_CLICK;

    /// <summary>
    /// 拖动起始判断参数,可自行更改
    /// </summary>
    public const float JUDGE_DISTANCE = 1F;

    void Awake()
    {
        mInstance = this;

        //以下代码可优化
        EVENT_MOUSE_DOWN += AvoidEmpty;
        EVENT_MOUSE_UP += AvoidEmpty;
        EVENT_MOUSE_DRAG += AvoidEmpty;
        EVENT_MOUSE_CLICK += AvoidEmpty;
    }

    void Start()
    {
        isPress = false;
        isClick = false;
    }

    /// <summary>
    /// 防空保护函数,无用处,可自行优化
    /// </summary>
    /// <param name="noUse"></param>
    private void AvoidEmpty(Vector2 noUse) { }

    void Update()
    {
        tempPress = Input.GetMouseButton(0);
        tempMousePosition = Input.mousePosition;
        // 两次状态不同,触发点击和抬起事件
        if (tempPress != isPress)
        {
            // 按下事件
            if (tempPress)
            {
                isClick = true;
                EVENT_MOUSE_DOWN(tempMousePosition);
            }
            // 抬起事件
            else
            {
                EVENT_MOUSE_UP(tempMousePosition);
                // 点击事件
                if (isClick)
                {
                    EVENT_MOUSE_CLICK(tempMousePosition);
                }
                isClick = false;
            }
        }
        // 按下的过程中发生了移动,发生事件变化
        else if (isClick && JudgeMove(oldMousePosition, tempMousePosition))
        {
            isClick = false;
        }
        // 拖动事件
        else if (tempPress && !isClick)
        {
            EVENT_MOUSE_DRAG(tempMousePosition - oldMousePosition);
        }

        isPress = tempPress;
        oldMousePosition = tempMousePosition;
    }

    /// <summary>
    /// 判断是否超出静止范围,用static速度更快
    /// </summary>
    /// <param name="p1"></param>
    /// <param name="p2"></param>
    /// <returns></returns>
    private static bool JudgeMove(Vector2 p1, Vector2 p2)
    {
        return Mathf.Abs(p1.x - p2.x) > JUDGE_DISTANCE || Mathf.Abs(p1.y - p2.y) > JUDGE_DISTANCE;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115

ScrollControl

using UnityEngine;
using UnityEngine.UI;

public class ScrollControl : MonoBehaviour
{

    /// <summary>
    /// 横向滚动条
    /// </summary>
    public Scrollbar m_HScrollBar;

    /// <summary>
    /// 竖向滚动条
    /// </summary>
    public Scrollbar[] m_VScrollBars;

    /// <summary>
    /// 有竖向滚动的页面
    /// </summary>
    public int[] m_VScrollIndexs;

    /// <summary>
    /// 页面个数
    /// </summary>
    public int m_Num;

    /// <summary>
    /// 设置移动超过多少百分比之后向下翻页
    /// </summary>
    public float m_NextLimit;

    /// <summary>
    /// 滑动敏感值
    /// </summary>
    public float m_Sensitive;

    /// <summary>
    /// 鼠标上一次的位置
    /// </summary>
    private Vector3 mOldPosition;

    /// <summary>
    /// 记录上一次的value
    /// </summary>
    private float mOldValue;

    private float mTargetPosition = 0.5f;

    private int mCurrentIndex = 3;

    private int mTargetIndex = 3;

    /// <summary>
    /// 是否可以移动
    /// </summary>
    private bool mCanMove = false;

    /// <summary>
    /// 初始移动速度
    /// </summary>
    private float mMoveSpeed;

    /// <summary>
    /// 平滑移动参数
    /// </summary>
    private const float SMOOTH_TIME = 0.2F;

    private float mDragParam = 0;
    private float mPageWidth = 0;

    /// <summary>
    /// 是否需要进行滑动方向判定
    /// </summary>
    private bool mNeedCaculate = false;

    /// <summary>
    /// 是否进行竖向滚动
    /// </summary>
    private bool mIsScollV = false;

    /// <summary>
    /// 竖向临时滚动条
    /// </summary>
    private Scrollbar mVScrollBar;

    public void SetNextIndex(int pIndex)
    {
        mTargetIndex = pIndex;
        mTargetPosition = (mTargetIndex - 1) * mPageWidth;
        mIsScollV = false;
        mCanMove = true;
    }

    private void OnPointerDown(Vector2 mousePosition)
    {
        // 记录当前value
        mOldValue = m_HScrollBar.value;
        mOldPosition = Input.mousePosition;
        // mCanMove = false;
        mCurrentIndex = GetCurrentIndex(mOldValue);
        // 判断当前是否在可竖向滑动的页面上
        for (int i = 0; i < m_VScrollIndexs.Length; ++i)
        {
            if (m_VScrollIndexs[i] == mCurrentIndex)
            {
                mNeedCaculate = true;
                mVScrollBar = m_VScrollBars[i];
                break;
            }
        }
    }

    private void OnDrag(Vector2 mousePosition)
    {

        Vector2 dragVector = Input.mousePosition - mOldPosition;

        if (mNeedCaculate)
        {
            mNeedCaculate = false;

            if (Mathf.Abs(dragVector.x) > Mathf.Abs(dragVector.y))
            {
                mIsScollV = false;
            }
            else
            {
                mIsScollV = true;
            }
        }

        DragScreen(dragVector);

        mOldPosition = Input.mousePosition;
    }

    private void OnPointerUp(Vector2 mousePosition)
    {
        Vector2 dragVector = Input.mousePosition - mOldPosition;
        DragScreen(dragVector);

        mOldPosition = Input.mousePosition;

        float valueOffset = m_HScrollBar.value - mOldValue;
        if (Mathf.Abs((valueOffset) / mPageWidth) > m_NextLimit)
        {
            mTargetIndex += valueOffset > 0 ? 1 : -1;
            mTargetPosition = (mTargetIndex - 1) * mPageWidth;
        }

        mCanMove = true;
    }

    private int GetCurrentIndex(float pCurrentValue)
    {
        return Mathf.RoundToInt(pCurrentValue / mPageWidth + 1);
    }

    private void DragScreen(Vector2 pDragVector)
    {
        if (mIsScollV)
        {
            float oldValue = mVScrollBar.value;
            mVScrollBar.value -= pDragVector.y / Screen.height * mVScrollBar.size;
            mMoveSpeed = mVScrollBar.value - oldValue;
        }
        else
        {
            float oldValue = m_HScrollBar.value;
            m_HScrollBar.value -= pDragVector.x / Screen.width * mDragParam;
            mMoveSpeed = m_HScrollBar.value - oldValue;
        }
    }

    void Awake()
    {
        if (m_Num <= 1)
        {
            Debug.LogError("参数错误:页面个数不对");
        }
        mDragParam = 1f / (m_Num - 1) * m_Sensitive;
        mPageWidth = 1f / (m_Num - 1);
        mCurrentIndex = GetCurrentIndex(m_HScrollBar.value);
        mTargetIndex = mCurrentIndex;
    }

    void Start()
    {
        InputControl.Instance.EVENT_MOUSE_DOWN += OnPointerDown;
        InputControl.Instance.EVENT_MOUSE_UP += OnPointerUp;
        InputControl.Instance.EVENT_MOUSE_DRAG += OnDrag;
    }

    void OnDestory()
    {
        InputControl.Instance.EVENT_MOUSE_DOWN -= OnPointerDown;
        InputControl.Instance.EVENT_MOUSE_UP -= OnPointerUp;
        InputControl.Instance.EVENT_MOUSE_DRAG -= OnDrag;
    }


    void Update()
    {
        if (mCanMove)
        {
            if (mIsScollV)
            {
                mVScrollBar.value += mMoveSpeed;
                float absValue = Mathf.Abs(mMoveSpeed);
                absValue -= 0.001f;
                if (absValue <= 0)
                {
                    mCanMove = false;
                }
                else
                {
                    mMoveSpeed = mMoveSpeed > 0 ? absValue : -absValue;
                }
            }
            else
            {
                if (Mathf.Abs(m_HScrollBar.value - mTargetPosition) < 0.01f)
                {
                    m_HScrollBar.value = mTargetPosition;
                    mCurrentIndex = mTargetIndex;
                    mCanMove = false;
                    return;
                }
                m_HScrollBar.value = Mathf.SmoothDamp(m_HScrollBar.value, mTargetPosition, ref mMoveSpeed, SMOOTH_TIME);
            }

        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235

总结

目前来看效果还可以,两种滑动无干扰,有简单的阻尼滑动效果,滑动分页界限可以设置

其他若有什么问题,欢迎留言
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/106808
推荐阅读
相关标签
  

闽ICP备14008679号