107 lines
3.6 KiB
C#
107 lines
3.6 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
[Serializable]
|
|
public sealed class PageChangedEvent : UnityEvent<int> {}
|
|
|
|
public class PageScrollRect : ScrollRect, IPointerDownHandler {
|
|
|
|
[SerializeField]
|
|
private float duration = 0.2f;
|
|
[SerializeField]
|
|
private Button prevButton = default;
|
|
[SerializeField]
|
|
private Button nextButton = default;
|
|
[SerializeField]
|
|
private PageChangedEvent onPageChanged = default;
|
|
public PageChangedEvent OnPageChanged {
|
|
get{ return onPageChanged; }
|
|
}
|
|
|
|
private float pageWidth;
|
|
private int prevPageIndex = 0;
|
|
private int prevPageIndexLate = 0;
|
|
private Coroutine coroutine;
|
|
|
|
protected override void Awake(){
|
|
base.Awake();
|
|
|
|
var grid = content.GetComponent<GridLayoutGroup>();
|
|
pageWidth = grid.cellSize.x + grid.spacing.x;
|
|
|
|
if(prevButton){
|
|
prevButton.gameObject.SetActive(prevPageIndex > 0);
|
|
prevButton.onClick.AddListener(() => ChangePage(prevPageIndexLate - 1));
|
|
}
|
|
if(nextButton){
|
|
nextButton.onClick.AddListener(() => ChangePage(prevPageIndexLate + 1));
|
|
}
|
|
}
|
|
|
|
public override void OnBeginDrag(PointerEventData eventData){
|
|
base.OnBeginDrag(eventData);
|
|
}
|
|
|
|
public override void OnEndDrag(PointerEventData eventData){
|
|
base.OnEndDrag(eventData);
|
|
|
|
// 慣性を停止
|
|
StopMovement();
|
|
|
|
var pageIndex = -Mathf.RoundToInt(content.anchoredPosition.x / pageWidth);
|
|
// ページが変わっていない且つ素早くドラッグした場合
|
|
if(pageIndex == prevPageIndex && Mathf.Abs(eventData.delta.x) >= 5){
|
|
pageIndex -= (int)Mathf.Sign(eventData.delta.x);
|
|
}
|
|
ChangePage(pageIndex);
|
|
}
|
|
private void ChangePage(int pageIndex){
|
|
var maxPage = content.childCount - 1;
|
|
pageIndex = Mathf.Clamp(pageIndex, 0, maxPage);
|
|
var destX = -pageIndex * pageWidth;
|
|
if(content.anchoredPosition.x != destX){
|
|
this.SafeStopCoroutine(coroutine);
|
|
var from = content.anchoredPosition.x;
|
|
coroutine = this.CallLerpRealtime(duration * Mathf.Abs(from - destX) / pageWidth, t => {
|
|
content.anchoredPosition = content.anchoredPosition.SetX(Mathf.Lerp(from, destX, t * t));
|
|
}, () => {
|
|
prevPageIndexLate = pageIndex;
|
|
if(prevButton){
|
|
prevButton.gameObject.SetActive(pageIndex > 0);
|
|
}
|
|
if(nextButton){
|
|
nextButton.gameObject.SetActive(pageIndex < maxPage);
|
|
}
|
|
onPageChanged.Invoke(pageIndex);
|
|
});
|
|
}
|
|
|
|
prevPageIndex = pageIndex;
|
|
}
|
|
public void ImmediateChangePage(int pageIndex){
|
|
var maxPage = content.childCount - 1;
|
|
pageIndex = Mathf.Clamp(pageIndex, 0, maxPage);
|
|
var destX = -pageIndex * pageWidth;
|
|
if(content.anchoredPosition.x != destX){
|
|
this.SafeStopCoroutine(coroutine);
|
|
content.anchoredPosition = content.anchoredPosition.SetX(destX);
|
|
}
|
|
|
|
if(prevButton){
|
|
prevButton.gameObject.SetActive(pageIndex > 0);
|
|
}
|
|
if(nextButton){
|
|
nextButton.gameObject.SetActive(pageIndex < maxPage);
|
|
}
|
|
|
|
prevPageIndex = pageIndex;
|
|
prevPageIndexLate = pageIndex;
|
|
}
|
|
|
|
public void OnPointerDown(PointerEventData eventData){
|
|
this.SafeStopCoroutine(coroutine);
|
|
}
|
|
} |