LoginSignup
57
50

More than 5 years have passed since last update.

uGUIのScroll Viewでページスクロール

Posted at

このページは
uGUIのScroll Viewをはじめてみる
uGUIのScroll ViewでGrid
を見ておくとよりわかりやすいかもです。
Unity5.3.1fで検証しました。

ページスクロールというのが、何かというとスマートフォンのHomeページをイメージするとわかりやすいでしょう。

例えばこんな感じで、薄い枠が実際に画面で、白いページが1ページ目、赤いページが2ページ目。
PageScroll.PNG

少し左にスワイプするとこんな感じ。それでここでスワイプをやめると...。
PageScroll1.PNG

こんな感じでスクロールが自動的に行われ、赤いページに吸着するようなイメージ。
中途半端なスクロール位置がないものかな?
PageScroll2.PNG

実装

初期配置

メニューバーの「GameOjbect」→「UI」→「Scroll View」を選択。
Scrollbarはいらないと思うので削除しておく。
PageScroll3.PNG

Inspectorはこんな感じ。

  • widthとHegithを500に調整
  • 横スクロール想定なのでHrizontalのチェックのみON

PageScroll4.PNG

Viewportの設定

わかりやすくするためMaskを外しておきます。
PageScroll5.PNG

Contentの設定

Anchorsを「stretch x stretch」
Pivotはド真ん中
Content Size Fitterのアタッチ(まだ値をいじらないでください)
Grid Layout Groupの「Padding」「Cell Size」をページがみやすいように設定
Constraintを「Fixed Row Count」
Constraint Countを「1」
PageScroll6.PNG

子にImageを3つ入れてみます
PageScroll7.PNG
こんな感じ。
灰色の背景があるところがGame画面で写るページです。MaskをONにすればよりわかりやすくなります。
Imageに色をつけてわかりやすくしています。
PageScroll8.PNG

それで先ほど設定していなかったContent Size Fitterの「Horizontal Fit」-「Preferred Size」にします。
PageScroll9.PNG
そうすると赤のImageが真ん中の初期表示となります。
別にこれでもいいんですが、左のImageからにしたかったので
PageScroll10.PNG

Content Size Fitterの「Horizontal Fit」-「Unconstained」に戻して、Left, Rightを0に戻したあと
Anchorsを「stretch x left」
Pivotは左真ん中
再度、Content Size Fitterの「Horizontal Fit」-「Preferred Size」
にします。下図のようになります。
PageScroll11.PNG
こんな感じ。
ここまでで普通のScroll Viewが完成
PageScroll12.PNG

Scroll Rectの改造

ScrollRectを継承して新しいScriptを作ってみます。
Scroll ViewにアッタチされているScrollRectを下記スクリプトに置き換えます。
設定が元に戻ってしまうので下図のように再設定します。
PageScroll13.PNG

PageScrollRect.cs
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

// ページスクロールビュー.
public class PageScrollRect : ScrollRect
{
    // 1ページの幅.
    private float pageWidth;
    // 前回のページIndex. 最も左を0とする.
    private int prevPageIndex = 0;

    protected override void Awake()
    {
        base.Awake();

        GridLayoutGroup grid = content.GetComponent<GridLayoutGroup>();
        // 1ページの幅を取得.
        pageWidth = grid.cellSize.x + grid.spacing.x;
    }

    // ドラッグを開始したとき.
    public override void OnBeginDrag(PointerEventData eventData)
    {
        base.OnBeginDrag(eventData);
    }

    // ドラッグを終了したとき.
    public override void OnEndDrag(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);

        // ドラッグを終了したとき、スクロールをとめます.
        // スナップさせるページが決まった後も慣性が効いてしまうので.
        StopMovement();

        // スナップさせるページを決定する.
        // スナップさせるページのインデックスを決定する.
        int pageIndex = Mathf.RoundToInt(content.anchoredPosition.x / pageWidth);
        // ページが変わっていない且つ、素早くドラッグした場合.
        // ドラッグ量の具合は適宜調整してください.
        if (pageIndex == prevPageIndex && Mathf.Abs(eventData.delta.x) >= 5)
        {
            pageIndex += (int)Mathf.Sign(eventData.delta.x);
        }

        // Contentをスクロール位置を決定する.
        // 必ずページにスナップさせるような位置になるところがポイント.
        float destX = pageIndex * pageWidth;
        content.anchoredPosition = new Vector2(destX, content.anchoredPosition.y);

        // 「ページが変わっていない」の判定を行うため、前回スナップされていたページを記憶しておく.
        prevPageIndex = pageIndex;
    }
}

ページにスナップするな感じがわかるでしょうか。
PageScrollGif.gif

その他(工事中)

ピタッって吸着している感じなので、アニメーションなどで流れるように止まってほしいので、また後ほど調査してみます。

57
50
2

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
57
50