unity的ugui-7.scroll view分页滚动
Posted mr.chenyuelin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity的ugui-7.scroll view分页滚动相关的知识,希望对你有一定的参考价值。
用scroll view做个滑动页面
我们新建scroll view
Horizontal —> 水平滑动
Vertical —> 竖直滑动,取消勾选后不能滑动同时隐藏滑动条
Inertia — > 惯性 ,使用时如果被勾选,当你滑动结束后仍会产生一定的移动
操作:
在scroll view面板取消勾选 Vertical,只让它你水平滑动即可
在scroll view->viewport的content添加两个组件
grid layout group:可以调节content子物体的大小及排列分布
content size fitter:使子物体适配这个网格大小
padding:调节与边缘的距离
ceil size:每个网格大小,因为我要做的是滑动界面,直接设为父物体大小即可
spacing:每个网格的间距
start corner:upper left就是左上角开始排,start axis为horizontal就是水平排列,详情点这里
constraint:
flexible:不限制行和列的数量
flexed Row count: 限制行数
flexed column count: 限制列数
然后在content下新建两个image,将瞄点设靠左排列
效果:
自动轮播(分页滚动)
以水平滚动为例,你可以在content下添加4个item,将grid layout group限制为1行,防止页面竖直排列
scroll rect组件下的rect.horizontalNormalizedPosition可以显示水平滑动条的进度,0-1
而rect.verticalNormalizedPosition显示垂直滑动条的进度,是从1-0,算刻度时用1-
那么我们如何用数组存刻度呢?以4个页面的为例,当前第j个页面,在数组中下标为i,结果为i*(1/(n-1));其中i为下标,n为页面个数,(n-1)要转为float
手动分页滚动
就是滚动的页面,谁显示的部分多,就显示哪个页面
那么如何计算当前滑动的距离离哪个页面近呢?
做法:只需要将当前页面刻度减去滚动进度的绝对值与前者比较,记录最短距离的下标
这里会用到IEndDragHandler实现拖拽功能的接口
1.导入using UnityEngine.EventSystems;
2.并实现接口的public void OnEndDrag(PointerEventData eventData){}方法,此方法可检测鼠标拖拽的结束
全部代码:(可运行)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
public enum PageScrollType
{
Horizontal,
Vertical,
}
public class PageScrollView : MonoBehaviour,IBeginDragHandler,IEndDragHandler
{
protected ScrollRect rect;
protected int pageCount;//页面item个数
private RectTransform content;
protected float[] pages;//存滚动条进度
public float moveTime = 0.3f;
private float timer = 0;
private float startMovePos;//开始位置
protected int currentPage = 0;//当前页
//是否在移动
private bool isMoving = false;
//是否开启自动滚动
public bool IsAutoScroll;
//是否正在拖拽
private bool isDraging = false;
public float AutoScrollTime = 2;
private float AutoScrollTimer = 0;
public PageScrollType pageScrollType = PageScrollType.Horizontal;
public Action<int> onPageChange;
// 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();
}
public void Init()
{
rect = transform.GetComponent<ScrollRect>();
if (rect == null)
{
throw new System.Exception("未查询到scrollRect");
}
content = transform.Find("Viewport/Content").GetComponent<RectTransform>();
if (pageCount == 1) return;
pageCount = content.childCount;
pages = new float[pageCount];
//设好每个页面的刻度
for (int i = 0; i < pages.Length; i++)
{
switch (pageScrollType)
{
case PageScrollType.Horizontal:
pages[i] = i * (1 / (float)(pageCount - 1));
break;
case PageScrollType.Vertical:
pages[i] = 1 - i * (1 / (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;
default:
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;
ScrollPage(currentPage);
}
}
}
//计算//计算出离得最近的一页
public int CaculateMinDistancePage()
{
int minPage = 0;
//计算出离得最近的一页
for (int i = 1; i < pages.Length; i++)
{
float curPage = 0;
switch (pageScrollType)
{
case PageScrollType.Horizontal:
curPage = rect.horizontalNormalizedPosition;
break;
case PageScrollType.Vertical:
curPage = rect.verticalNormalizedPosition;
break;
}
if (Mathf.Abs(pages[i] - curPage) < Mathf.Abs(pages[minPage] - curPage))
{
minPage = i;
}
}
return minPage;
}
//滚到哪一页
public void ScrollPage(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;
}
onPageChange?.Invoke(this.currentPage);
}
//结束拖拽滑动
public void OnEndDrag(PointerEventData eventData)
{
this.ScrollPage(CaculateMinDistancePage());
isDraging = false;
AutoScrollTimer = 0
; }
//开始拖拽滑动
public void OnBeginDrag(PointerEventData eventData)
{
isDraging = true;
}
}
附加带scale属性和rotation属性的分页滚动
ScalePageScrollVIew.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScalePageScrollVIew : PageScrollView
{
protected GameObject[] items;
public float currentScale = 1f;
public float otherScale = 0.6f;
public int prePage;
public int nextPage;
protected override void Start()
{
base.Start();
items = new GameObject[pageCount];
for(int i=0;i<pageCount;i++)
{
items[i] = transform.Find("Viewport/Content").GetChild(i).gameObject;
}
}
protected override void Update()
{
base.Update();
ListenerScale();
}
public void ListenerScale()
{
//找上一页
for(int i=0;i<pages.Length;i++)
{
if(pages[i]<=rect.horizontalNormalizedPosition)
{
prePage = i;
}
}
//下一页
for (int i = 0; i < pages.Length; i++)
{
if (pages[i] > rect.horizontalNormalizedPosition)
{
nextPage = i;
break;
}
}
if (nextPage == prePage) return;
//移动幅度占页面距离的比例
float percent = (rect.horizontalNormalizedPosition - pages[prePage]) / (pages[nextPage] - pages[prePage]);
//移动幅度越大,后面页面变大,移动幅度越小,前面页面变小
items[prePage].transform.localScale = Vector3.Lerp(Vector3.one * currentScale, Vector3.one * otherScale, percent);
items[nextPage].transform.localScale = Vector3.Lerp(Vector3.one * currentScale, Vector3.one * otherScale, 1 - percent);
for (int i = 0; i < items.Length; i++)
{
//除了中间,其它都为0.6scale
if(i!=prePage&&i!=nextPage)
items[i].transform.localScale = Vector3.one * otherScale;
}
}
}
Quaternion.Euler(vector3 angle):表示物体旋转的角度
RotationPageScrollView.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationPageScrollView : ScalePageScrollVIew
{
public float rotation;
protected override void Start()
{
base.Start();
}
protected override void Update()
{
base.Update();
ScalePageScroll();
}
public void ScalePageScroll()
{
if (nextPage == prePage) return;
//移动幅度占页面距离的比例
float percent = (rect.horizontalNormalizedPosition - pages[prePage]) / (pages[nextPage] - pages[prePage]);
//移动幅度越大,后面页面变大,移动幅度越小,前面页面变小
items[prePage].transform.localRotation = Quaternion.Euler( -Vector3.Lerp(Vector3.zero, new Vector3(0,rotation,0), percent));
items[nextPage].transform.localRotation = Quaternion.Euler(-Vector3.Lerp(Vector3.zero, new Vector3(0, rotation, 0), 1 - percent));
for (int i = 0; i < items.Length; i++)
{
//除了中间,其它都为0.6scale
if (i != prePage && i != nextPage)
{
if(i>currentPage)
{
items[i].transform.localRotation = Quaternion.Euler(new Vector3(0, rotation, 0));
}
else if(i<currentPage)
{
items[i].transform.localRotation = Quaternion.Euler(new Vector3(0, -rotation, 0));
}
else
{
items[i].transform.localRotation = Quaternion.Euler(new Vector3(0, 0, 0));
}
}
}
}
}
以上是关于unity的ugui-7.scroll view分页滚动的主要内容,如果未能解决你的问题,请参考以下文章
分享Unity的Profiler分析和解决GC.MarkDependencies
Appcenter Android Build for React-Native with Unity