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:
- https://docs.unity3d.com/ScriptReference/EventSystems.EventTrigger.html
- http://answers.unity3d.com/questions/902929/scroll-not-working-when-elements-inside-have-click.html
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

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.

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~