using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
//枚举类型
public enum PageScrollType {
Horizontal,
Vertical
}
public class PageScrollView : MonoBehaviour,IBeginDragHandler,IEndDragHandler
{
#region 字段
protected ScrollRect rect;
public Vector2 a;
protected int pageCount; //共有几页
private RectTransform content;
protected float[] pages;
public float moveTime = 0.3f; //滚动的时间设置为0.3秒
private float timer = 0; //用来计时
private float startMovePos; //开始移动的位置
protected int currentPage = 0; //当前页等于0
private bool isDraging = false; //判断是否在拖拽中
private bool isMoving = false; //判断是否移动
public bool IsAutoScroll; //是否开启自动滚动
public float AutoScrollTime = 2; //自动滚动的时间间隔
private float AutoScrollTimer = 0; //计时的
public PageScrollType pageScrollType = PageScrollType.Horizontal;
public float vertical;
#endregion
#region 事件
public Action<int> OnPageChange; //监听事件,晓得当前滚动到了哪一页,用于制作轮播图的小点点
#endregion
#region Unity回调函数
// Start is called before the first frame update
protected virtual void Start()
{
Init();
rect.onValueChanged.AddListener(bjkomoj);
}
private void bjkomoj(Vector2 arg0)
{
a = arg0;
}
// Update is called once per frame
protected virtual void Update()
{
ListenerMove();
ListenerAutoScroll();
vertical = rect.verticalNormalizedPosition;
}
public void OnEndDrag(PointerEventData eventData)
{
//滚动到离得最近的一页
this.ScrollToPage(CaculateMinDistancePage());
isDraging = false;
AutoScrollTimer = 0;
}
public void OnBeginDrag(PointerEventData eventData)
{
isDraging = true; //开始拖拽
}
#endregion
#region 方法
//初始化
public void Init()
{
rect = transform.GetComponent<ScrollRect>();
if (rect == null)
{
throw new System.Exception("未查询到ScrollRect!");
}
content = transform.Find("Viewport/Content").GetComponent<RectTransform>(); //初始化有多少页 ""中是它的路径
pageCount = content.childCount;
if(pageCount ==1 )
{
throw new System.Exception("只有一页,不用进行分页滚动");
}
pages = new float[pageCount];
for (int i = 0; i < pages.Length; i++)
{
switch (pageScrollType)
{
case PageScrollType.Horizontal:
pages[i] = i * (1.0f / (float)(pageCount - 1)); //第i页 要转成float类型
break;
case PageScrollType.Vertical:
pages[i] = 1 - i * (1.0f / (float)(pageCount - 1));
break;
}
}
}
//生成一个方法:监听移动
public void ListenerMove()
{
if (isMoving)
{
timer += Time.deltaTime * (1 / moveTime);
switch (pageScrollType)
{
case PageScrollType.Horizontal:
rect.horizontalNormalizedPosition = Mathf.Lerp(startMovePos, pages[currentPage], timer);
break;
case PageScrollType.Vertical:
rect.verticalNormalizedPosition = Mathf.Lerp(startMovePos, pages[currentPage], timer);
break;
}
//做一个插值运算 从开始移动的位置移动到当前页所处的位置
if (timer >= 1)
{
isMoving = false;
}
}
}
//监听自动滚动
public void ListenerAutoScroll()
{
if (isDraging) { return; }
if (IsAutoScroll)
{
AutoScrollTimer += Time.deltaTime;
if (AutoScrollTimer >= AutoScrollTime)
{
AutoScrollTimer = 0;
//滚动到下一页
currentPage++;
currentPage %= pageCount; //解决最后一页回到第一页的问题
ScrollToPage(currentPage);
}
}
}
//方法 滚动到指定页
public void ScrollToPage(int page)
{
isMoving = true;
this.currentPage = page; //当前页等于此页
timer = 0;
switch (pageScrollType)
{
case PageScrollType.Horizontal:
startMovePos = rect.horizontalNormalizedPosition;
break;
case PageScrollType.Vertical:
startMovePos = rect.verticalNormalizedPosition;
break;
}
if (OnPageChange != null)
{
OnPageChange(this.currentPage);
}
}
//结束拖拽,计算出离得最近的页
public int CaculateMinDistancePage()
{
int minPage = 0; //默认离得最近的是第0页
for (int i = 1; i < pages.Length; i++)
{
switch (pageScrollType)
{
case PageScrollType.Horizontal:
if (Mathf.Abs(pages[i] - rect.horizontalNormalizedPosition) < Mathf.Abs(pages[minPage] - rect.horizontalNormalizedPosition))
{
minPage = i;
}
break;
case PageScrollType.Vertical:
if (Mathf.Abs(pages[i] - rect.verticalNormalizedPosition) < Mathf.Abs(pages[minPage] - rect.verticalNormalizedPosition))
{
minPage = i;
}
break;
}
}
Debug.Log(rect.horizontalNormalizedPosition );
return minPage;
}
#endregion
}