热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UnityNGUIScrollView苹果式滑动

又回来写博客了,这回已经开始上班了,所以就发一发工作中解决的难题吧。单个展示Panel(苹果式)以前对UI的滑动组件很烦心,不是很会用,这回项目要求写一个类似于苹果的文件滑动效果,





又回来写博客了,这回已经开始上班了,所以就发一发工作中解决的难题吧。


单个展示Panel(苹果式)


以前对UI的滑动组件很烦心,不是很会用,这回项目要求写一个类似于苹果的文件滑动效果,但是苹果就展示一个文件,而我这边展示数目不定,头疼!


下面就直接来干货吧~,这里附送一个苹果式滑动解决方式 : 点这里


多个展示Panel(改写)


而我追求的效果呢,稍微改动一下,如下:(中间显示很多个,旁边的在叠起来的效果)


Unity NGUI ScrollView 苹果式滑动


这里我们采用比例的方式,这样好控制一些。


几个比较重要的点:



  • 每个Panel之间的比例差值



_offset = 1f / (totalPanelCount - showPanelCount); // 1f / (总共Panel - 展示Panel)



  • 获得拖动结束要偏移到的目标位置



private float GetTarget()
{
return Mathf.Clamp01(Mathf.RoundToInt(_scrollValue / _offset) * _offset); // 取得最近的整数位
}



  • 分成三个区域,左缩放区域,右缩放区域,中间展示区域



 1     private void AnimationCore(int index)
2 {
3 float sourcePos = index * _offset;
4 // 左边区域
5 if (sourcePos < _scrollValue)
6 {
7 float dif = _scrollValue - sourcePos;
8 int depth = _currentIndex - index;
9 _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
10 _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, true), 100 * Time.deltaTime);
11 }
12 // 右边区域
13 else if (sourcePos > _scrollValue + _offset * (showPanelCount - 1))
14 {
15 float dif = sourcePos - _scrollValue - _offset * (showPanelCount - 1);
16 int depth = index - _currentIndex - showPanelCount + 1;
17 _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
18 _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, false), 100 * Time.deltaTime);
19 }
20 // 中间区域
21 else
22 {
23 _panelPool[index].transform.SetAsLastSibling();
24 _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, _panelPoolPos[index], 100 * Time.deltaTime);
25 }
26 }



  • 获取Panel的滑动偏移位置



    private Vector3 GetTargetPos(int index, float dif, bool isLeft)
{
float offSetDif = 60 / _offset * dif;
if (isLeft)
{
return _panelPoolPos[index] + Vector3.right * offSetDif; // 左区域
}
else
{
return _panelPoolPos[index] - Vector3.right * offSetDif; // 右区域
}
}



  • 获取当前滑动的位置



 1     private float _scrollValue
2 {
3 get
4 {
5 return _scrollRect.horizontal ?
6 _scrollRect.horizontalNormalizedPosition :
7 _scrollRect.verticalNormalizedPosition;
8 }
9
10 set
11 {
12 if (_scrollRect.horizontal)
13 {
14 _scrollRect.horizOntalNormalizedPosition= value;
15 }
16 else
17 {
18 _scrollRect.verticalNormalizedPosition = value;
19 }
20 }
21 }


需要继承NGUI的EventSystem的时间来触发管理拖动 PS:用DOTween做最后的回滑效果


完整代码如下:



  1 using System;
