Unity之滑页效果&基于ScrollRect实现
效果图
设计思路
- 基于ScrollRect的基础功能,本身在ScrollRect下的Content内容就是可以滑动的,但是它的滑动不符合预期
- 我们把滑动的效果设置为预期效果,那就需要获得开始滑动,滑动中,滑动结束的函数进行改造
- 我们在开始滑动记录位置,滑动中的幅度值,滑动结束记录位置,然后滑动结束时控制滑动效果
- 达到下一页的阈值,计算好下一页的位置,那就让页面Lerp插值到指定位置,滑动结束
场景搭建
创建一个scrollRect,替换ScrollRect脚本,使用我们自己的脚本ScrollRectBase,该脚本继承了ScrollRect,对其中一些关键方法进行了重写,并暴露一些关键事件给外界注册。
在Content下创建我们的页面,页面数量自定义,我这里创了5个页面。
创建一个导航栏,用来指示我当前所滑到的页面位置。
代码
#region 重构拖拽相关的逻辑
//ScrollRect里面就带有滑动相关的特性,拖拽时Content里面的内容就是会动的,我要做的是在拖拽结束时执行自己想要的效果,而不是它自带的效果,就是在拖拽结束时快速切换到指定的页面,而不是缓动直至慢慢停止
public override void OnBeginDrag(PointerEventData eventData)
{
if (UseDrag)
{
OnBeginDragInternal(eventData);
}
}
public void OnBeginDragInternal(PointerEventData eventData)
{
base.OnBeginDrag(eventData);
if (UsePage)
{
OnBeginDragPage(eventData);
}
}
public override void OnDrag(PointerEventData eventData)
{
if (UseDrag)
{
OnDragInternal(eventData);
}
}
public void OnDragInternal(PointerEventData eventData)
{
base.OnDrag(eventData);
if (UsePage)
{
OnDragPage(eventData);
}
if (Drag != null)
{
Drag(eventData);
}
}
public override void OnEndDrag(PointerEventData eventData)
{
if (UseDrag)
{
OnEndDragInternal(eventData);
}
}
public void OnEndDragInternal(PointerEventData eventData)
{
base.OnEndDrag(eventData);
if (UsePage)
{
OnEndDragPage(eventData);
}
}
///开始拖拽
private void OnBeginDragPage(PointerEventData eventData)
{
bDragging = true;
BeginDragPos = eventData.position.x;
}
//拖拽中
private void OnDragPage(PointerEventData eventData)
{
Debug.Log(eventData.delta);
Vector2 delta = eventData.delta;
speed = delta.x;
}
//拖拽结束
private void OnEndDragPage(PointerEventData eventData)
{
EndDragPos = eventData.position.x;
float LofR = BeginDragPos - EndDragPos;
if (Mathf.Abs(speed) > SpeedCritical || Mathf.Abs(BeginDragPos - EndDragPos) > 400f)//能够切到下一页的阈值,一个是速度达到20,一个是滑动距离大于400
{
if (LofR < 0f)
{
currentPage = GetNextPage(currentPage, true);
}
else
{
currentPage = GetNextPage(currentPage, false);
}
currentPage = Mathf.Clamp(currentPage, 0, Page_Count - 1);
}
bUpdateEnd = false;
bDragging = false;
speed = 0f;
BeginDragPos = 0;
EndDragPos = 0;
UpdateScrollEndPos();
if (EndDragItem != null)
{
EndDragItem(currentPage);
}
}
//计算停止页面的位置
private void UpdateScrollEndPos()
{
scrollendpos = currentPage * (1f / ((float)Page_Count - 1));
}
//更新页面
private void OnUpdatePage()
{
//拖拽过程中不更新页面
if (bDragging || bSendFinish)
{
return;
}
if (base.horizontal)
{
base.horizontalNormalizedPosition = Mathf.Lerp(base.horizontalNormalizedPosition, scrollendpos, 15f * Time.deltaTime);
float num = Mathf.Abs(base.horizontalNormalizedPosition - scrollendpos);
Vector2 sizeDelta = base.content.sizeDelta;
if (num * sizeDelta.x < 2f)//最后距离不多了直接到位
{
base.horizontalNormalizedPosition = scrollendpos;
bUpdateEnd = true;
}
}
if (bUpdateEnd)
{
if (mPageAniFinish != null)
{
mPageAniFinish();
}
bSendFinish = true;
}
}
private void Update()
{
if (UsePage)
{
OnUpdatePage();
}
}
工程项目
链接:https://pan.baidu.com/s/1zuNIDWQrjcWiEwBlU-yYbA
提取码:xhg8