このページは
uGUIのScroll Viewをはじめてみる
uGUIのScroll ViewでGrid
を見ておくとよりわかりやすいかもです。
Unity5.3.1fで検証しました。
ページスクロールというのが、何かというとスマートフォンのHomeページをイメージするとわかりやすいでしょう。
例えばこんな感じで、薄い枠が実際に画面で、白いページが1ページ目、赤いページが2ページ目。
少し左にスワイプするとこんな感じ。それでここでスワイプをやめると...。
こんな感じでスクロールが自動的に行われ、赤いページに吸着するようなイメージ。
中途半端なスクロール位置がないものかな?
#実装
##初期配置
メニューバーの「GameOjbect」→「UI」→「Scroll View」を選択。
Scrollbarはいらないと思うので削除しておく。
Inspectorはこんな感じ。
- widthとHegithを500に調整
- 横スクロール想定なのでHrizontalのチェックのみON
##Viewportの設定
わかりやすくするためMaskを外しておきます。
##Contentの設定
Anchorsを「stretch x stretch」
Pivotはド真ん中
Content Size Fitterのアタッチ(まだ値をいじらないでください)
Grid Layout Groupの「Padding」「Cell Size」をページがみやすいように設定
Constraintを「Fixed Row Count」
Constraint Countを「1」
子にImageを3つ入れてみます
こんな感じ。
灰色の背景があるところがGame画面で写るページです。MaskをONにすればよりわかりやすくなります。
Imageに色をつけてわかりやすくしています。
それで先ほど設定していなかったContent Size Fitterの「Horizontal Fit」-「Preferred Size」にします。
そうすると赤のImageが真ん中の初期表示となります。
別にこれでもいいんですが、左のImageからにしたかったので
Content Size Fitterの「Horizontal Fit」-「Unconstained」に戻して、Left, Rightを0に戻したあと
Anchorsを「stretch x left」
Pivotは左真ん中
再度、Content Size Fitterの「Horizontal Fit」-「Preferred Size」
にします。下図のようになります。
こんな感じ。
ここまでで普通のScroll Viewが完成
##Scroll Rectの改造
ScrollRectを継承して新しいScriptを作ってみます。
Scroll ViewにアッタチされているScrollRectを下記スクリプトに置き換えます。
設定が元に戻ってしまうので下図のように再設定します。
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;
}
}
#その他(工事中)
ピタッって吸着している感じなので、アニメーションなどで流れるように止まってほしいので、また後ほど調査してみます。