(学习网上公开教程的笔记和小思考)
1.创建一个空gameobject,可以命名为:scroll rect
(手动设置width和height作为列表显示滚动的区域)
2.把一长串的grid 放到里面
3.在 scroll rect 上面添加 scroll rect 组件,和image组件,两者必须齐全,缺一不可(因为 image有射线检测组件,才可以在运行时候检测到点击拖动等事件)
组件里面的content即为可滚动列表区域,把grid放入
滚动是按照超出范围进行控制的,因此会在scroll rect 框定范围左右进行移动
在scroll rect上可以取消勾选vertical或者horizontal来控制滑动方向
4.继续在scroll rect组件上 添加mask来控制显示范围,超出区域的不显示,mask!!!!!很重要,mask也能控制子物体的显示程度,跟image相关,所以上面image透明度不能设置为0,否则会看不见子物体滚动内容。
mask作用:超出范围部分不显示,遮罩作用
5.想要切换页面,需要监测滚动和判断离哪一页更近
(1)使用scroll rect监听滚动值,滚动到末尾的时候会传入1(传的是二维向量,左右是X值)
拖拽结束之后离哪一页更近,到哪一页
(2)滚动到指定页代码
首先测试返回值
(超出范围监听到的是1.1,正常到结束末尾,坐标是1)
(3)实现拖拽接口
只要继承这两个接口就会监听 开始拖拽事件 和 结束拖拽事件。
不需要使用on value change 去指定,会自动触发, 但必须和scroll rect作用的游戏物体,处于同一界面
(4)定义一个scroll
属性:
normalize Position 可以把位置设置为0-1 范围区间,拿到scroll的值,进行量化操作,例如获取值和设置值。
(5)想要进行页面跳转首先要进行页面位置的判定
把四个页面进,0-1的平均分,拿到每个页面中间数值,例如三个页面是0,0.5f ,1
通过scroll拿到当前页面的位置,判断离哪一个页面更近,然后设置成那个页面的位置,即为跳转
(6)通过for循环不断判断,当前位置和不同页面之间的偏移,选择偏移量最小的就是距离最近的页面。
(7)设置了最近的页面,直接跳转比较突兀,可以物理增加一个缓动效果
通过慢慢增加targetposition来实现,ismoving 在updated里进行控制,动画判断
把最后赋值给的改成targetPosition
然后进行mini动画
动画方法就一行,但是做完之后要进行判断,是否到目标页面,到了就停止动画并且把目标位置给他。
(8)通过按钮选择进行控制页面切换
toggle被选中都会触发on value change, 改变的是bool值,触发是true,不触发是false
逻辑比较简单,但是要在每个toggle进行onvaluechange传入设置。
可以封装成下面的代码:
public void MoveToPage(int pageIndex, bool isOn)
{
if (isOn && pageIndex >= 0 && pageIndex < pagePosition.Length)
{
isMoving = true;
targetPosition = pagePosition[pageIndex];
}
}
最后,案例的总体代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class LevelScrollRect : MonoBehaviour,IBeginDragHandler,IEndDragHandler
{
private ScrollRect scroll;
private float[] pagePosition = new float[4] { 0,0.3333f,0.6666f, 1 };
public Toggle[] toggleArray;
private float targetPosition = 0;
private bool isMoving = false;
private float speed = 7;
// Start is called before the first frame update
void Start()
{
scroll = GetComponent<ScrollRect>();
}
// Update is called once per frame
void Update()
{
if (isMoving)
{
scroll.horizontalNormalizedPosition =
Mathf.Lerp(scroll.horizontalNormalizedPosition, targetPosition, Time.deltaTime*speed);
if( Mathf.Abs(scroll.horizontalNormalizedPosition - targetPosition)<0.001f)
{
isMoving = false;
scroll.horizontalNormalizedPosition = targetPosition;
}
}
}
public void OnBeginDrag(PointerEventData eventData)
{
}
public void OnEndDrag(PointerEventData eventData)
{
float currentPosition = scroll.horizontalNormalizedPosition;
int index = 0;
float offset = currentPosition - pagePosition[0];
for(int i=1;i<4;i++)
{
if( Mathf.Abs(currentPosition-pagePosition[i]) < offset)
{
index = i;
offset = Mathf.Abs(currentPosition - pagePosition[i]);
}
}
targetPosition=pagePosition[index];
isMoving = true;
toggleArray[index].isOn = true;
}
public void MoveToPage1(bool isOn)
{
if (isOn)
{
isMoving = true;
targetPosition = pagePosition[0];
}
}
public void MoveToPage2(bool isOn)
{
if (isOn)
{
isMoving = true;
targetPosition = pagePosition[1];
}
}
public void MoveToPage3(bool isOn)
{
if (isOn)
{
isMoving = true;
targetPosition = pagePosition[2];
}
}
public void MoveToPage4(bool isOn)
{
if (isOn)
{
isMoving = true;
targetPosition = pagePosition[3];
}
}
}
我在具体项目中借鉴使用的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class LevelScrollRect : MonoBehaviour, IBeginDragHandler, IEndDragHandler
{
private ScrollRect scroll;
private float[] pagePosition = new float[3] { 0, 0.5f, 1 };
public Toggle[] toggleArray;
private float targetPosition = 0;
private bool isMoving = false;
private float speed = 7;
void Start()
{
scroll = GetComponent<ScrollRect>();
targetPosition = scroll.horizontalNormalizedPosition;
for (int i = 0; i < toggleArray.Length; i++)
{
int index = i;
toggleArray[i].onValueChanged.AddListener((isOn) => MoveToPage(index, isOn));
}
}
void Update()
{
moving();
}
public void OnBeginDrag(PointerEventData eventData)
{
}
public void OnEndDrag(PointerEventData eventData)
{
ChangePage();
}
public void moving()
{
if (isMoving)
{
scroll.horizontalNormalizedPosition =
Mathf.Lerp(scroll.horizontalNormalizedPosition, targetPosition, Time.deltaTime * speed);
if (Mathf.Abs(scroll.horizontalNormalizedPosition - targetPosition) < 0.001f)
{
isMoving = false;
scroll.horizontalNormalizedPosition = targetPosition;
}
}
}
public void ChangePage()
{
float currentPosition = scroll.horizontalNormalizedPosition;
int index = 0;
float minOffset = Mathf.Abs(currentPosition - pagePosition[0]);
for (int i = 1; i < pagePosition.Length; i++)
{
float offset = Mathf.Abs(currentPosition - pagePosition[i]);
if (offset < minOffset)
{
index = i;
minOffset = offset;
}
}
targetPosition = pagePosition[index];
isMoving = true;
toggleArray[index].isOn = true;
}
//toggle 为true调用下面的方法,记得面板设置一下
public void MoveToPage(int pageIndex, bool isOn)
{
if (isOn && pageIndex >= 0 && pageIndex < pagePosition.Length)
{
isMoving = true;
targetPosition = pagePosition[pageIndex];
}
}
}