Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
来源:互联网 发布:淘宝店铺动态在哪里看 编辑:程序博客网 时间:2024/06/11 22:47
简介
由于项目需要+有网友咨询,所以做了个横向滑页+某一横向滑页中有竖向滑页的demo,实现有点绕弯子,但基本功能还是比较完善,发上来共享一下。
效果
思路
第一步的思路是自己判断触屏拖动位置,然后控制界面横向或者纵向滑动。然后,由于UGUI组件重叠时会屏蔽事件比如Button会屏蔽掉PointerDown(PS:当然也可以采取继承UGUI组件的方式释放屏蔽事件,这里对UGUI源码不熟,采取自己写一个事件分发器方便一点)
项目配置
这里就不赘述咯,我的前一篇blog有详细配置说明:1.首先建立两个ScrollRect
2.分别给两个ScrollRect配置格子的ScrollBar,然后关掉以下设置
3.在最外层的ScrollRect配置ScrollControl代码(PS:代码后续给出)
4.配置InputControl(PS:新建一个Gameobjct就可以咯,也可以挂在已有物体上)
5.运行,检查效果...
代码
代码写的比较急,很多不规范的地方,使用者请看懂逻辑之后自行重构,直接使用者有坑勿怪
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; }}
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); } } }}
总结
目前来看效果还可以,两种滑动无干扰,有简单的阻尼滑动效果,滑动分页界限可以设置其他若有什么问题,欢迎留言
0 0
- Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
- Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
- Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
- Android 解决ScrolView嵌套GridView冲突问题
- 解决scrollView嵌套listview的冲突问题
- 解决ViewPager嵌套ViewPager滑动冲突问题
- 解决ViewPager嵌套ViewPager滑动冲突问题
- 解决ScrollView嵌套viewpager冲突问题
- 解决ScrollView嵌套viewpager的冲突问题
- Scrollview嵌套listVIew冲突问题的解决
- 解决RecycleView嵌套RecycleView滑动冲突问题
- ListView解决嵌套冲突
- Viewpager嵌套冲突问题
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- ScrollView嵌套Recycler View嵌套冲突解决
- 【chage】修改账号或密码的有效期限
- spoj CPTTRN7 - Character Patterns (Act 7)
- 在windows下搭建hadoop工程(二)之 WordCount 作业测试
- java线程的几种状态
- Android apk大小优化之自我实践
- Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
- JavaScript中call,apply,bind方法的总结。
- C#中的 int?是什么意思
- hdu 1151 匈牙利算法
- 数据库SQL优化大总结之 百万级数据库优化方案
- 通过HSV进行RGB二值化,
- 偷天换日:网络劫持,网页js被伪装替换。
- 【chgrp】修改文件属组
- apktool反编译apk,提取资源文件