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 not
pull/413/head
LARS-LAPTOP2\larsme 2019-02-22 18:05:03 +01:00
parent ff47f703c0
commit cee50a6d63
4 changed files with 231 additions and 162 deletions

View File

@ -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>();

View File

@ -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:

View File

@ -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";

View File

@ -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)
if (scrollUpButton)
scrollUpButton.GetComponent<Button>().onClick.AddListener(() =>
{ {
Debug.Log("No child content found, exiting.."); ScrollUp();
return; });
}
elementLength = _arrayOfElements.Length; if (scrollDownButton)
distance = new float[elementLength]; scrollDownButton.GetComponent<Button>().onClick.AddListener(() =>
distReposition = new float[elementLength];
//get distance between buttons
//elementsDistance = (int)Mathf.Abs(_arrayOfElements[1].GetComponent<RectTransform>().anchoredPosition.y - _arrayOfElements[0].GetComponent<RectTransform>().anchoredPosition.y);
deltaY = _arrayOfElements[0].GetComponent<RectTransform>().rect.height * elementLength / 3 * 2;
Vector2 startPosition = new Vector2(_scrollingPanel.anchoredPosition.x, -deltaY);
_scrollingPanel.anchoredPosition = startPosition;
for (var i = 0; i < _arrayOfElements.Length; i++)
{ {
AddListener(_arrayOfElements[i], i); ScrollDown();
});
updateChildren(startingIndex, _arrayOfElements);
} }
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)
ScrollingElements(-_arrayOfElements[minElementsNum].GetComponent<RectTransform>().anchoredPosition.y); {
OnFocusChanged.Invoke(focusedElementIndex);
} }
private void ScrollingElements(float position)
if (!Input.GetMouseButton(0))
{ {
float newY = Mathf.Lerp(_scrollingPanel.anchoredPosition.y, position, Time.deltaTime * 1f); // scroll slowly to nearest element when not dragged
Vector2 newPosition = new Vector2(_scrollingPanel.anchoredPosition.x, newY); ScrollingElements();
_scrollingPanel.anchoredPosition = newPosition;
} }
public string GetResults()
// 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))
{ {
return result; scrollRect.velocity = Vector2.zero;
}
}
private void ScrollingElements()
{
float newY = Mathf.Lerp(scrollingPanel.anchoredPosition.y, scrollingPanel.anchoredPosition.y + distReposition[focusedElementIndex], Time.deltaTime * 2f);
Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, newY);
scrollingPanel.anchoredPosition = newPosition;
} }
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>
{
} }
} }
} }