UNITY UGUI如何实现整页滑动
unity的LayoutGroup分为三种,
Horizontal Layout Group(水平布局):对象填充总个父物体,水平会填充
Vertical Layout Group(垂直布局):垂直(高度)会填充
Grid Layout Group (网格布局):以表格的形式布局,不会填充父物体
比如:垂直布局和水平布局效果
Grid Layout Group
如果单纯的时候用滑动效果可以使用Scroll Rect组件即可。但使用布局就要使用布局控件
Grid Layout Group是网格布局,先看看一个效果
其实滑动依然是用的Scroll Rect。这个就不说了。这里主要说布局。
Spacing 表示 cell之间的距离。
Cell表示格子的宽度和和高度
Start Axis 表示布局方式,有横向和纵向
Child Alignment 表示对齐方式。
注意Layout Group节点下面的所有cell节点都是不能修改Rect Transform的。因为cell可能下面会放很多图片,这样我们会用个空的gameObject来当父节点。
但你仔细看。会发现。这个不是整块滑动的。比如手机屏幕左右滑动,是滑动区域判断的。没有划过来的时候。会退回去。像这样
这里可以根据Scroll Rect组件的normalizedPosition属性来判断。这是一个Vector2坐标。是滑动中XY的值
horizontalNormalizedPosition:水平的值
verticalNormalizedPosition:垂直的值
需要在拖动结束后判断。需要继承
IBeginDragHandler,IEndDragHandler。引用命名空间:using UnityEngine.EventSystems;
using UnityEngine; using System.Collections; using UnityEngine.EventSystems; using UnityEngine.UI; public class newScroll : MonoBehaviour, IBeginDragHandler, IEndDragHandler { ScrollRect rect; //页面:0,1,2 索引从0开始 //每夜占的比列:0/2=0 1/2=0.5 2/2=1 float[] page = { 0, 0.5f, 1 }; //滑动速度 public float smooting = 4; //滑动的起始坐标 float targethorizontal = 0; //是否拖拽结束 bool isDrag = false; // Use this for initialization void Start() { rect = transform.GetComponent<ScrollRect>(); } // Update is called once per frame void Update() { //如果不判断。当在拖拽的时候要也会执行插值,所以会出现闪烁的效果 //这里只要在拖动结束的时候。在进行插值 if (!isDrag) { rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, Time.deltaTime * smooting); } } /// <summary> /// 拖动开始 /// </summary> /// <param name="eventData"></param> public void OnBeginDrag(PointerEventData eventData) { isDrag = true; } /// <summary> /// 拖拽结束 /// </summary> /// <param name="eventData"></param> public void OnEndDrag(PointerEventData eventData) { isDrag = false; // //拖动停止滑动的坐标 // Vector2 f = rect.normalizedPosition; // //水平 开始值是0 结尾值是1 [0,1] // float h = rect.horizontalNormalizedPosition; // //垂直 // float v = rect.verticalNormalizedPosition; float posX = rect.horizontalNormalizedPosition; int index = 0; //假设离第一位最近 float offset = Mathf.Abs(page[index] - posX); for (int i = 1; i < page.Length; i++) { float temp = Mathf.Abs(page[i] - posX); if (temp < offset) { index = i; //保存当前的偏移量 //如果到最后一页。反翻页。所以要保存该值,如果不保存。你试试效果就知道 offset = temp; } } /* 因为这样效果不好。没有滑动效果。比较死板。所以改为插值 */ //rect.horizontalNormalizedPosition = page[index]; targethorizontal = page[index]; } }
像这种布局。内容是动态添加的。所以内容的多少是不确定的。很多时候是用u3d自带的ContentSizeFitter。这个组件可以自动计算宽度
那么问题来了。当总数不是页数的倍数,那么horizontalNormalizedPosition是不正确的。比如:有2页。一页5条
当只有6条。是不是也是2页呢?。
所以又得必须动态计算了。
这里写了一个适用于其他场合的类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
class UIScrollItemTips : MonoBehaviour, IBeginDragHandler, IEndDragHandler
{
//页面:0,1,2 索引从0开始
//每夜占的比列:0/2=0 1/2=0.5 2/2=1
public List<float> pageArray;
//public List<float> PageArray
//{
// // get { return pageArray; }
// set { pageArray = value; }
//}
private List<Toggle> toggleArray;
public List<Toggle> ToggleArray
{
//get { return toggleArray; }
set { toggleArray = value; }
}
public int pageCount;//多少页
public int pageIndex = 0;//:当前页码
private ScrollRect rect;
//滑动速度
public float smooting;
public float Smooting
{
get { return smooting; }
set { smooting = value; }
}
private int pageSize;
/// <summary>
/// 一页显示多少条
/// </summary>
public int setPageSize
{
get { return pageSize; }
set { pageSize = value; }
}
private int sumRecord;
/// <summary>
/// 总记录数
/// </summary>
public int setSumRecord
{
get { return sumRecord; }
set { sumRecord = value; }
}
private List<GameObject> pageList = new List<GameObject>();
//滑动的起始坐标
public float targethorizontal = 0;
//是否拖拽结束
public bool isDrag = false;
public GameObject root;
private int updateInfo;
public int UpdateInfo
{
//get { return updateInof; }
set { Init(); }
}
//private static UIScrollItem instance;
//public static UIScrollItem Instance
//{
// get { return instance; }
// //set { ObjectPools.instance = value; }
//}
void Init()
{
UnInit();
//pageSize = 8;
//setSumRecord = 54;
smooting = 4;
rect = transform.GetComponent<ScrollRect>();
pageArray = new List<float>();
toggleArray = new List<Toggle>();
targethorizontal = 0;
rect.horizontalNormalizedPosition = 0;
//instance = this; //单列
pageCount = Convert.ToInt32(Math.Ceiling((double)sumRecord / pageSize)); //sumRecord为总记录数
//Debug.LogError(pageCount);
//求出每页的临界角,页索引从0开始
int num = pageCount - 1;
if (num == 0) num = 1;
for (int i = 0; i < pageCount; i++)
{
//Debug.LogError(i + "/" + num + "==" + (float)i / (float)num);
pageArray.Add((float)i / (float)num);
}
if (root != null)
{
ToggleGroup group = root.GetComponent<ToggleGroup>();
for (int i = 0; i < pageCount; i++)
{
//获取页码预设体
GameObject pageItem = U3DResources.SpawnUI("Item_New");
pageList.Add(pageItem);
pageItem.transform.SetParent(root.transform);
pageItem.transform.localScale = new Vector3(1, 1, 1);
pageItem.transform.localRotation = new Quaternion();
pageItem.transform.localPosition = Vector3.one;
Toggle toogle = pageItem.transform.Find("page").GetComponent<Toggle>();
toogle.group = group;
toggleArray.Add(toogle);
}
}
//Debug.LogError(pageSize);
//rect.horizontalNormalizedPosition = 0;
//不管怎样默认都是显示最后一页,同理,页码页码也是。已在生成页码时处理
//初始化不需要显示滑动效果。直接赋值即可
//targethorizontal = pageArray[pageArray.Count - 1];
//rect.horizontalNormalizedPosition = pageArray[pageArray.Count - 1];
foreach (var item in toggleArray)
{
item.isOn = false;
}
if (toggleArray.Count > 0)
{
//默认第一个选中
toggleArray[0].isOn = true;
}
}
void Awake()
{
}
void Start()
{
//Init();
//rect.horizontalNormalizedPosition = 0;
}
void Update()
{
//如果不判断。当在拖拽的时候要也会执行插值,所以会出现闪烁的效果
////这里只要在拖动结束的时候。在进行插值
if (!isDrag)
{
rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, Time.deltaTime * smooting);
//rect.horizontalNormalizedPosition = targethorizontal;
}
}
/// <summary>
/// 拖动开始
/// </summary>
/// <param name="eventData"></param>
public void OnBeginDrag(PointerEventData eventData)
{
isDrag = true;
}
/// <summary>
/// 拖拽结束
/// </summary>
/// <param name="eventData"></param>
public void OnEndDrag(PointerEventData eventData)
{
isDrag = false;
float posX = rect.horizontalNormalizedPosition;
int index = 0;
//假设离第一位最近
float offset = Mathf.Abs(pageArray[index] - posX);
for (int i = 1; i < pageArray.Count; i++)
{
float temp = Mathf.Abs(pageArray[i] - posX);
if (temp < offset)
{
index = i;
//保存当前的偏移量
offset = temp;
}
}
try
{
targethorizontal = pageArray[index];
//说明页码大于1 toggle有值
if (pageCount > 1 && toggleArray.Count > 0)
toggleArray[index].isOn = true;
}
catch (Exception)
{
return;
}
}
void UnInit()
{
foreach (var item in pageList)
{
U3DResources.Despawn(item);
}
}
}
itemTips.setSumRecord = nows; itemTips.setPageSize = 8; mItemGrid.GetComponent<ContentSizeFitter>().enabled = false; //总页数 int pageCount = Convert.ToInt32(Math.Ceiling((double)nows / itemTips.setPageSize)); //sumRecord为总记录数 int resultCount = nows; if (nows % itemTips.setPageSize != 0) { //求差 int poor = pageCount * itemTips.setPageSize - nows; //加上差数。凑整 resultCount = nows + poor; } else { //可以启用自动计算宽度 //mItemGrid.GetComponent<ContentSizeFitter>().enabled = true; } //Debug.LogError(nows); //Debug.LogError(resultCount); GridLayoutGroup group = mItemGrid.GetComponent<GridLayoutGroup>(); float cellSize = group.cellSize.x; //一个格子的宽度 float spacing = group.spacing.x; //格子的间距 //总宽度 float totalWidth = cellSize * resultCount + (resultCount - 1) * spacing; //Debug.LogError(totalWidth); RectTransform rectWidth = mItemGrid.GetComponent<RectTransform>(); Vector2 targetVec = new Vector2(totalWidth, rectWidth.sizeDelta.y); rectWidth.sizeDelta = targetVec;
itemTips是UIScrollItemTips变量
ScrollRect滑动组件。怎么可以定位到哪个地方呢。即滑动到指定位置;
ScrollRect有个属性normalizedPosition,是Vector2类型的。
如果是垂直滑动;那么范围是1-0
比如到初始位置
GetComponent<ScrollRect>().normalizedPosition = new Vector2(0, 1);
滑动到最后一页
GetComponent<ScrollRect>().normalizedPosition = new Vector2(0, 0);
原文链接:http://www.cnblogs.com/nsky/p/4854002.html