com.unity.uiextensions/Scripts/Layout/FancyScrollView/GridView/FancyGridView.cs

144 lines
5.8 KiB
C#

/// 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
{
/// <summary>
/// グリッドレイアウトのスクロールビューを実装するための抽象基底クラス.
/// 無限スクロールおよびスナップには対応していません.
/// </summary>
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
/// <typeparam name="TContext"><see cref="FancyScrollView{TItemData, TContext}.Context"/> の型.</typeparam>
public abstract class FancyGridView<TItemData, TContext> : FancyScrollRect<TItemData[], TContext>
where TContext : class, IFancyScrollRectContext, IFancyGridViewContext, new()
{
/// <summary>
/// カラム同士の余白.
/// </summary>
[SerializeField] protected float columnSpacing = 0f;
GameObject cachedRowPrefab;
/// <summary>
/// 行の Prefab.
/// </summary>
/// <remarks>
/// <see cref="FancyGridView{TItemData, TContext}"/> では,
/// <see cref="FancyScrollView{TItemData, TContext}.CellPrefab"/> を行オブジェクトとして使用します.
/// </remarks>
protected sealed override GameObject CellPrefab => cachedRowPrefab ?? (cachedRowPrefab = SetupRowTemplate());
/// <summary>
/// 一行あたりの要素数.
/// </summary>
protected abstract int ColumnCount { get; }
/// <summary>
/// セルのテンプレート.
/// </summary>
protected abstract FancyScrollViewCell<TItemData, TContext> CellTemplate { get; }
/// <summary>
/// 行オブジェクトのテンプレート.
/// </summary>
protected abstract FancyGridViewRow<TItemData, TContext> RowTemplate { get; }
/// <summary>
/// アイテムの総数.
/// </summary>
public int DataCount { get; private set; }
/// <inheritdoc/>
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;
}
/// <summary>
/// 行オブジェクトのセットアップを行います.
/// </summary>
/// <returns>行を構成する <c>GameObject</c>.</returns>
protected virtual GameObject SetupRowTemplate()
{
var cell = CellTemplate.GetComponent<RectTransform>();
var row = RowTemplate.GetComponent<RectTransform>();
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;
}
/// <summary>
/// 渡されたアイテム一覧に基づいて表示内容を更新します.
/// </summary>
/// <param name="items">アイテム一覧.</param>
public virtual void UpdateContents(IList<TItemData> 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);
}
/// <summary>
/// 指定したアイテムの位置まで移動します.
/// </summary>
/// <param name="itemIndex">アイテムのインデックス.</param>
/// <param name="duration">移動にかける秒数.</param>
/// <param name="alignment"><see cref="Alignment"/>.</param>
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
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);
}
/// <summary>
/// 指定したアイテムの位置まで移動します.
/// </summary>
/// <param name="itemIndex">アイテムのインデックス.</param>
/// <param name="duration">移動にかける秒数.</param>
/// <param name="easing">移動に使用するイージング.</param>
/// <param name="alignment"><see cref="Alignment"/>.</param>
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
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);
}
/// <summary>
/// 指定したアイテムの位置までジャンプします.
/// </summary>
/// <param name="itemIndex">アイテムのインデックス.</param>
/// <param name="alignment"><see cref="Alignment"/>.</param>
public virtual void JumpTo(int itemIndex, Alignment alignment = Alignment.Center)
{
var rowIndex = itemIndex / Context.GetColumnCount();
UpdatePosition(rowIndex, alignment);
}
}
}