26
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Unity #2Advent Calendar 2018

Day 14

UGUIで多重スクロールを作る

Last updated at Posted at 2018-12-13

多重スクロールしたい!

少し調べたら、みんな大好きテラシュールブログに書いていましたが、
ちょっと違う部分もあるので、アドベントカレンダーの記事とさせていただきます。

##ためしにスクロールビューの中にスクロールビューを入れてみる
こうしてみると、親の方のスクロールビュー(以下、親)は反応せず、
子供の方のスクロールビュー(以下、子供)しか反応しなくなります。
これは、スクロールイベントが、子供で消費されてしまうため、
親にイベントが渡されないからです。
advent2018_1.gif

##親スクロールビューにイベントを渡す
子供で消費されるイベントを、親にも渡せれば、親が反応してくれます。
そのため、スクロールビュー(ScrollRect)を拡張し、渡されたイベントを親に通知する仕組みを作ることが考えられます。
UnityのuGUIで階層構造を持ったスクロールビューを作る

##既存のスクロールビューに追加で多重スクロールされるようにしたい
ここでScrollRectを拡張せずに、親へイベントを渡すことを考えてみます。

実は、子供で消費されてしまうイベントですが、
同ゲームオブジェクトにアタッチされているコンポーネントに関しては、
同じようにイベントを受け取ることができます。

ですので、子供が受け取っているイベントを別コンポーネント経由で親に渡せば、
既存のScrollRectを使って多重スクロールを実現することができます。

以下ソース

MultiScroller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using System.Linq;

public class MultiScroller : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler {
	[SerializeField]
	private IDragHandler[] m_parentDragHandlers;
	private IBeginDragHandler[] m_parentBeginDragHandlers;
	private IEndDragHandler[] m_parentEndDragHandlers;

	private bool isSelf = false;
	void Start () {
		m_parentDragHandlers = this.GetComponentsInParent<IDragHandler>().Where(p => !(p is MultiScroller)).ToArray();
		m_parentBeginDragHandlers = this.GetComponentsInParent<IBeginDragHandler>().Where(p => !(p is MultiScroller)).ToArray();
		m_parentEndDragHandlers = this.GetComponentsInParent<IEndDragHandler>().Where(p => !(p is MultiScroller)).ToArray();
	}
	
	public void OnDrag(PointerEventData ped)
	{
		foreach(var dr in m_parentDragHandlers)
		{
			dr.OnDrag(ped);
		}
	}
	public void OnBeginDrag(PointerEventData ped)
	{
		foreach(var dr in m_parentBeginDragHandlers)
		{
			dr.OnBeginDrag(ped);
		}
	}
	public void OnEndDrag(PointerEventData ped)
	{
		foreach(var dr in m_parentEndDragHandlers)
		{
			dr.OnEndDrag(ped);
		}
	}
}

※GetComponentでinterfaceを取得可能なので覚えておくと便利です。

これを使うとこうなります。
advent2018.png

advent2018_2.gif

##おまけ
この、別オブジェクトに直接イベントを渡してやる方式ですが、
応用すると、イベント周りの拡張がしやすくなります。

26
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?