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

このページは
[uGUIのScroll Viewをはじめてみる](http://qiita.com/okuhiiro/items/14b829778d226bc2f2ed)
[uGUIのScroll ViewでGrid](http://qiita.com/okuhiiro/items/d33a5c8940bf0843d8ff)
を見ておくとよりわかりやすいかもです。
Unity5.3.1fで検証しました。

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

例えばこんな感じで、薄い枠が実際に画面で、白いページが1ページ目、赤いページが2ページ目。
![PageScroll.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/0ee9ba43-dd36-59f5-584d-1bb842402abe.png)

少し左にスワイプするとこんな感じ。それでここでスワイプをやめると...。
![PageScroll1.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/c4e32053-d54b-9b0e-7f21-910d2ca2760d.png)

こんな感じでスクロールが自動的に行われ、赤いページに吸着するようなイメージ。
中途半端なスクロール位置がないものかな？
![PageScroll2.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/3fea7155-b580-97fd-0179-ed44d418c14d.png)

#実装
##初期配置
メニューバーの「GameOjbect」→「UI」→「Scroll View」を選択。
Scrollbarはいらないと思うので削除しておく。
![PageScroll3.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/b0e2a4ff-fbdc-e376-5a48-a199e476f6b7.png)

Inspectorはこんな感じ。

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

![PageScroll4.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/35811cc1-76cf-179c-4894-071cf0e2e92d.png)

##Viewportの設定
わかりやすくするためMaskを外しておきます。
![PageScroll5.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/89e5d6d3-dca8-d92f-9c78-f45f319220c9.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](https://qiita-image-store.s3.amazonaws.com/0/17192/aa2e30b0-63ed-9519-99d0-38e82344d5f8.png)

子にImageを3つ入れてみます
![PageScroll7.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/0a699d98-0dee-7494-93f9-d4abd19b8dd1.png)
こんな感じ。
灰色の背景があるところがGame画面で写るページです。MaskをONにすればよりわかりやすくなります。
Imageに色をつけてわかりやすくしています。
![PageScroll8.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/4b0f535b-0ff1-62a0-94ab-6ffea7371966.png)

それで先ほど設定していなかったContent Size Fitterの「Horizontal Fit」-「Preferred Size」にします。
![PageScroll9.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/cbb35082-575c-ac10-186d-1f228557c387.png)
そうすると赤のImageが真ん中の初期表示となります。
別にこれでもいいんですが、左のImageからにしたかったので
![PageScroll10.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/65508de8-67fa-f623-2e8b-2b87bbe6318f.png)

Content Size Fitterの「Horizontal Fit」-「Unconstained」に戻して、Left, Rightを0に戻したあと
Anchorsを「stretch x left」
Pivotは左真ん中
再度、Content Size Fitterの「Horizontal Fit」-「Preferred Size」
にします。下図のようになります。
![PageScroll11.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/8b1b31ec-3e90-83f9-7e03-0b45313dd6eb.png)
こんな感じ。
ここまでで**普通**のScroll Viewが完成
![PageScroll12.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/699e4123-94fb-cfb6-c6da-86a5688bd49f.png)

##Scroll Rectの改造
ScrollRectを継承して新しいScriptを作ってみます。
Scroll ViewにアッタチされているScrollRectを下記スクリプトに置き換えます。
設定が元に戻ってしまうので下図のように再設定します。
![PageScroll13.PNG](https://qiita-image-store.s3.amazonaws.com/0/17192/cf9db4b2-c0a8-4032-992c-ee4f358e3ffb.png)

```csharp: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](https://qiita-image-store.s3.amazonaws.com/0/17192/be81f8de-3b85-2d57-22d1-edb9fdf6e5e1.gif)

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