UGUI nest ScrollView drag event passer

UGUI nest ScrollView drag event passer

For the first time using UGUI to develop the nest layout, very easy to arrange the basic UI elements,
simply click & drag..etc
and study some article on : http://k79k06k02k.com/blog/542/unity/unity-ugui-%E5%8E%9F%E7%90%86%E7%AF%87%E4%BA%94%EF%BC%9Aauto-layout-%E8%87%AA%E5%8B%95%E4%BD%88%E5%B1%80

here is the first problem that I meet, the ScrollRect (ScrollView) within another ScrollRect will not pass the drag event to their parent(s)


well, it not a bug but I insist developer should able to easier design which event can bubble up to their parent.
for that reason I did some research on unity forum and realize the Event System limitation and behavior.
ref:

and created follow script to redirect the drag event to another specified ScrollRect (ScrollView)

UIDragPasser.cs

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

namespace Kit.UI
{
	[RequireComponent(typeof(ScrollRect))]
	public class UIDragPasser : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
	{
		public ScrollRect m_Scroll;
		public ScrollRect m_OtherScroll;

		[Range(0f, 1f)]
		public float m_MinThrehold;
		[Range(0f, 1f)]
		public float m_MaxThrehold;

		private bool m_Allow = false;

		void OnValidate()
		{
			if (m_Scroll == null)
				m_Scroll = GetComponent<ScrollRect>();

			if (m_OtherScroll == m_Scroll)
				m_OtherScroll = null;
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			m_Allow = IsAllow(eventData);
			if (m_Allow)
			{
				m_OtherScroll.OnBeginDrag(eventData);
				m_OtherScroll.SendMessage("OnBeginDrag", eventData, SendMessageOptions.DontRequireReceiver);
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
			if (m_Allow)
			{
				m_OtherScroll.OnDrag(eventData);
				m_OtherScroll.SendMessage("OnDrag", eventData, SendMessageOptions.DontRequireReceiver);
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			if (m_Allow)
			{
				m_OtherScroll.OnEndDrag(eventData);
				m_OtherScroll.SendMessage("OnEndDrag", eventData, SendMessageOptions.DontRequireReceiver);
			}
		}

		private bool IsAllow(PointerEventData eventData)
		{
			if (!m_Scroll.vertical && !m_Scroll.horizontal)
			{
				return true;
			}
			else if (m_Scroll.horizontal)
			{
				return
					(Mathf.Abs(eventData.delta.y) > Mathf.Abs(eventData.delta.x)) || // Main direction
					(eventData.delta.x < 0f && m_Scroll.horizontalNormalizedPosition < m_MinThrehold) || // Left
					(eventData.delta.x > 0f && m_Scroll.horizontalNormalizedPosition > m_MaxThrehold); // Right
			}
			else // if (m_Scroll.vertical)
			{
				return
					(Mathf.Abs(eventData.delta.x) > Mathf.Abs(eventData.delta.y)) || // Main direction
					(eventData.delta.y > 0f && m_Scroll.verticalNormalizedPosition < m_MinThrehold) || // Bottom
					(eventData.delta.y < 0f && m_Scroll.verticalNormalizedPosition > m_MaxThrehold); // Top
			}
		}
	}
}

by attach this script on ScrollRect (ScrollView) you can define which ScrollRect can receive the drag event
feature : when current Scroll are reaching the limit, the event should pass to its parents

UIDragPasser

as example 0.1f(Min) is bottom/left, 0.9f(Max) is top/right, well the direction was a little bit confuse me.
its not perfect, and still require developer to manually setup the UIDragPasser.cs, but at least we have a way to do it.

UIDragPasser_setup

and then the result for apply this script.

and now I’m thinking about to implement the Infinitely loop content during scrolling Scrollview, any suggestion ?!

Study:

seem someone did it before~

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

*

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料