2 using UnityEngine;
3 using UnityEngine.EventSystems;
4 using UnityEngine.UI;
5 using DG.Tweening;
6
7 [RequireComponent(typeof(ScrollRect))]
8 public class ScrollController : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
9 {
10 [Tooltip("创建出来的对象")]
11 public GameObject imageObject;
12 [Tooltip("展示页面数量")]
13 public int showPanelCount = 8;
14 [Tooltip("总计页面数量")]
15 public int totalPanelCount = 20;
16 [Tooltip("拖动结束制动弹回制动时间")]
17 public float endDragMoveTime = 1f;
18 public Ease doTweenEase = Ease.OutExpo;
19
20 private int _currentIndex;
21 private ScrollRect _scrollRect;
22 private Tweener _tweener;
23 private GameObject[] _panelPool = new GameObject[20];
24 private Vector3[] _panelPoolPos = new Vector3[20];
25 private float _offset;
26
27 void Start()
28 {
29 _currentIndex = 1;
30 _scrollRect = GetComponent();
31 _scrollRect.inertia = false;
32
33 for (int i = 0; i )
34 {
35 GameObject go = Instantiate(imageObject) as GameObject;
36 go.transform.SetParent(_scrollRect.content.transform);
37 go.GetComponent().sizeDelta = new Vector2(100, 200);
38 go.GetComponent().anchorMax = new Vector2(0, 0.5f);
39 go.GetComponent().anchorMin = new Vector2(0, 0.5f);
40 go.GetComponent().pivot = new Vector2(0, 0.5f);
41 go.GetComponent().anchoredPosition = new Vector2(100 + 100 * i, 0);
42 go.transform.localScale = Vector3.one;
43 _panelPool[i] = go;
44 _panelPoolPos[i] = go.transform.localPosition;
45 }
46
47 _scrollRect.content.GetComponent().sizeDelta = new Vector2(totalPanelCount * 100 + 200, 200);
48
49 _offset = 1f / (totalPanelCount - showPanelCount);
50
51 for (int i = 0; i )
52 {
53 AnimationCore(i);
54 }
55 }
56
57 public void OnBeginDrag(PointerEventData eventData)
58 {
59 if (_tweener != null && _tweener.IsActive())
60 {
61 _tweener.Kill();
62 }
63 }
64
65 public void OnDrag(PointerEventData eventData)
66 {
67 _currentIndex = Mathf.RoundToInt(GetTarget() * (totalPanelCount - showPanelCount));
68
69 OnDragAnimation();
70 }
71
72 public void OnEndDrag(PointerEventData eventData)
73 {
74 _tweener = DOTween.To(() => _scrollValue, (v) => _scrollValue = v, GetTarget(), endDragMoveTime).SetEase(doTweenEase);
75 _tweener.OnUpdate= () =>
76 {
77 OnDragAnimation();
78 };
79 }
80
81 private void OnDragAnimation()
82 {
83 //向左拉动(解决层级问题)
84 if (_scrollValue > 0)
85 {
86 for (int i = 0; i )
87 {
88 AnimationCore(i);
89 }
90 }
91 else
92 {
93 for (int i = totalPanelCount - 1; i >= 0; i--)
94 {
95 AnimationCore(i);
96 }
97 }
98 }
99
100 private void AnimationCore(int index)
101 {
102 float sourcePos = index * _offset;
103 // 左边区域
104 if (sourcePos < _scrollValue)
105 {
106 float dif = _scrollValue - sourcePos;
107 int depth = _currentIndex - index;
108 _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
109 _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, true), 100 * Time.deltaTime);
110 }
111 // 右边区域
112 else if (sourcePos > _scrollValue + _offset * (showPanelCount - 1))
113 {
114 float dif = sourcePos - _scrollValue - _offset * (showPanelCount - 1);
115 int depth = index - _currentIndex - showPanelCount + 1;
116 _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
117 _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, false), 100 * Time.deltaTime);
118 }
119 // 中间区域
120 else
121 {
122 _panelPool[index].transform.SetAsLastSibling();
123 _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, _panelPoolPos[index], 100 * Time.deltaTime);
124 }
125 }
126
127 ///
128 /// 获取到页面的偏移后位置
129 ///

130 ///
131 private Vector3 GetTargetPos(int index, float dif, bool isLeft)
132 {
133 float offSetDif = 60 / _offset * dif;
134 if (isLeft)
135 {
136 return _panelPoolPos[index] + Vector3.right * offSetDif;
137 }
138 else
139 {
140 return _panelPoolPos[index] - Vector3.right * offSetDif;
141 }
142 }
143
144 ///
145 /// 获得偏转目标位置
146 ///

147 ///
148 private float GetTarget()
149 {
150 return Mathf.Clamp01(Mathf.RoundToInt(_scrollValue / _offset) * _offset);
151 }
152
153 ///
154 /// 当前滑动位置
155 ///

156 ///
157 private float _scrollValue
158 {
159 get
160 {
161 return _scrollRect.horizontal ?
162 _scrollRect.horizontalNormalizedPosition :
163 _scrollRect.verticalNormalizedPosition;
164 }
165
166 set
167 {
168 if (_scrollRect.horizontal)
169 {
170 _scrollRect.horizOntalNormalizedPosition= value;
171 }
172 else
173 {
174 _scrollRect.verticalNormalizedPosition = value;
175 }
176 }
177 }
178 }


 







推荐阅读
author-avatar
水门街口卖瓜子的
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有