255 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			255 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | 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<int> 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<float> posList = new List<float>();//求出每页的临界角,页索引从0开始  | |||
|  |     private int currentPageIndex = -1; | |||
|  | 
 | |||
|  |     private bool stopMove = true; | |||
|  |     private float startTime; | |||
|  | 
 | |||
|  |     private float startDragHorizontal; | |||
|  | 
 | |||
|  |     protected List<GameObject> mCellList; | |||
|  |     protected List<Transform> mPageList; | |||
|  | 
 | |||
|  |     #region page scroll | |||
|  |     void Awake() | |||
|  |     { | |||
|  |         rect = transform.GetComponent<ScrollRect>(); | |||
|  |         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>(); | |||
|  |         } | |||
|  | 
 | |||
|  |         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<Transform>(); | |||
|  |         } | |||
|  | 
 | |||
|  |         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 | |||
|  | } |