Unity uGUI スクロールビューをスナップさせる

  • 26
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

Unity - uGUI スクロールビューを分割毎にスナップする - Qiita - http://qiita.com/imatomi/items/61db31536a9f08a67440

の改良版。

元ページにあるコードの位置取得のための計算式の意味はパッと見よくわからないし、forループを使っているのも意図がわからないし、最終的に必要であろうデータのインデックスも取れないので改良した。

外側からインデックスを変更してforcePositionUpdateフラグを用いればこのコードの外側から位置を変更可能である。

また、元ページにあるように、Editorスクリプトを追加する必要がある。それに関しては元ページを参照して各自実装してほしい。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class ScrollSnapSelector : ScrollRect
{
    public int hIndex;
    public int vIndex;

    public int horizontalPages = 3;
    public int verticalPages = 3;
    public float smooth = 10f;

    Vector2 targetPosition;
    float hPerPage;
    float vPerPage;
    bool dragging;

    public bool forcePositionUpdate = false;

    void Awake()
    {
        hPerPage = 1.0f / (float)(horizontalPages - 1);
        vPerPage = 1.0f / (float)(verticalPages - 1);
    }

    void Start()
    {
        targetPosition = GetSnapPosition();
    }

    void Update()
    {
        if (!dragging && normalizedPosition != targetPosition)
        {
            normalizedPosition = Vector2.Lerp(normalizedPosition, targetPosition, smooth * Time.deltaTime);
            if (Vector2.Distance(normalizedPosition, targetPosition) < 0.009f)
            {
                normalizedPosition = targetPosition;
            }
        }
        if (forcePositionUpdate)
        {
            forcePositionUpdate = false;
            targetPosition = GetSnapPosition();
        }
    }

    public override void OnBeginDrag(PointerEventData eventData)
    {
        base.OnBeginDrag(eventData);
        dragging = true;
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);
        UpdateIndex();
        targetPosition = GetSnapPosition();
        dragging = false;
    }

    void UpdateIndex()
    {
        int xPage = -1;
        int yPage = -1;
        if (horizontal && horizontalPages > 0)
        {
            xPage = Mathf.RoundToInt(normalizedPosition.x / hPerPage);
            xPage = Mathf.Clamp(xPage, 0, horizontalPages - 1);
            hIndex = xPage;
        }

        if (vertical && verticalPages > 0)
        {
            yPage = Mathf.RoundToInt(normalizedPosition.y / vPerPage);
            yPage = Mathf.Clamp(yPage, 0, verticalPages - 1);
            vIndex = yPage;
        }
    }

    Vector2 GetSnapPosition()
    {
        return new Vector2(horizontal && horizontalPages > 0 ? hIndex * hPerPage : normalizedPosition.x, vertical && verticalPages > 0 ? vIndex * vPerPage : normalizedPosition.y);
    }
}