/// 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, IFancyGridViewContext, new() { /// /// デフォルトのセルグループクラス. /// protected abstract class DefaultCellGroup : FancyCellGroup { } /// /// 最初にセルを配置する軸方向のセル同士の余白. /// [SerializeField] protected float startAxisSpacing = 0f; /// /// 最初にセルを配置する軸方向のセル数. /// [SerializeField] protected int startAxisCellCount = 4; /// /// セルのサイズ. /// [SerializeField] protected Vector2 cellSize = new Vector2(100f, 100f); /// /// セルのグループ Prefab. /// /// /// では, /// を最初にセルを配置する軸方向のセルコンテナとして使用します. /// protected sealed override GameObject CellPrefab => cellGroupTemplate; /// protected override float CellSize => Scroller.ScrollDirection == ScrollDirection.Horizontal ? cellSize.x : cellSize.y; /// /// アイテムの総数. /// public int DataCount { get; private set; } GameObject cellGroupTemplate; /// protected override void Initialize() { base.Initialize(); Debug.Assert(startAxisCellCount > 0); Context.ScrollDirection = Scroller.ScrollDirection; Context.GetGroupCount = () => startAxisCellCount; Context.GetStartAxisSpacing = () => startAxisSpacing; Context.GetCellSize = () => Scroller.ScrollDirection == ScrollDirection.Horizontal ? cellSize.y : cellSize.x; SetupCellTemplate(); } /// /// 最初にセルが生成される直前に呼び出されます. /// メソッドを使用してセルテンプレートのセットアップを行ってください. /// /// /// /// { /// class CellGroup : DefaultCellGroup { } /// /// [SerializeField] Cell cellPrefab = default; /// /// protected override void SetupCellTemplate() => Setup(cellPrefab); /// } /// ]]> /// protected abstract void SetupCellTemplate(); /// /// セルテンプレートのセットアップを行います. /// /// セルのテンプレート. /// セルグループの型. protected virtual void Setup(FancyCell cellTemplate) where TGroup : FancyCell { Context.CellTemplate = cellTemplate.gameObject; cellGroupTemplate = new GameObject("Group").AddComponent().gameObject; cellGroupTemplate.transform.SetParent(cellContainer, false); cellGroupTemplate.SetActive(false); } /// /// 渡されたアイテム一覧に基づいて表示内容を更新します. /// /// アイテム一覧. public virtual void UpdateContents(IList items) { DataCount = items.Count; var itemGroups = items .Select((item, index) => (item, index)) .GroupBy( x => x.index / startAxisCellCount, x => x.item) .Select(group => group.ToArray()) .ToArray(); UpdateContents(itemGroups); } /// /// 指定したアイテムの位置までジャンプします. /// /// アイテムのインデックス. /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾). protected override void JumpTo(int itemIndex, float alignment = 0.5f) { var groupIndex = itemIndex / startAxisCellCount; base.JumpTo(groupIndex, alignment); } /// /// 指定したアイテムの位置まで移動します. /// /// アイテムのインデックス. /// 移動にかける秒数. /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾). /// 移動が完了した際に呼び出されるコールバック. protected override void ScrollTo(int itemIndex, float duration, float alignment = 0.5f, Action onComplete = null) { var groupIndex = itemIndex / startAxisCellCount; base.ScrollTo(groupIndex, duration, alignment, onComplete); } /// /// 指定したアイテムの位置まで移動します. /// /// アイテムのインデックス. /// 移動にかける秒数. /// 移動に使用するイージング. /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾). /// 移動が完了した際に呼び出されるコールバック. protected override void ScrollTo(int itemIndex, float duration, Ease easing, float alignment = 0.5f, Action onComplete = null) { var groupIndex = itemIndex / startAxisCellCount; base.ScrollTo(groupIndex, duration, easing, alignment, onComplete); } } /// /// グリッドレイアウトのスクロールビューを実装するための抽象基底クラス. /// 無限スクロールおよびスナップには対応していません. /// /// アイテムのデータ型. /// public abstract class FancyGridView : FancyGridView { } }