Tanoda
UIVerticalScroller.cs
Go to the documentation of this file.
1
4
6
8{
9 [RequireComponent(typeof(ScrollRect))]
10 [AddComponentMenu("Layout/Extensions/Vertical Scroller")]
11 public class UIVerticalScroller : MonoBehaviour
12 {
13 [Tooltip("desired ScrollRect")]
14 public ScrollRect scrollRect;
15 [Tooltip("Center display area (position of zoomed content)")]
16 public RectTransform center;
17 [Tooltip("Size / spacing of elements")]
18 public RectTransform elementSize;
19 [Tooltip("Scale = 1/ (1+distance from center * shrinkage)")]
20 public Vector2 elementShrinkage = new Vector2(1f / 200, 1f / 200);
21 [Tooltip("Minimum element scale (furthest from center)")]
22 public Vector2 minScale = new Vector2(0.7f, 0.7f);
23 [Tooltip("Select the item to be in center on start.")]
24 public int startingIndex = -1;
25 [Tooltip("Stop scrolling past last element from inertia.")]
26 public bool stopMomentumOnEnd = true;
27 [Tooltip("Set Items out of center to not interactible.")]
28 public bool disableUnfocused = true;
29 [Tooltip("Button to go to the next page. (optional)")]
30 public GameObject scrollUpButton;
31 [Tooltip("Button to go to the previous page. (optional)")]
32 public GameObject scrollDownButton;
33 [Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
35 [Tooltip("Event fired when the focused item is Changed. (optional)")]
37 [HideInInspector]
38 public GameObject[] _arrayOfElements;
39
40 public int focusedElementIndex { get; private set; }
41
42 public string result { get; private set; }
43
44 private float[] distReposition;
45 private float[] distance;
46 //private int elementsDistance;
47
48
49 //Scrollable area (content of desired ScrollRect)
50 [HideInInspector]
51 public RectTransform scrollingPanel{ get { return scrollRect.content; } }
52
53
58 {
59 }
60
64 public UIVerticalScroller(RectTransform center, RectTransform elementSize, ScrollRect scrollRect, GameObject[] arrayOfElements)
65 {
66 this.center = center;
67 this.elementSize = elementSize;
68 this.scrollRect = scrollRect;
69 _arrayOfElements = arrayOfElements;
70 }
71
75 public void Awake()
76 {
77 if (!scrollRect)
78 {
79 scrollRect = GetComponent<ScrollRect>();
80 }
81 if (!center)
82 {
83 Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
84 }
85 if (!elementSize)
86 {
88 }
89 if (_arrayOfElements == null || _arrayOfElements.Length == 0)
90 {
91 _arrayOfElements = new GameObject[scrollingPanel.childCount];
92 for (int i = 0; i < scrollingPanel.childCount; i++)
93 {
94 _arrayOfElements[i] = scrollingPanel.GetChild(i).gameObject;
95 }
96 }
97 }
98
104 public void updateChildren(int startingIndex = -1, GameObject[] arrayOfElements = null)
105 {
106 // Set _arrayOfElements to arrayOfElements if given, otherwise to child objects of the scrolling panel.
107 if (arrayOfElements != null)
108 {
109 _arrayOfElements = arrayOfElements;
110 }
111 else
112 {
113 _arrayOfElements = new GameObject[scrollingPanel.childCount];
114 for (int i = 0; i < scrollingPanel.childCount; i++)
115 {
116 _arrayOfElements[i] = scrollingPanel.GetChild(i).gameObject;
117 }
118 }
119
120 // resize the elements to match elementSize rect
121 for (var i = 0; i < _arrayOfElements.Length; i++)
122 {
123 int j = i;
124 _arrayOfElements[i].GetComponent<Button>().onClick.RemoveAllListeners();
125 if (OnButtonClicked != null)
126 {
127 _arrayOfElements[i].GetComponent<Button>().onClick.AddListener(() => OnButtonClicked.Invoke(j));
128 }
129 RectTransform r = _arrayOfElements[i].GetComponent<RectTransform>();
130 r.anchorMax = r.anchorMin = r.pivot = new Vector2(0.5f, 0.5f);
131 r.localPosition = new Vector2(0, i * elementSize.rect.size.y);
132 r.sizeDelta = elementSize.rect.size;
133 }
134
135 // prepare for scrolling
136 distance = new float[_arrayOfElements.Length];
137 distReposition = new float[_arrayOfElements.Length];
139
140 //scrollRect.scrollSensitivity = elementSize.rect.height / 5;
141
142 // if starting index is given, snap to respective element
143 if (startingIndex > -1)
144 {
147 }
148 }
149
150 public void Start()
151 {
152
153 if (scrollUpButton)
154 scrollUpButton.GetComponent<Button>().onClick.AddListener(() =>
155 {
156 ScrollUp();
157 });
158
160 scrollDownButton.GetComponent<Button>().onClick.AddListener(() =>
161 {
162 ScrollDown();
163 });
165 }
166
167
168 public void Update()
169 {
170 if (_arrayOfElements.Length < 1)
171 {
172 return;
173 }
174
175 for (var i = 0; i < _arrayOfElements.Length; i++)
176 {
177 distReposition[i] = center.GetComponent<RectTransform>().position.y - _arrayOfElements[i].GetComponent<RectTransform>().position.y;
178 distance[i] = Mathf.Abs(distReposition[i]);
179
180 //Magnifying effect
181 Vector2 scale = Vector2.Max(minScale, new Vector2(1 / (1 + distance[i] * elementShrinkage.x), (1 / (1 + distance[i] * elementShrinkage.y))));
182 _arrayOfElements[i].GetComponent<RectTransform>().transform.localScale = new Vector3(scale.x, scale.y, 1f);
183 }
184
185 // detect focused element
186 float minDistance = Mathf.Min(distance);
187 int oldFocusedElement = focusedElementIndex;
188 for (var i = 0; i < _arrayOfElements.Length; i++)
189 {
190 _arrayOfElements[i].GetComponent<CanvasGroup>().interactable = !disableUnfocused || minDistance == distance[i];
191 if (minDistance == distance[i])
192 {
194 result = _arrayOfElements[i].GetComponentInChildren<Text>().text;
195 }
196 }
197 if (focusedElementIndex != oldFocusedElement && OnFocusChanged != null)
198 {
200 }
201
202
203 if (!Input.GetMouseButton(0))
204 {
205 // scroll slowly to nearest element when not dragged
206 ScrollingElements();
207 }
208
209
210 // stop scrolling past last element from inertia
212 && (_arrayOfElements[0].GetComponent<RectTransform>().position.y > center.position.y
213 || _arrayOfElements[_arrayOfElements.Length - 1].GetComponent<RectTransform>().position.y < center.position.y))
214 {
215 scrollRect.velocity = Vector2.zero;
216 }
217 }
218
219 private void ScrollingElements()
220 {
221 float newY = Mathf.Lerp(scrollingPanel.anchoredPosition.y, scrollingPanel.anchoredPosition.y + distReposition[focusedElementIndex], Time.deltaTime * 2f);
222 Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, newY);
223 scrollingPanel.anchoredPosition = newPosition;
224 }
225
226 public void SnapToElement(int element)
227 {
228 float deltaElementPositionY = elementSize.rect.height * element;
229 Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, -deltaElementPositionY);
230 scrollingPanel.anchoredPosition = newPosition;
231
232 }
233
234 public void ScrollUp()
235 {
236 float deltaUp = elementSize.rect.height / 1.2f;
237 Vector2 newPositionUp = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y - deltaUp);
238 scrollingPanel.anchoredPosition = Vector2.Lerp(scrollingPanel.anchoredPosition, newPositionUp, 1);
239 }
240
241 public void ScrollDown()
242 {
243 float deltaDown = elementSize.rect.height / 1.2f;
244 Vector2 newPositionDown = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y + deltaDown);
245 scrollingPanel.anchoredPosition = newPositionDown;
246 }
247
248 [System.Serializable]
249 public class IntEvent:UnityEvent<int>
250 {
251
252 }
253 }
254}
UnityEngine.UI.Button Button
Definition: Pointer.cs:7
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
void updateChildren(int startingIndex=-1, GameObject[] arrayOfElements=null)
Recognises and resizes the children.
UIVerticalScroller(RectTransform center, RectTransform elementSize, ScrollRect scrollRect, GameObject[] arrayOfElements)
Constructor when not used as component but called from other script
UIVerticalScroller()
Constructor when not used as component but called from other script, don't forget to set the non-opti...
Credit Erdener Gonenc - @PixelEnvision.