UNITY UGUI如何实现整页滑动

发表于2017-05-03
评论2 8.7k浏览
  现在很多项目都喜欢用整页滑动,这样看的东西会更多,那么这个功能是如何去开发实现的呢,下面就给大家介绍下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 


如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论