ScrollView列表带阻尼效果滑动居中

       为了实现带阻尼滑动居中,在网上查了蛮多资料,但是感觉都不怎么好用,只能自己花时间摸索了。实时拖拽就利用了UGUI的ScrollView实现了,回弹和阻尼居中用了LeanTween(我现在项目里都在用这个,所以直接拿来用了,可以用自己写其他的代替),仔细看看里面有很多地方是可以优化的,比如,我这需要判断列表里对象的奇偶性。。。大概的思路就是这样,工作经验实在有限。差点忘了,里面还有选中区域内放大功能。

脚本我就挂在ScrollView上
 
 
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;

public class MusicScrollView : MonoBehaviour, IEndDragHandler, IBeginDragHandler
{
    LTDescr lt;//LeanTween
    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;       //父节点 

    //[UI设置参数]
    private float m_inertiaTime = 0f;    //惯性作用时间 
    private float m_BackTime = 0.3f;     //会弹时间
    private float m_startDecelert = 0.8f;//初始惯性加速度
    private float m_UpRange = 0.4f;      //放大检测范围及Scale增量

    float m_SpaceBetween;               //设置的碟片间距
    float m_ParentStarPosY;             //Content初始Y位置
    float m_CurPosY;                    //Content相对Y位置(0为参考)
    float m_ItemHight;                  //碟片高度
    int m_Index = 0;                    //Y位置与碟片(高度+间距)的整倍数
    float m_Surplus = 0;                //Y位置与碟片(高度+间距)的整倍后剩余
    Vector3 m_StartPos;                 //记录每次需要居中前的Content位置

    void Awake()
    {
        _instance = this;
        scrollRect = GetComponent<ScrollRect>();
        ContentObj = scrollRect.content;
    }

    void OnEnable()
    {
    }

    // Use this for initialization
    void Start()
    {
        m_ItemHight = Math.Abs(2 * ItemObj.transform.GetComponent<RectTransform>().rect.y);//sizeDelta.y获取的是子对象UI的Height(此处的方法会根据锚点不同而修改)
        m_SpaceBetween = ContentObj.GetComponent<GridLayoutGroup>().spacing.y + m_ItemHight;
        //Debug.Log(m_ItemHight);
    }

    void Init()
    {
        if (ContentObj.childCount % 2 == 0)//判断子对象的奇偶
        {
            m_ParentStarPosY = -(m_SpaceBetween / 2);
            ContentObj.localPosition = new Vector3(ContentObj.localPosition.x, m_ParentStarPosY, ContentObj.localPosition.z);
        }
        m_ParentStarPosY = ContentObj.localPosition.y;
    }

    // Update is called once per frame
    void Update()
    {
        //Debug.Log(ParentList.localPosition + "____" + ParentList.position);
        //Debug.Log(ContentObj.GetChild(4).position);
        ChanageItemScale();
    }



    /// <summary>
    /// 更新列表内容
    /// </summary>
    /// <param name="Rr">对象</param>
    public void RefreshMusicList(List<ResResut> Rr)
    {
        gameObject.SetActive(true);
        DicItem[] itemList = ContentObj.AddChild<DicItem>(ItemObj.gameObject, Rr.Count);
        for (int i = 0; i < itemList.Length; i++)
        {
            if (Rr[i].ResType == 1)
                itemList[i].Init(Rr[i],i%3+6);//
        }


        Init();//更新列表位置
      
    }


    /// <summary>
    /// Item定位
    /// </summary>
    public void LocateItem()
    {
        //Debug.Log(m_Index + "========Index");
        //Debug.Log(m_CurPosY + "___sp___" + m_Surplus + "___cur__" + m_Index * m_SpaceBetween + m_ParentStarPosY);
        lt = LeanTween.value(0, 1, m_inertiaTime).setOnStart(() =>
        {
            scrollRect.decelerationRate = 0.6f;
        }).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));
                    //Debug.Log(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));
                    }
                }
                //Debug.Log(m_Index + "___wai");


            }).setOnUpdate((float f) =>
            {
                ContentObj.localPosition = Vector3.Lerp(m_StartPos, new Vector3(ContentObj.localPosition.x, m_Index * m_SpaceBetween + m_ParentStarPosY, ContentObj.localPosition.z), f);
                //Debug.Log(f+"___Scale_F_____+ Pos"+ ContentObj.localPosition);
            });
        });
    }

    void IEndDragHandler.OnEndDrag(PointerEventData eventData)	//结束拖拽
    {
        //Debug.Log("UP");
        scrollRect.OnEndDrag(eventData);
        m_inertiaTime = Mathf.Clamp01(Math.Abs(eventData.delta.y * 0.008f));
        LocateItem();

    }

    public void OnBeginDrag(PointerEventData eventData)		//开始拖拽
    {
        //Debug.Log("New ");
        if (lt != null)
            lt.reset();
        //scrollRect.OnEndDrag(eventData);
        //((IBeginDragHandler)Instance).OnBeginDrag(eventData);
        //Debug.Log(eventData.delta.y + "____start");
    }

    /// <summary>
    /// 碟片尺寸过渡
    /// </summary>
    void ChanageItemScale()
    {
        for (int i = 0; i < ContentObj.childCount; i++)
        {
            if (ContentObj.GetChild(i).position.y < SingBox.transform.position.y+ m_UpRange && ContentObj.GetChild(i).position.y > SingBox.transform.position.y- m_UpRange)
            {
                float m_addSca = m_UpRange - Math.Abs(ContentObj.GetChild(i).position.y - SingBox.transform.position.y);
                ContentObj.GetChild(i).transform.localScale = Vector3.one + new Vector3(m_addSca, m_addSca, m_addSca);
            }
            else
            {
                ContentObj.GetChild(i).transform.localScale = Vector3.one;
            }
        }

    }


}

下面是面板上的设置截图






猜你喜欢

转载自blog.csdn.net/sam_one/article/details/59056766