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 如何處理網站訪客的留言資料