/// Credit setchi (https://github.com/setchi) /// Sourced from - https://github.com/setchi/FancyScrollView using System; using System.Collections.Generic; using System.Linq; using UnityEngine.UI.Extensions.EasingCore; namespace UnityEngine.UI.Extensions { /// /// グリッドレイアウトのスクロールビューを実装するための抽象基底クラス. /// 無限スクロールおよびスナップには対応していません. /// /// アイテムのデータ型. /// の型. public abstract class FancyGridView : FancyScrollRect where TContext : class, IFancyScrollRectContext, IFancyGridViewContext, new() { /// /// カラム同士の余白. /// [SerializeField] protected float columnSpacing = 0f; GameObject cachedRowPrefab; /// /// 行の Prefab. /// /// /// では, /// を行オブジェクトとして使用します. /// protected sealed override GameObject CellPrefab => cachedRowPrefab ?? (cachedRowPrefab = SetupRowTemplate()); /// /// 一行あたりの要素数. /// protected abstract int ColumnCount { get; } /// /// セルのテンプレート. /// protected abstract FancyScrollViewCell CellTemplate { get; } /// /// 行オブジェクトのテンプレート. /// protected abstract FancyGridViewRow RowTemplate { get; } /// /// アイテムの総数. /// public int DataCount { get; private set; } /// protected override void Initialize() { base.Initialize(); Debug.Assert(RowTemplate != null); Debug.Assert(CellTemplate != null); Debug.Assert(ColumnCount > 0); Context.CellTemplate = CellTemplate.gameObject; Context.ScrollDirection = Scroller.ScrollDirection; Context.GetColumnCount = () => ColumnCount; Context.GetColumnSpacing = () => columnSpacing; } /// /// 行オブジェクトのセットアップを行います. /// /// 行を構成する GameObject. protected virtual GameObject SetupRowTemplate() { var cell = CellTemplate.GetComponent(); var row = RowTemplate.GetComponent(); row.sizeDelta = Scroller.ScrollDirection == ScrollDirection.Horizontal ? new Vector2(cell.rect.width, row.sizeDelta.y) : new Vector2(row.sizeDelta.x, cell.rect.height); return row.gameObject; } /// /// 渡されたアイテム一覧に基づいて表示内容を更新します. /// /// アイテム一覧. public virtual void UpdateContents(IList items) { DataCount = items.Count; var rows = items .Select((item, index) => (item, index)) .GroupBy( x => x.index / ColumnCount, x => x.item) .Select(group => group.ToArray()) .ToArray(); UpdateContents(rows); } /// /// 指定したアイテムの位置まで移動します. /// /// アイテムのインデックス. /// 移動にかける秒数. /// . /// 移動が完了した際に呼び出されるコールバック. public override void ScrollTo(int itemIndex, float duration, Alignment alignment = Alignment.Center, Action onComplete = null) { var rowIndex = itemIndex / Context.GetColumnCount(); base.ScrollTo(rowIndex, duration, alignment, onComplete); } /// /// 指定したアイテムの位置まで移動します. /// /// アイテムのインデックス. /// 移動にかける秒数. /// 移動に使用するイージング. /// . /// 移動が完了した際に呼び出されるコールバック. public override void ScrollTo(int itemIndex, float duration, Ease easing, Alignment alignment = Alignment.Center, Action onComplete = null) { var rowIndex = itemIndex / Context.GetColumnCount(); base.ScrollTo(rowIndex, duration, easing, alignment, onComplete); } /// /// 指定したアイテムの位置までジャンプします. /// /// アイテムのインデックス. /// . public virtual void JumpTo(int itemIndex, Alignment alignment = Alignment.Center) { var rowIndex = itemIndex / Context.GetColumnCount(); UpdatePosition(rowIndex, alignment); } } }