LoginSignup
2
2

More than 3 years have passed since last update.

uGUIのGridLayoutGroupがオートレイアウト対応してないので対応させるやつ書いた

Last updated at Posted at 2020-12-15

概要

GridLayoutGroupのCellSizeを自動調整します。

使い方

GridLayoutGroupと同じオブジェクトに付与してください。
もしくは、付与した際に自動でGridLayoutGroupが連鎖的に付与されます。
なお、Constraintを何に設定するかで、調整項目が違うので注意。

  • Flexible
    • CellSizeが完全に自動調整されます。事前入力値は無視します。
  • FixedColumnCount
    • CellSizeのXを自動調整します。Yは事前入力値を継承。
  • FixedRowCount
    • CellSizeのYを自動調整します。Xは事前入力値を継承。
AutoGridLayoutOverrider.cs
using UnityEngine;
using UnityEngine.UI;

namespace CustomUIParts
{
    /// <summary>
    /// UnityEngine.UI.GridLayoutGroup をAutoLayout仕様にする
    /// </summary>
    [RequireComponent(typeof(GridLayoutGroup))]
    public class AutoGridLayoutOverrider : MonoBehaviour
    {
        /// <summary>
        /// オートレイアウト対応するGridLayoutGroup
        /// </summary>
        [SerializeField] GridLayoutGroup grid = default;

        /// <summary>
        /// サイズ調整に使用するRectTransform
        /// </summary>
        RectTransform rect = default;

        #region サイズ変動要素の比較用キャッシュ
        // Grid内オブジェクトの個数
        int beforeChildCount;
        // RectTransformからのデータ
        float beforeWidth, beforeHeight;
        // GridLayoutGroupからのデータ
        Vector2 beforeCellSize;
        Vector2 beforeSpacing;
        GridLayoutGroup.Axis beforeAxis;
        GridLayoutGroup.Constraint beforeConstraint;
        int beforeConstraingCount;
        #endregion


        /// <summary>
        /// InspectorでのReset動作定義
        /// </summary>
        void Reset()
        {
            grid = GetComponent<GridLayoutGroup>();
        }

        /// <summary>
        /// Unityライフサイクル関数
        /// </summary>
        void Awake()
        {
            // サイズ調整の基準となるRectTransformを取得
            rect = GetComponent<RectTransform>();
            while (rect.rect.width == 0 && rect.rect.height == 0)
            {
                // Streach前提でサイズが取得できないときは、親・祖先オブジェクトに遡って取得しにいく
                rect = rect.transform.parent.GetComponent<RectTransform>();
            }
        }

        /// <summary>
        /// Unityライフサイクル関数
        /// </summary>
        void Update()
        {
            ResetLayoutSize();
        }

        /// <summary>
        /// レイアウトサイズ変更
        /// </summary>
        void ResetLayoutSize()
        {
            // レイアウト状態に変更が無ければスキップ
            bool skipFlag =
                beforeWidth == rect.rect.width &&
                beforeHeight == rect.rect.height &&
                beforeChildCount == grid.transform.childCount &&
                beforeSpacing.x == grid.spacing.x &&
                beforeSpacing.y == grid.spacing.y &&
                beforeAxis == grid.startAxis &&
                beforeConstraint == grid.constraint;

            // 幅固定指定の場合は、前回サイズから変更がないか追加チェック
            switch (grid.constraint) {
                case GridLayoutGroup.Constraint.FixedColumnCount:
                    skipFlag &= beforeCellSize.y == grid.cellSize.y;
                    skipFlag &= beforeConstraingCount == grid.constraintCount;
                    break;
                case GridLayoutGroup.Constraint.FixedRowCount:
                    skipFlag &= beforeCellSize.x == grid.cellSize.x;
                    skipFlag &= beforeConstraingCount == grid.constraintCount;
                    break;
            }

            if (skipFlag)
            {
                return;
            }

            // 何かしら状況が変わったのでレイアウト設定を変える

            float x = grid.cellSize.x;
            float y = grid.cellSize.y;

            switch (grid.constraint)
            {
                // x,y:ともに可変(領域全体を埋める)
                case GridLayoutGroup.Constraint.Flexible:
                    int childCount = grid.transform.childCount;
                    int i = 0;
                    while (Mathf.Pow(++i, 2) < childCount) { }

                    int tateNum, yokoNum;
                    if (Mathf.Pow(i, 2) == childCount)
                    {
                        tateNum = yokoNum = i;
                    }
                    else if (grid.startAxis == GridLayoutGroup.Axis.Horizontal)
                    {
                        yokoNum = i;
                        tateNum = childCount / i + (childCount % i != 0 ? 1 : 0);
                    }
                    else
                    {
                        // 縦方向優先に並べる動作は挙動が特殊
                        yokoNum = i;
                        if(childCount <= i * (i-1))
                        {
                            tateNum = childCount / i + (childCount % i != 0 ? 1 : 0);
                        }
                        else
                        {
                            tateNum = i;
                        }
                    }

                    x = (rect.rect.width - grid.spacing.x * (tateNum - 1)) / tateNum;
                    y = (rect.rect.height - grid.spacing.y * (yokoNum - 1)) / yokoNum;
                    break;

                // width のみ可変
                case GridLayoutGroup.Constraint.FixedColumnCount:
                    x = (rect.rect.width - grid.spacing.x * (grid.constraintCount - 1)) / grid.constraintCount;
                    break;

                // height のみ可変
                case GridLayoutGroup.Constraint.FixedRowCount:
                    y = (rect.rect.height - grid.spacing.y * (grid.constraintCount - 1)) / grid.constraintCount;
                    break;
            }
            beforeCellSize = grid.cellSize = new Vector2(x, y);

            // 更新処理スキップ判定用に諸々キャッシュ
            beforeChildCount = grid.transform.childCount;

            beforeWidth = rect.rect.width;
            beforeHeight = rect.rect.height;

            beforeSpacing = grid.spacing;
            beforeAxis = grid.startAxis;
            beforeConstraint = grid.constraint;
            beforeConstraingCount = grid.constraintCount;
        }
    }
}

変更ログ

2020/12/16
最初はUpdateにプラットフォーム依存処理を入れていたが、
別プラットフォームでビルドしたら反映されなかったので修正。

2
2
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
2
2