ScrollView无限循环阻尼居中(带缩放)

来源:互联网 发布:蓟县一中网络空间 编辑:程序博客网 时间:2024/04/30 13:06

       前两天写的SceollView阻尼居中的忘了加入循环列表的功能,本来我以为加入循环的功能不难,当写了才发现,因为上一个版本的Content里为了方便加的两个挂件(Content Size Fitter 和 Grid Layout Group)让我很尴尬,中间我试着实现了循环功能,发现在运行情况下我切换至VS后切换回Unity之后它又让我回到解放前(交换的Item位置又倍还原了。。),其中的原有我大概了解,但水平有限无法说明了。所以这次,我把它们卸了,自己给每个Item赋值,搞定!能力有限,写不出什么复用性高的代码。。。。。

之前忘记说,中间有一个AddChild()方法是自己写的拓展方法,只是为了方便一次性加入Item对象并返回所以子对象而写。
其中SignBox是放大区的标记点。

下面是代码:

using UnityEngine;using System.Collections;using System.Collections.Generic;using GameServer.Script.Model;using UnityEngine.UI;using UnityEngine.EventSystems;using System;public class MusicScrollView : MonoBehaviour, IEndDragHandler, IBeginDragHandler{    LTDescr lt;    private static MusicScrollView _instance;    public static MusicScrollView Instance    {        get        {            if (_instance == null)            {                GameObject go = new GameObject();                _instance = go.AddComponent<MusicScrollView>();            }            return _instance;        }    }    //[组件信息]    ScrollRect scrollRect;    public DicItem ItemObj;             //Item    public GameObject SingBox;          //标记盒子              private Transform ContentObj;       //父节点    List<DicItem> itemList;             //子节点管理    //[UI效果设置参数]    private float m_inertiaTime = 0f;    //惯性作用时间     private float m_BackTime = 0.3f;     //会弹时间    private float m_startDecelert = 0.05f;//初始惯性加速度    private float m_UpRange = 0.4f;      //放大检测范围及Scale增量    //[Item设置参数]    float m_SpaceBetween;               //设置的碟片中心点间距    float m_ParentStarPosY;             //Content初始Y位置    float m_CurPosY;                    //Content相对Y位置(0为参考)    float ItemHeight = 300;             //碟片高度    float SpaceY = 180;                 //碟片边缘之间的间距    int m_Index = 0;                    //Y位置与碟片(高度+间距)的整倍数    float m_Surplus = 0;                //Y位置与碟片(高度+间距)的整倍后剩余    float MaxPosY = 0;                  //根据Item数量、间距、item高度计算得到的Y轴最大的数值    Vector3 m_StartPos;                 //记录每次需要居中前的Content位置    //[Item包含数据相关]    [HideInInspector]    public DicItem SelectDic;           //选中碟片歌曲信息    private int SelectItem;             //选中歌曲在Content下的排列序号    private int RealAmount;             //真实的List<ResResut>Count    //[计算相关数值]    private int Direct = 0;    private Vector3 lastPos;    private Vector3 firstPos;    int fistIndex = 0;    int lastIndex = 0;    Vector3[] PosArra;    void Awake()    {        _instance = this;        scrollRect = GetComponent<ScrollRect>();        ContentObj = scrollRect.content;    }    // Use this for initialization    void Start()    {        m_SpaceBetween = SpaceY + ItemHeight;// ContentObj.GetComponent<GridLayoutGroup>().spacing.y + m_ItemHight;    }    /// <summary>    /// Content的初始位置Y赋值    /// </summary>    void ContentPointInit()    {        if (ContentObj.childCount % 2 == 0)//判断子对象的奇偶(上一次亦为奇数)        {            ContentObj.localPosition = new Vector3(ContentObj.localPosition.x, ContentObj.localPosition.y - (m_SpaceBetween / 2), ContentObj.localPosition.z);        }        else if (ContentObj.childCount % 2 != 0)        {        }        m_ParentStarPosY = ContentObj.localPosition.y;    }    // Update is called once per frame    void Update()    {        m_PreviousIndex = m_CurrentIndex;        ChanageItemScale();        CalculationContentChanege();    }    /// <summary>    /// 初始更新列表内容    /// </summary>    /// <param name="Rr">对象</param>    public void RefreshMusicList(List<ResResut> Rr)    {        MaxPosY = (Rr.Count / 2) * m_SpaceBetween;      //根据Item数量计算得到最顶上Item的Pos,用于往下一次推算之后的Pos        if (Rr.Count % 2 == 0)            MaxPosY -= m_SpaceBetween / 2;        RealAmount = Rr.Count;        gameObject.SetActive(true);        itemList = ContentObj.AddChild<DicItem>(ItemObj.gameObject, Rr.Count).ToList();//数组转List        for (int i = 0; i < itemList.Count; i++)        {            if (Rr[i].ResType == 1)                itemList[i].Init(Rr[i], i % 3); //专辑封面零时            itemList[i].transform.localPosition = new Vector3(0, MaxPosY - i * m_SpaceBetween, 0);     //便利赋值所有子对象的LocaPos        }        ContentPointInit();                     //更新列表初始位置        fistIndex = 0;                          //记录首末序号        lastIndex = RealAmount - 1;    }    /// <summary>    /// Item定位    /// </summary>    public void LocateItem()    {        lt = LeanTween.value(0, 1, m_inertiaTime).setOnStart(() =>        {            scrollRect.decelerationRate = m_startDecelert;        }).setOnUpdate((float f) =>        {            scrollRect.decelerationRate = Mathf.Lerp(m_startDecelert, 0, f);        }).setOnComplete(() =>        {            lt = LeanTween.value(0, 1, m_BackTime).setOnStart(() =>            {                m_StartPos = ContentObj.localPosition;                m_CurPosY = ContentObj.localPosition.y - m_ParentStarPosY;                m_Index = (int)(m_CurPosY / m_SpaceBetween);                m_Surplus = m_CurPosY % m_SpaceBetween;                if ((m_Surplus >= (m_SpaceBetween / 3) && m_Index > 0) || (m_Index < 0 && -m_Surplus >= (m_SpaceBetween / 3)))                {                    m_Index += (m_Index / Mathf.Abs(m_Index));                }                else if (m_Index == 0)                {                    if ((m_CurPosY > 0 && m_CurPosY >= (m_SpaceBetween / 3)) || (m_CurPosY < 0 && -m_CurPosY >= (m_SpaceBetween / 3)))                    {                        m_Index += (int)(m_CurPosY / Mathf.Abs(m_CurPosY));                    }                }            }).setOnUpdate((float f) =>            {                ContentObj.localPosition = Vector3.Lerp(m_StartPos, new Vector3(ContentObj.localPosition.x, m_Index * m_SpaceBetween + m_ParentStarPosY, ContentObj.localPosition.z), f);            });        });    }    void IEndDragHandler.OnEndDrag(PointerEventData eventData)    {        scrollRect.OnEndDrag(eventData);        m_inertiaTime = Mathf.Clamp(Mathf.Clamp01(Math.Abs(eventData.delta.y * 0.008f)), 0, 0.1f);      //根据拖拽的速度限制惯性运行的时间        LocateItem();    }    public void OnBeginDrag(PointerEventData eventData)    {        if (lt != null)            lt.reset();    }    /// <summary>    /// 碟片尺寸过渡    /// </summary>    void ChanageItemScale()    {        for (int i = 0; i < itemList.Count; i++)        {            if (itemList[i].transform.position.y < SingBox.transform.position.y + m_UpRange && itemList[i].transform.position.y > SingBox.transform.position.y - m_UpRange)            {                float m_addSca = m_UpRange - Math.Abs(itemList[i].transform.position.y - SingBox.transform.position.y);                itemList[i].transform.localScale = Vector3.one + new Vector3(m_addSca, m_addSca, m_addSca);                if (m_addSca >= (m_UpRange - 0.3f))//&& i != m_LastIndex                {                    if (SelectItem != i)                    {                        SelectItem = i;                                                     //得到Scale最大的碟片序号                        SelectDic = itemList[i].transform.GetComponent<DicItem>();          //得到Scale最大的碟片信息                    }                }            }            else            {                itemList[i].transform.transform.localScale = Vector3.one;            }        }    }    void Circulation(int _dir)    {        if (_dir > 0)        {            itemList[fistIndex].transform.localPosition = itemList[lastIndex].transform.localPosition - new Vector3(0, m_SpaceBetween, 0);//PosArra[RealAmount - 1];            lastIndex = fistIndex;            fistIndex = (fistIndex + 1) % RealAmount;        }        else if (_dir < 0)        {            itemList[lastIndex].transform.localPosition = itemList[fistIndex].transform.localPosition + new Vector3(0, m_SpaceBetween, 0);            fistIndex = lastIndex;            lastIndex = (lastIndex + RealAmount - 1) % RealAmount;        }    }    int m_CurrentIndex = 0;    int m_PreviousIndex = 0;    private void CalculationContentChanege()    {        m_CurrentIndex = Mathf.FloorToInt(((ContentObj.localPosition.y)/ m_SpaceBetween));  //向下取整获得变化的Index!!!!!!!!!!        if (m_PreviousIndex != m_CurrentIndex)                                                      {            for (int i = 0; i < Mathf.Abs(m_CurrentIndex - m_PreviousIndex); i++)                Circulation(m_CurrentIndex - m_PreviousIndex);        }    }    //List<DicItem> sortList(int _ChanageIndx, List<DicItem> _list)    //{    //    List<DicItem> temp = new List<DicItem>();    //    for (int i = 0; i < _list.Count; i++)    //    {    //        if (_ChanageIndx < 0)    //            temp[i] = _list[(i + 1) % _list.Count];    //        else    //            temp[i] = _list[(_list.Count - 1 - i) % _list.Count];    //    }    //    return temp;    //}}

在上下AddChild()的拓
using UnityEngine;using System.Collections;using System.Collections.Generic;public static partial class Extensions{    public static T[] AddChild<T>(this Transform trans,GameObject t,int count,bool isReset = false)where T:MonoBehaviour    {        //获取所有子物体        T[] children = trans.GetComponentsInChildren<T>(true);                //子物体的数量少于要求的        if (children.Length < count)        {            //要补充创建的数量            int createCount = count - children.Length;            for(int i = 0; i < createCount; i++)            {                 //实例化的对象                GameObject go = GameObject.Instantiate(t);                //设置父物体                go.transform.SetParent(trans);                //设置初值                go.transform.localScale = Vector3.one;                go.transform.localPosition = Vector3.zero;            }        }        children = trans.GetComponentsInChildren<T>(true);        int cur = 0;        for(int i = 0; i < children.Length; i++)        {            //获取子物体            T child = children[i];            child.transform.SetParent(trans);            child.transform.localScale = Vector3.one;            child.transform.localPosition = Vector3.zero;            //如果索引小于物体总数            if (cur < count)                //激活子物体                child.gameObject.SetActive(true);            else                //失活子物体                child.gameObject.SetActive(false);            //索引++            cur++;        }        //返回数组        return trans.GetComponentsInChildren<T>()
}    /// <summary>    /// 数组转list    /// </summary>    /// <typeparam name="T"></typeparam>    /// <param name="arr"></param>    /// <returns></returns>    public static List<T> ToList<T>(this T[] arr)    {        List<T> list = new List<T>();        for (int i = 0; i < arr.Length; i++)        {            list.Add(arr[i]);        }        return list;    }}
组件面板参数设置

能力有限,只是抱着分享和记录并学习的想法上传了,有不妥的地方,见谅。




0 0
原创粉丝点击