using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; using UnityEngine.EventSystems; using System; public abstract class PageView : MonoBehaviour, IBeginDragHandler, IEndDragHandler { public Action OnPageChanged; protected Action OnScrollPage; protected Action OnReachEdge; public int CountPerPage; public float SlideSpeed = 4; //滑动速度 public float sensitivity = 0.3f; [SerializeField] PageSpot mSpotView; [SerializeField] Transform mCtnPage; [SerializeField] GameObject mTplPage; [SerializeField] GameObject mTplCell; ScrollRect rect; //滑动组件 private float targethorizontal = 0; //滑动的起始坐标 private bool isDrag = false; //是否拖拽结束 List posList = new List();//求出每页的临界角,页索引从0开始 private int currentPageIndex = -1; private bool stopMove = true; private float startTime; private float startDragHorizontal; protected List mCellList; protected List mPageList; #region page scroll void Awake() { rect = transform.GetComponent(); AwakeInit(); } void Update() { if (!isDrag && !stopMove) { startTime += Time.deltaTime; float t = startTime * SlideSpeed; rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, t); if (t >= 1) { stopMove = true; NotifyPageChange(); } } } public void PageTo(int index, bool pWithScroll = true) { if (index >= 0 && index < posList.Count) { if (currentPageIndex != index) { currentPageIndex = index; if (pWithScroll) { OnScrollPage?.Invoke(); } } if (pWithScroll) { targethorizontal = posList[currentPageIndex]; //设置当前坐标,更新函数进行插值 isDrag = false; startTime = 0; stopMove = false; } else { rect.horizontalNormalizedPosition = posList[index]; NotifyPageChange(); } } else { //Debug.LogError("页码不存在"); } } public void LastPage() { PageTo(currentPageIndex--); } public void NextPage() { PageTo(currentPageIndex++); } public void OnBeginDrag(PointerEventData eventData) { isDrag = true; startDragHorizontal = rect.horizontalNormalizedPosition; } public void OnEndDrag(PointerEventData eventData) { float posX = rect.horizontalNormalizedPosition; posX += ((posX - startDragHorizontal) * sensitivity); float tTempPosX = posX; posX = posX < 1 ? posX : 1; posX = posX > 0 ? posX : 0; int index = 0; float offset = Mathf.Abs(posList[index] - posX); for (int i = 1; i < posList.Count; i++) { float temp = Mathf.Abs(posList[i] - posX); if (temp < offset) { index = i; offset = temp; } } PageTo(index); if (tTempPosX > 1 || tTempPosX < 0) { OnReachEdge?.Invoke(); } } private void NotifyPageChange() { OnPageChanged?.Invoke(currentPageIndex); if (mSpotView != null) { mSpotView.SetPageIndex(currentPageIndex); } } #endregion #region config cell public abstract int Count { get; } public int PageCount => mPageCount; private int mPageCount; protected abstract void AwakeInit(); protected abstract void BeforeLoad(); protected abstract void ConfigCell(GameObject pCellGob, int pIndex); public void LoadData() { BeforeLoad(); mPageCount = Count / CountPerPage + ((Count % CountPerPage) > 0 ? 1 : 0); int tSplitCount = Mathf.Max(1, mPageCount); float tDelta = tSplitCount > 1 ? (1f / (tSplitCount - 1)) : 1; for (int i = 0; i < tSplitCount; i++) { posList.Add(tDelta * i); } for (int i = 0; i < Count; i++) { GameObject tCell = GetCell(i); ConfigCell(tCell, i); } HideUnused(); if (mSpotView != null) { mSpotView.Init(mPageCount); } PageTo(0, false); } private GameObject GetCell(int pCellIndex) { if (mCellList == null) { mCellList = new List(); } GameObject tCell = null; if (pCellIndex < mCellList.Count) { tCell = mCellList[pCellIndex]; } else { tCell = Instantiate(mTplCell, GetPage(pCellIndex)); tCell.transform.localScale = Vector3.one; mCellList.Add(tCell); } tCell.SetActive(true); return tCell; } private Transform GetPage(int pCellIndex) { if (mPageList == null) { mPageList = new List(); } int tPageIndex = pCellIndex / CountPerPage; Transform tPage = null; if (tPageIndex < mPageList.Count) { tPage = mPageList[tPageIndex]; } else { tPage = Instantiate(mTplPage, mCtnPage).transform; mPageList.Add(tPage); } tPage.gameObject.SetActive(true); return tPage; } private void HideUnused() { for (int i = Count; i < mCellList.Count; i++) { mCellList[i].SetActive(false); } for (int i = PageCount; i < mPageList.Count; i++) { mPageList[i].gameObject.SetActive(false); } } #endregion }