/// 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 { }
}