ScrollView列表带阻尼效果滑动居中
2017-03-01 10:10
323 查看
为了实现带阻尼滑动居中,在网上查了蛮多资料,但是感觉都不怎么好用,只能自己花时间摸索了。实时拖拽就利用了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; } } } }
下面是面板上的设置截图
相关文章推荐
- Unity 滑动列表时实现平滑阻尼效果初始篇
- Unity 滑动列表时实现平滑阻尼效果修改篇
- Android Design ItemTouchHelper实现酷炫列表的移行和滑动删除效果
- Android ScrollView向上滑动控件顶部悬浮效果实现
- Android 自定义ScrollView 支持惯性滑动,惯性回弹效果。支持上拉加载更多
- Android回弹阻尼效果的简单实现,非基于ListView,ScrollView
- Android仿微信对话列表滑动删除效果
- ScrollView滑动悬停效果
- 学习笔记之——自定义带滑动距离监控和仿iOS回弹效果的ScrollView
- scrollview 上下滑动 禁止弹回效果
- 一个 ScrollView 里面包含 viewpager 嵌套 listview 或 RecyclerView 极少代码实现的流畅滑动效果 处理一个两层滑动 view 的自定义布局,以最少的代码实现,
- Android UI设计之<十三>自定义ScrollView,实现QQ空间阻尼下拉刷新和渐变菜单栏效果
- NestedScrollView 嵌套 ListView 实现滑动折叠效果
- 高仿微信对话列表滑动删除效果
- android ScrollView向上滑动 控件顶部悬浮效果实现
- 忘了哪个大神的博客的滑动刷新带有弹簧效果的ScrollView
- ScrollView、ListView、GridView去掉边缘的蓝边和滑动条,改变item点击效果
- 如何去掉滑动控件(比如ScrollView、ListView、ViewPager等)滑动到最顶部或最底部时出现的阴影效果。
- Android ScrollView .顶部栏滑动透明度改变,底部栏滑到特定位置显示或隐藏效果
- ScrollView阻尼效果