因爲項目須要+有網友諮詢,因此作了個橫向滑頁+某一橫向滑頁中有豎向滑頁的demo,實現有點繞彎子,但基本功能仍是比較完善,發上來共享一下。
第一步的思路是本身判斷觸屏拖動位置,而後控制界面橫向或者縱向滑動。 而後, 因爲UGUI組件重疊時會屏蔽事件 好比Button會屏蔽掉PointerDown (PS:固然也能夠採起繼承UGUI組件的方式釋放屏蔽事件, 這裏對UGUI源碼不熟,採起本身寫一個事件分發器方便一點)
這裏就不贅述咯,個人前一篇blog有詳細配置說明: 1.首先創建兩個ScrollRect
2.分別給兩個ScrollRect配置格子的ScrollBar,而後關掉如下設置
3.在最外層的ScrollRect配置ScrollControl代碼 (PS:代碼後續給出)
4.配置InputControl (PS:新建一個Gameobjct就能夠咯,也能夠掛在已有物體上)
5.運行,檢查效果...
代碼寫的比較急,不少不規範的地方,使用者請看懂邏輯以後自行重構,直接使用者有坑勿怪
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; } }
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); } } } }
目前來看效果還能夠,兩種滑動無干擾,有簡單的阻尼滑動效果,滑動分頁界限能夠設置 其餘如有什麼問題,歡迎留言