此篇主要内容:1、代码逻辑(流程图呈现) 2、具体实现语句 3、脚本(脚本为完善后的)
一、分页逻辑图
2、语句分析与记录
3、脚本
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; 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(); } // 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; } } return minPage; } #endregion }