More Options for UI Vertical Scroller
- Option to stop scrolling momentum when scrolling past first / last item (still draggable in that direction) - Explicit function to recognize / set array elements in case they were changed - Resize elements to match elementSize rect object (defaults to center object), scaled using modifiable elementShrinkage and minSize - Detect focusedElement and trigger event if focus changes - Option whether to make unfocused elements interactible or notpull/413/head
parent
ff47f703c0
commit
cee50a6d63
|
@ -607,7 +607,7 @@ namespace UnityEditor.UI
|
||||||
rectTransformCenter.anchorMax = new Vector2(1f, 0.6f);
|
rectTransformCenter.anchorMax = new Vector2(1f, 0.6f);
|
||||||
rectTransformCenter.sizeDelta = Vector2.zero;
|
rectTransformCenter.sizeDelta = Vector2.zero;
|
||||||
|
|
||||||
uiscr._center = uiScrollerCenter.GetComponent<RectTransform>();
|
uiscr.center = uiScrollerCenter.GetComponent<RectTransform>();
|
||||||
|
|
||||||
//Setup Content container
|
//Setup Content container
|
||||||
RectTransform rectTransformContent = childContent.GetComponent<RectTransform>();
|
RectTransform rectTransformContent = childContent.GetComponent<RectTransform>();
|
||||||
|
|
|
@ -38,7 +38,7 @@ RenderSettings:
|
||||||
m_ReflectionIntensity: 1
|
m_ReflectionIntensity: 1
|
||||||
m_CustomReflection: {fileID: 0}
|
m_CustomReflection: {fileID: 0}
|
||||||
m_Sun: {fileID: 0}
|
m_Sun: {fileID: 0}
|
||||||
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
|
m_IndirectSpecularColor: {r: 0.44657874, g: 0.4964127, b: 0.5748172, a: 1}
|
||||||
--- !u!157 &3
|
--- !u!157 &3
|
||||||
LightmapSettings:
|
LightmapSettings:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -472,11 +472,11 @@ RectTransform:
|
||||||
m_Father: {fileID: 1858671176}
|
m_Father: {fileID: 1858671176}
|
||||||
m_RootOrder: 1
|
m_RootOrder: 1
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.35940847, y: 0.5}
|
m_AnchorMin: {x: 0.39, y: 0}
|
||||||
m_AnchorMax: {x: 0.6406339, y: 1}
|
m_AnchorMax: {x: 0.61, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: -50}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 0, y: 100}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0, y: 0.5}
|
||||||
--- !u!1 &172038071
|
--- !u!1 &172038071
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -507,10 +507,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 12
|
m_RootOrder: 12
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.7869379, y: 0.12806748}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.8576017, y: 0.23082823}
|
||||||
m_AnchoredPosition: {x: 301, y: -209}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 66, y: 67}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &172038073
|
--- !u!114 &172038073
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -577,10 +577,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 10
|
m_RootOrder: 10
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.485, y: 0.28834355}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.515, y: 0.33435583}
|
||||||
m_AnchoredPosition: {x: 0, y: -123}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 30, y: 30}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &278688116
|
--- !u!114 &278688116
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -979,10 +979,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 1858671176}
|
m_Father: {fileID: 1858671176}
|
||||||
m_RootOrder: 0
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0.5}
|
m_AnchorMin: {x: 0.12, y: 0}
|
||||||
m_AnchorMax: {x: 0.28054926, y: 1}
|
m_AnchorMax: {x: 0.34, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: -50}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 1, y: 100}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0, y: 0.5}
|
m_Pivot: {x: 0, y: 0.5}
|
||||||
--- !u!1 &399961834
|
--- !u!1 &399961834
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -1016,10 +1016,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 9
|
m_RootOrder: 9
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.215, y: 0.28834355}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.245, y: 0.33435583}
|
||||||
m_AnchoredPosition: {x: -260, y: -123}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 30, y: 30}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &399961836
|
--- !u!114 &399961836
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -1212,10 +1212,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 11
|
m_RootOrder: 11
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.755, y: 0.28834355}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.785, y: 0.33435583}
|
||||||
m_AnchoredPosition: {x: 260, y: -123}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 30, y: 30}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &608866809
|
--- !u!114 &608866809
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -1365,11 +1365,11 @@ RectTransform:
|
||||||
m_Father: {fileID: 1858671176}
|
m_Father: {fileID: 1858671176}
|
||||||
m_RootOrder: 2
|
m_RootOrder: 2
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.71677464, y: 0.5}
|
m_AnchorMin: {x: 0.66, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 0.88, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: -50}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: -1, y: 100}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 1, y: 0.5}
|
m_Pivot: {x: 0, y: 0.5}
|
||||||
--- !u!1 &674720968
|
--- !u!1 &674720968
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -1508,10 +1508,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 8
|
m_RootOrder: 8
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.755, y: 0.66871166}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.785, y: 0.71472394}
|
||||||
m_AnchoredPosition: {x: 260, y: 125}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 30, y: 30}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &738460844
|
--- !u!114 &738460844
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -2321,6 +2321,9 @@ MonoBehaviour:
|
||||||
monthsScrollingPanel: {fileID: 900655611}
|
monthsScrollingPanel: {fileID: 900655611}
|
||||||
yearsScrollingPanel: {fileID: 1788125454}
|
yearsScrollingPanel: {fileID: 1788125454}
|
||||||
daysScrollingPanel: {fileID: 1390764938}
|
daysScrollingPanel: {fileID: 1390764938}
|
||||||
|
monthsScrollRect: {fileID: 1704132813}
|
||||||
|
yearsScrollRect: {fileID: 1811286347}
|
||||||
|
daysScrollRect: {fileID: 1598544346}
|
||||||
yearsButtonPrefab: {fileID: 118010, guid: 65ce75600991941569988ab4538a21a6, type: 2}
|
yearsButtonPrefab: {fileID: 118010, guid: 65ce75600991941569988ab4538a21a6, type: 2}
|
||||||
monthsButtonPrefab: {fileID: 194106, guid: 6d45e8f0aa19044ffb3553ca52febef2, type: 2}
|
monthsButtonPrefab: {fileID: 194106, guid: 6d45e8f0aa19044ffb3553ca52febef2, type: 2}
|
||||||
daysButtonPrefab: {fileID: 138598, guid: ec6f9b1230e4a4896b7be2e60d3be758, type: 2}
|
daysButtonPrefab: {fileID: 138598, guid: ec6f9b1230e4a4896b7be2e60d3be758, type: 2}
|
||||||
|
@ -2374,10 +2377,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 1
|
m_RootOrder: 1
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.34, y: 0.11196319}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.66, y: 0.26533744}
|
||||||
m_AnchoredPosition: {x: 0, y: -168}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 300, y: 100}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &1285461119
|
--- !u!114 &1285461119
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -2625,10 +2628,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 7
|
m_RootOrder: 7
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.485, y: 0.66871166}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.515, y: 0.71472394}
|
||||||
m_AnchoredPosition: {x: 0, y: 125}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 30, y: 30}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &1580916629
|
--- !u!114 &1580916629
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -3252,10 +3255,10 @@ RectTransform:
|
||||||
m_Father: {fileID: 674720969}
|
m_Father: {fileID: 674720969}
|
||||||
m_RootOrder: 6
|
m_RootOrder: 6
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.215, y: 0.66871166}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.245, y: 0.71472394}
|
||||||
m_AnchoredPosition: {x: -260, y: 125}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 30, y: 30}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &1820653142
|
--- !u!114 &1820653142
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
|
|
@ -13,6 +13,10 @@ namespace UnityEngine.UI.Extensions.Examples
|
||||||
public RectTransform yearsScrollingPanel;
|
public RectTransform yearsScrollingPanel;
|
||||||
public RectTransform daysScrollingPanel;
|
public RectTransform daysScrollingPanel;
|
||||||
|
|
||||||
|
public ScrollRect monthsScrollRect;
|
||||||
|
public ScrollRect yearsScrollRect;
|
||||||
|
public ScrollRect daysScrollRect;
|
||||||
|
|
||||||
public GameObject yearsButtonPrefab;
|
public GameObject yearsButtonPrefab;
|
||||||
public GameObject monthsButtonPrefab;
|
public GameObject monthsButtonPrefab;
|
||||||
public GameObject daysButtonPrefab;
|
public GameObject daysButtonPrefab;
|
||||||
|
@ -51,8 +55,7 @@ namespace UnityEngine.UI.Extensions.Examples
|
||||||
{
|
{
|
||||||
arrayYears[i] = 1900 + i;
|
arrayYears[i] = 1900 + i;
|
||||||
|
|
||||||
GameObject clone = (GameObject)Instantiate(yearsButtonPrefab, new Vector3(0, i * 80, 0), Quaternion.Euler(new Vector3(0, 0, 0))) as GameObject;
|
GameObject clone = Instantiate(yearsButtonPrefab, yearsScrollingPanel);
|
||||||
clone.transform.SetParent(yearsScrollingPanel, false);
|
|
||||||
clone.transform.localScale = new Vector3(1, 1, 1);
|
clone.transform.localScale = new Vector3(1, 1, 1);
|
||||||
clone.GetComponentInChildren<Text>().text = "" + arrayYears[i];
|
clone.GetComponentInChildren<Text>().text = "" + arrayYears[i];
|
||||||
clone.name = "Year_" + arrayYears[i];
|
clone.name = "Year_" + arrayYears[i];
|
||||||
|
@ -74,8 +77,7 @@ namespace UnityEngine.UI.Extensions.Examples
|
||||||
string month = "";
|
string month = "";
|
||||||
months[i] = i;
|
months[i] = i;
|
||||||
|
|
||||||
GameObject clone = (GameObject)Instantiate(monthsButtonPrefab, new Vector3(0, i * 80, 0), Quaternion.Euler(new Vector3(0, 0, 0))) as GameObject;
|
GameObject clone = Instantiate(monthsButtonPrefab, monthsScrollingPanel);
|
||||||
clone.transform.SetParent(monthsScrollingPanel, false);
|
|
||||||
clone.transform.localScale = new Vector3(1, 1, 1);
|
clone.transform.localScale = new Vector3(1, 1, 1);
|
||||||
|
|
||||||
switch (i)
|
switch (i)
|
||||||
|
@ -133,9 +135,7 @@ namespace UnityEngine.UI.Extensions.Examples
|
||||||
for (var i = 0; i < days.Length; i++)
|
for (var i = 0; i < days.Length; i++)
|
||||||
{
|
{
|
||||||
days[i] = i + 1;
|
days[i] = i + 1;
|
||||||
GameObject clone = (GameObject)Instantiate(daysButtonPrefab, new Vector3(0, i * 80, 0), Quaternion.Euler(new Vector3(0, 0, 0))) as GameObject;
|
GameObject clone = Instantiate(daysButtonPrefab, daysScrollingPanel);
|
||||||
clone.transform.SetParent(daysScrollingPanel, false);
|
|
||||||
clone.transform.localScale = new Vector3(1, 1, 1);
|
|
||||||
clone.GetComponentInChildren<Text>().text = "" + days[i];
|
clone.GetComponentInChildren<Text>().text = "" + days[i];
|
||||||
clone.name = "Day_" + days[i];
|
clone.name = "Day_" + days[i];
|
||||||
clone.AddComponent<CanvasGroup>();
|
clone.AddComponent<CanvasGroup>();
|
||||||
|
@ -151,9 +151,9 @@ namespace UnityEngine.UI.Extensions.Examples
|
||||||
InitializeDays();
|
InitializeDays();
|
||||||
|
|
||||||
//Yes Unity complains about this but it doesn't matter in this case.
|
//Yes Unity complains about this but it doesn't matter in this case.
|
||||||
monthsVerticalScroller = new UIVerticalScroller(monthsScrollingPanel, monthsButtons, monthCenter);
|
monthsVerticalScroller = new UIVerticalScroller(monthCenter, monthCenter, monthsScrollRect, monthsButtons);
|
||||||
yearsVerticalScroller = new UIVerticalScroller(yearsScrollingPanel, yearsButtons, yearsCenter);
|
yearsVerticalScroller = new UIVerticalScroller(yearsCenter, yearsCenter, yearsScrollRect, yearsButtons);
|
||||||
daysVerticalScroller = new UIVerticalScroller(daysScrollingPanel, daysButtons, daysCenter);
|
daysVerticalScroller = new UIVerticalScroller(daysCenter, daysCenter, daysScrollRect, daysButtons);
|
||||||
|
|
||||||
monthsVerticalScroller.Start();
|
monthsVerticalScroller.Start();
|
||||||
yearsVerticalScroller.Start();
|
yearsVerticalScroller.Start();
|
||||||
|
@ -177,9 +177,9 @@ namespace UnityEngine.UI.Extensions.Examples
|
||||||
yearsVerticalScroller.Update();
|
yearsVerticalScroller.Update();
|
||||||
daysVerticalScroller.Update();
|
daysVerticalScroller.Update();
|
||||||
|
|
||||||
string dayString = daysVerticalScroller.GetResults();
|
string dayString = daysVerticalScroller.result;
|
||||||
string monthString = monthsVerticalScroller.GetResults();
|
string monthString = monthsVerticalScroller.result;
|
||||||
string yearsString = yearsVerticalScroller.GetResults();
|
string yearsString = yearsVerticalScroller.result;
|
||||||
|
|
||||||
if (dayString.EndsWith("1") && dayString != "11")
|
if (dayString.EndsWith("1") && dayString != "11")
|
||||||
dayString = dayString + "st";
|
dayString = dayString + "st";
|
||||||
|
|
|
@ -10,114 +10,160 @@ namespace UnityEngine.UI.Extensions
|
||||||
[AddComponentMenu("Layout/Extensions/Vertical Scroller")]
|
[AddComponentMenu("Layout/Extensions/Vertical Scroller")]
|
||||||
public class UIVerticalScroller : MonoBehaviour
|
public class UIVerticalScroller : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Tooltip("Scrollable area (content of desired ScrollRect)")]
|
[Tooltip("desired ScrollRect")]
|
||||||
public RectTransform _scrollingPanel;
|
public ScrollRect scrollRect;
|
||||||
[Tooltip("Elements to populate inside the scroller")]
|
|
||||||
public GameObject[] _arrayOfElements;
|
|
||||||
[Tooltip("Center display area (position of zoomed content)")]
|
[Tooltip("Center display area (position of zoomed content)")]
|
||||||
public RectTransform _center;
|
public RectTransform center;
|
||||||
[Tooltip("Select the item to be in center on start. (optional)")]
|
[Tooltip("Size / spacing of elements")]
|
||||||
public int StartingIndex = -1;
|
public RectTransform elementSize;
|
||||||
|
[Tooltip("Scale = 1/ (1+distance fom center * shrinkage)")]
|
||||||
|
public Vector2 elementShrinkage = new Vector2(1f / 200, 1f / 200);
|
||||||
|
[Tooltip("Minimum element scale (furthest from center)")]
|
||||||
|
public Vector2 minScale = new Vector2(0.7f, 0.7f);
|
||||||
|
[Tooltip("Select the item to be in center on start.")]
|
||||||
|
public int startingIndex = -1;
|
||||||
|
[Tooltip("Stop scrolling past last element from inertia.")]
|
||||||
|
public bool stopMomentumOnEnd = true;
|
||||||
|
[Tooltip("Set Items out of center to not interactible.")]
|
||||||
|
public bool disableUnfocused = true;
|
||||||
[Tooltip("Button to go to the next page. (optional)")]
|
[Tooltip("Button to go to the next page. (optional)")]
|
||||||
public GameObject ScrollUpButton;
|
public GameObject scrollUpButton;
|
||||||
[Tooltip("Button to go to the previous page. (optional)")]
|
[Tooltip("Button to go to the previous page. (optional)")]
|
||||||
public GameObject ScrollDownButton;
|
public GameObject scrollDownButton;
|
||||||
[Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
|
[Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
|
||||||
public UnityEvent<int> ButtonClicked;
|
public IntEvent OnButtonClicked;
|
||||||
|
[Tooltip("Event fired when the focused item is Changed. (optional)")]
|
||||||
|
public IntEvent OnFocusChanged;
|
||||||
|
[HideInInspector]
|
||||||
|
public GameObject[] _arrayOfElements;
|
||||||
|
|
||||||
|
public int focusedElementIndex { get; private set; }
|
||||||
|
|
||||||
|
public string result { get; private set; }
|
||||||
|
|
||||||
private float[] distReposition;
|
private float[] distReposition;
|
||||||
private float[] distance;
|
private float[] distance;
|
||||||
//private int elementsDistance;
|
//private int elementsDistance;
|
||||||
private int minElementsNum;
|
|
||||||
private int elementLength;
|
|
||||||
//private int elementHalfLength;
|
|
||||||
private float deltaY;
|
|
||||||
private string result;
|
|
||||||
|
|
||||||
public UIVerticalScroller() { }
|
|
||||||
|
|
||||||
public UIVerticalScroller(RectTransform scrollingPanel, GameObject[] arrayOfElements, RectTransform center)
|
//Scrollable area (content of desired ScrollRect)
|
||||||
|
[HideInInspector]
|
||||||
|
public RectTransform scrollingPanel{ get { return scrollRect.content; } }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor when not used as component but called from other script, don't forget to set the non-optional properties.
|
||||||
|
/// </summary>
|
||||||
|
public UIVerticalScroller()
|
||||||
{
|
{
|
||||||
_scrollingPanel = scrollingPanel;
|
|
||||||
_arrayOfElements = arrayOfElements;
|
|
||||||
_center = center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor when not used as component but called from other script
|
||||||
|
/// </summary>
|
||||||
|
public UIVerticalScroller(RectTransform center, RectTransform elementSize, ScrollRect scrollRect, GameObject[] arrayOfElements)
|
||||||
|
{
|
||||||
|
this.center = center;
|
||||||
|
this.elementSize = elementSize;
|
||||||
|
this.scrollRect = scrollRect;
|
||||||
|
_arrayOfElements = arrayOfElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Awake this instance.
|
||||||
|
/// </summary>
|
||||||
public void Awake()
|
public void Awake()
|
||||||
{
|
{
|
||||||
var scrollRect = GetComponent<ScrollRect>();
|
if (!scrollRect)
|
||||||
if (!_scrollingPanel)
|
|
||||||
{
|
{
|
||||||
_scrollingPanel = scrollRect.content;
|
scrollRect = GetComponent<ScrollRect>();
|
||||||
}
|
}
|
||||||
if (!_center)
|
if (!center)
|
||||||
{
|
{
|
||||||
Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
|
Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
|
||||||
}
|
}
|
||||||
|
if (!elementSize)
|
||||||
|
{
|
||||||
|
elementSize = center;
|
||||||
|
}
|
||||||
if (_arrayOfElements == null || _arrayOfElements.Length == 0)
|
if (_arrayOfElements == null || _arrayOfElements.Length == 0)
|
||||||
{
|
{
|
||||||
var childCount = scrollRect.content.childCount;
|
_arrayOfElements = new GameObject[scrollingPanel.childCount];
|
||||||
if (childCount > 0)
|
for (int i = 0; i < scrollingPanel.childCount; i++)
|
||||||
{
|
{
|
||||||
_arrayOfElements = new GameObject[childCount];
|
_arrayOfElements[i] = scrollingPanel.GetChild(i).gameObject;
|
||||||
for (int i = 0; i < childCount; i++)
|
}
|
||||||
{
|
}
|
||||||
_arrayOfElements[i] = scrollRect.content.GetChild(i).gameObject;
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recognises and resizes the children.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startingIndex">Starting index.</param>
|
||||||
|
/// <param name="arrayOfElements">Array of elements.</param>
|
||||||
|
public void updateChildren(int startingIndex = -1, GameObject[] arrayOfElements = null)
|
||||||
|
{
|
||||||
|
// Set _arrayOfElements to arrayOfElements if given, otherwise to child objects of the scrolling panel.
|
||||||
|
if (arrayOfElements != null)
|
||||||
|
{
|
||||||
|
_arrayOfElements = arrayOfElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_arrayOfElements = new GameObject[scrollingPanel.childCount];
|
||||||
|
for (int i = 0; i < scrollingPanel.childCount; i++)
|
||||||
|
{
|
||||||
|
_arrayOfElements[i] = scrollingPanel.GetChild(i).gameObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resize the elements to match elementSize rect
|
||||||
|
for (var i = 0; i < _arrayOfElements.Length; i++)
|
||||||
|
{
|
||||||
|
int j = i;
|
||||||
|
_arrayOfElements[i].GetComponent<Button>().onClick.RemoveAllListeners();
|
||||||
|
if (OnButtonClicked != null)
|
||||||
|
{
|
||||||
|
_arrayOfElements[i].GetComponent<Button>().onClick.AddListener(() => OnButtonClicked.Invoke(j));
|
||||||
|
}
|
||||||
|
RectTransform r = _arrayOfElements[i].GetComponent<RectTransform>();
|
||||||
|
r.anchorMax = r.anchorMin = r.pivot = new Vector2(0.5f, 0.5f);
|
||||||
|
r.localPosition = new Vector2(0, i * elementSize.rect.size.y);
|
||||||
|
r.sizeDelta = elementSize.rect.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare for scrolling
|
||||||
|
distance = new float[_arrayOfElements.Length];
|
||||||
|
distReposition = new float[_arrayOfElements.Length];
|
||||||
|
focusedElementIndex = -1;
|
||||||
|
|
||||||
|
//scrollRect.scrollSensitivity = elementSize.rect.height / 5;
|
||||||
|
|
||||||
|
// if starting index is given, snap to respective element
|
||||||
|
if (startingIndex > -1)
|
||||||
|
{
|
||||||
|
startingIndex = startingIndex > _arrayOfElements.Length ? _arrayOfElements.Length - 1 : startingIndex;
|
||||||
|
SnapToElement(startingIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if (_arrayOfElements.Length < 1)
|
|
||||||
{
|
|
||||||
Debug.Log("No child content found, exiting..");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
elementLength = _arrayOfElements.Length;
|
if (scrollUpButton)
|
||||||
distance = new float[elementLength];
|
scrollUpButton.GetComponent<Button>().onClick.AddListener(() =>
|
||||||
distReposition = new float[elementLength];
|
{
|
||||||
|
ScrollUp();
|
||||||
|
});
|
||||||
|
|
||||||
//get distance between buttons
|
if (scrollDownButton)
|
||||||
//elementsDistance = (int)Mathf.Abs(_arrayOfElements[1].GetComponent<RectTransform>().anchoredPosition.y - _arrayOfElements[0].GetComponent<RectTransform>().anchoredPosition.y);
|
scrollDownButton.GetComponent<Button>().onClick.AddListener(() =>
|
||||||
deltaY = _arrayOfElements[0].GetComponent<RectTransform>().rect.height * elementLength / 3 * 2;
|
{
|
||||||
Vector2 startPosition = new Vector2(_scrollingPanel.anchoredPosition.x, -deltaY);
|
ScrollDown();
|
||||||
_scrollingPanel.anchoredPosition = startPosition;
|
});
|
||||||
|
updateChildren(startingIndex, _arrayOfElements);
|
||||||
for (var i = 0; i < _arrayOfElements.Length; i++)
|
|
||||||
{
|
|
||||||
AddListener(_arrayOfElements[i], i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ScrollUpButton)
|
|
||||||
ScrollUpButton.GetComponent<Button>().onClick.AddListener(() => { ScrollUp(); });
|
|
||||||
|
|
||||||
if (ScrollDownButton)
|
|
||||||
ScrollDownButton.GetComponent<Button>().onClick.AddListener(() => { ScrollDown(); });
|
|
||||||
|
|
||||||
if (StartingIndex > -1)
|
|
||||||
{
|
|
||||||
StartingIndex = StartingIndex > _arrayOfElements.Length ? _arrayOfElements.Length - 1 : StartingIndex;
|
|
||||||
SnapToElement(StartingIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddListener(GameObject button, int index)
|
|
||||||
{
|
|
||||||
button.GetComponent<Button>().onClick.AddListener(() => DoSomething(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoSomething(int index)
|
|
||||||
{
|
|
||||||
if (ButtonClicked != null)
|
|
||||||
{
|
|
||||||
ButtonClicked.Invoke(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
@ -126,63 +172,83 @@ namespace UnityEngine.UI.Extensions
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < elementLength; i++)
|
for (var i = 0; i < _arrayOfElements.Length; i++)
|
||||||
{
|
{
|
||||||
distReposition[i] = _center.GetComponent<RectTransform>().position.y - _arrayOfElements[i].GetComponent<RectTransform>().position.y;
|
distReposition[i] = center.GetComponent<RectTransform>().position.y - _arrayOfElements[i].GetComponent<RectTransform>().position.y;
|
||||||
distance[i] = Mathf.Abs(distReposition[i]);
|
distance[i] = Mathf.Abs(distReposition[i]);
|
||||||
|
|
||||||
//Magnifying effect
|
//Magnifying effect
|
||||||
float scale = Mathf.Max(0.7f, 1 / (1 + distance[i] / 200));
|
Vector2 scale = Vector2.Max(minScale, new Vector2(1 / (1 + distance[i] * elementShrinkage.x), (1 / (1 + distance[i] * elementShrinkage.y))));
|
||||||
_arrayOfElements[i].GetComponent<RectTransform>().transform.localScale = new Vector3(scale, scale, 1f);
|
_arrayOfElements[i].GetComponent<RectTransform>().transform.localScale = new Vector3(scale.x, scale.y, 1f);
|
||||||
}
|
}
|
||||||
float minDistance = Mathf.Min(distance);
|
|
||||||
|
|
||||||
for (var i = 0; i < elementLength; i++)
|
// detect focused element
|
||||||
|
float minDistance = Mathf.Min(distance);
|
||||||
|
int oldFocusedElement = focusedElementIndex;
|
||||||
|
for (var i = 0; i < _arrayOfElements.Length; i++)
|
||||||
{
|
{
|
||||||
_arrayOfElements[i].GetComponent<CanvasGroup>().interactable = false;
|
_arrayOfElements[i].GetComponent<CanvasGroup>().interactable = !disableUnfocused || minDistance == distance[i];
|
||||||
if (minDistance == distance[i])
|
if (minDistance == distance[i])
|
||||||
{
|
{
|
||||||
minElementsNum = i;
|
focusedElementIndex = i;
|
||||||
_arrayOfElements[i].GetComponent<CanvasGroup>().interactable = true;
|
|
||||||
result = _arrayOfElements[i].GetComponentInChildren<Text>().text;
|
result = _arrayOfElements[i].GetComponentInChildren<Text>().text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (focusedElementIndex != oldFocusedElement && OnFocusChanged != null)
|
||||||
|
{
|
||||||
|
OnFocusChanged.Invoke(focusedElementIndex);
|
||||||
|
}
|
||||||
|
|
||||||
ScrollingElements(-_arrayOfElements[minElementsNum].GetComponent<RectTransform>().anchoredPosition.y);
|
|
||||||
|
if (!Input.GetMouseButton(0))
|
||||||
|
{
|
||||||
|
// scroll slowly to nearest element when not dragged
|
||||||
|
ScrollingElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// stop scrolling past last element from inertia
|
||||||
|
if (stopMomentumOnEnd
|
||||||
|
&& (_arrayOfElements[0].GetComponent<RectTransform>().position.y > center.position.y
|
||||||
|
|| _arrayOfElements[_arrayOfElements.Length - 1].GetComponent<RectTransform>().position.y < center.position.y))
|
||||||
|
{
|
||||||
|
scrollRect.velocity = Vector2.zero;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ScrollingElements(float position)
|
private void ScrollingElements()
|
||||||
{
|
{
|
||||||
float newY = Mathf.Lerp(_scrollingPanel.anchoredPosition.y, position, Time.deltaTime * 1f);
|
float newY = Mathf.Lerp(scrollingPanel.anchoredPosition.y, scrollingPanel.anchoredPosition.y + distReposition[focusedElementIndex], Time.deltaTime * 2f);
|
||||||
Vector2 newPosition = new Vector2(_scrollingPanel.anchoredPosition.x, newY);
|
Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, newY);
|
||||||
_scrollingPanel.anchoredPosition = newPosition;
|
scrollingPanel.anchoredPosition = newPosition;
|
||||||
}
|
|
||||||
|
|
||||||
public string GetResults()
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SnapToElement(int element)
|
public void SnapToElement(int element)
|
||||||
{
|
{
|
||||||
float deltaElementPositionY = _arrayOfElements[0].GetComponent<RectTransform>().rect.height * element;
|
float deltaElementPositionY = elementSize.rect.height * element;
|
||||||
Vector2 newPosition = new Vector2(_scrollingPanel.anchoredPosition.x, -deltaElementPositionY);
|
Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, -deltaElementPositionY);
|
||||||
_scrollingPanel.anchoredPosition = newPosition;
|
scrollingPanel.anchoredPosition = newPosition;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScrollUp()
|
public void ScrollUp()
|
||||||
{
|
{
|
||||||
float deltaUp = _arrayOfElements[0].GetComponent<RectTransform>().rect.height / 1.2f;
|
float deltaUp = elementSize.rect.height / 1.2f;
|
||||||
Vector2 newPositionUp = new Vector2(_scrollingPanel.anchoredPosition.x, _scrollingPanel.anchoredPosition.y - deltaUp);
|
Vector2 newPositionUp = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y - deltaUp);
|
||||||
_scrollingPanel.anchoredPosition = Vector2.Lerp(_scrollingPanel.anchoredPosition, newPositionUp, 1);
|
scrollingPanel.anchoredPosition = Vector2.Lerp(scrollingPanel.anchoredPosition, newPositionUp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScrollDown()
|
public void ScrollDown()
|
||||||
{
|
{
|
||||||
float deltaDown = _arrayOfElements[0].GetComponent<RectTransform>().rect.height / 1.2f;
|
float deltaDown = elementSize.rect.height / 1.2f;
|
||||||
Vector2 newPositionDown = new Vector2(_scrollingPanel.anchoredPosition.x, _scrollingPanel.anchoredPosition.y + deltaDown);
|
Vector2 newPositionDown = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y + deltaDown);
|
||||||
_scrollingPanel.anchoredPosition = newPositionDown;
|
scrollingPanel.anchoredPosition = newPositionDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class IntEvent:UnityEvent<int>
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue