parent
0c68f929f6
commit
1bb60d72b4
|
@ -9,7 +9,6 @@
|
||||||
/// if you dont wish to use this auto resize turn of autoLayoutItems
|
/// if you dont wish to use this auto resize turn of autoLayoutItems
|
||||||
/// - fixed current page made it independant from pivot
|
/// - fixed current page made it independant from pivot
|
||||||
/// - replaced pagination with delegate function
|
/// - replaced pagination with delegate function
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
|
@ -22,10 +21,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
// needed becouse of reversed behavior of axis Y compared to X
|
// needed becouse of reversed behavior of axis Y compared to X
|
||||||
// (positions of children lower in children list in horizontal directions grows when in vertical it gets smaller)
|
// (positions of children lower in children list in horizontal directions grows when in vertical it gets smaller)
|
||||||
public enum ScrollDirection {
|
public enum ScrollDirection
|
||||||
|
{
|
||||||
Horizontal,
|
Horizontal,
|
||||||
Vertical
|
Vertical
|
||||||
};
|
}
|
||||||
|
|
||||||
public delegate void PageSnapChange(int page);
|
public delegate void PageSnapChange(int page);
|
||||||
|
|
||||||
|
@ -34,11 +34,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
public ScrollDirection direction = ScrollDirection.Horizontal;
|
public ScrollDirection direction = ScrollDirection.Horizontal;
|
||||||
|
|
||||||
protected ScrollRect scrollRect;
|
protected ScrollRect scrollRect;
|
||||||
protected RectTransform scrollRectTransform;
|
|
||||||
protected Transform listContainerTransform;
|
|
||||||
protected RectTransform rectTransform;
|
|
||||||
|
|
||||||
protected int items = 0;
|
protected RectTransform scrollRectTransform;
|
||||||
|
|
||||||
|
protected Transform listContainerTransform;
|
||||||
|
|
||||||
|
protected RectTransform rectTransform;
|
||||||
|
|
||||||
int pages;
|
int pages;
|
||||||
|
|
||||||
|
@ -46,22 +47,31 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
// anchor points to lerp to to see child on certain indexes
|
// anchor points to lerp to to see child on certain indexes
|
||||||
protected Vector3[] pageAnchorPositions;
|
protected Vector3[] pageAnchorPositions;
|
||||||
|
|
||||||
protected Vector3 lerpTarget;
|
protected Vector3 lerpTarget;
|
||||||
|
|
||||||
protected bool lerp;
|
protected bool lerp;
|
||||||
|
|
||||||
// item list related
|
// item list related
|
||||||
protected float listContainerMinPosition;
|
protected float listContainerMinPosition;
|
||||||
|
|
||||||
protected float listContainerMaxPosition;
|
protected float listContainerMaxPosition;
|
||||||
|
|
||||||
protected float listContainerSize;
|
protected float listContainerSize;
|
||||||
|
|
||||||
protected RectTransform listContainerRectTransform;
|
protected RectTransform listContainerRectTransform;
|
||||||
|
|
||||||
protected Vector2 listContainerCachedSize;
|
protected Vector2 listContainerCachedSize;
|
||||||
|
|
||||||
protected float itemSize;
|
protected float itemSize;
|
||||||
|
|
||||||
|
protected int itemsCount = 0;
|
||||||
|
|
||||||
[Tooltip("Button to go to the next page. (optional)")]
|
[Tooltip("Button to go to the next page. (optional)")]
|
||||||
public GameObject nextButton;
|
public Button nextButton;
|
||||||
|
|
||||||
[Tooltip("Button to go to the previous page. (optional)")]
|
[Tooltip("Button to go to the previous page. (optional)")]
|
||||||
public GameObject prevButton;
|
public Button prevButton;
|
||||||
|
|
||||||
[Tooltip("Number of items visible in one page of scroll frame.")]
|
[Tooltip("Number of items visible in one page of scroll frame.")]
|
||||||
[RangeAttribute(1,100)]
|
[RangeAttribute(1,100)]
|
||||||
|
@ -73,73 +83,96 @@ namespace UnityEngine.UI.Extensions
|
||||||
[Tooltip("If you wish to update scrollbar numberOfSteps to number of active children on list.")]
|
[Tooltip("If you wish to update scrollbar numberOfSteps to number of active children on list.")]
|
||||||
public bool linkScrolbarSteps = false;
|
public bool linkScrolbarSteps = false;
|
||||||
|
|
||||||
|
[Tooltip("If you wish to update scrollrect sensitivity to size of list element.")]
|
||||||
|
public bool linkScrolrectScrollSensitivity = false;
|
||||||
|
|
||||||
public Boolean useFastSwipe = true;
|
public Boolean useFastSwipe = true;
|
||||||
|
|
||||||
public int fastSwipeThreshold = 100;
|
public int fastSwipeThreshold = 100;
|
||||||
|
|
||||||
// drag related
|
// drag related
|
||||||
protected bool startDrag = true;
|
protected bool startDrag = true;
|
||||||
|
|
||||||
protected Vector3 positionOnDragStart = new Vector3();
|
protected Vector3 positionOnDragStart = new Vector3();
|
||||||
|
|
||||||
protected int pageOnDragStart;
|
protected int pageOnDragStart;
|
||||||
|
|
||||||
protected bool fastSwipeTimer = false;
|
protected bool fastSwipeTimer = false;
|
||||||
|
|
||||||
protected int fastSwipeCounter = 0;
|
protected int fastSwipeCounter = 0;
|
||||||
|
|
||||||
protected int fastSwipeTarget = 10;
|
protected int fastSwipeTarget = 10;
|
||||||
|
|
||||||
// Use this for initialization
|
// Use this for initialization
|
||||||
void Start()
|
void Awake()
|
||||||
{
|
{
|
||||||
lerp = false;
|
lerp = false;
|
||||||
|
|
||||||
scrollRect = gameObject.GetComponent<ScrollRect> ();
|
scrollRect = gameObject.GetComponent<ScrollRect>();
|
||||||
scrollRectTransform = gameObject.GetComponent<RectTransform> ();
|
scrollRectTransform = gameObject.GetComponent<RectTransform>();
|
||||||
listContainerTransform = scrollRect.content;
|
listContainerTransform = scrollRect.content;
|
||||||
listContainerRectTransform = listContainerTransform.GetComponent<RectTransform> ();
|
listContainerRectTransform = listContainerTransform.GetComponent<RectTransform>();
|
||||||
|
|
||||||
rectTransform = listContainerTransform.gameObject.GetComponent<RectTransform> ();
|
rectTransform = listContainerTransform.gameObject.GetComponent<RectTransform>();
|
||||||
UpdateListItemsSize();
|
UpdateListItemsSize();
|
||||||
UpdateListItemPositions();
|
UpdateListItemPositions();
|
||||||
|
|
||||||
ChangePage (CurrentPage ());
|
ChangePage(CurrentPage());
|
||||||
|
|
||||||
if (nextButton)
|
if (nextButton)
|
||||||
{
|
{
|
||||||
nextButton.GetComponent<Button> ().onClick.AddListener (() => { NextScreen (); });
|
nextButton.GetComponent<Button>().onClick.AddListener(() => {
|
||||||
|
NextScreen(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevButton)
|
if (prevButton)
|
||||||
{
|
{
|
||||||
prevButton.GetComponent<Button> ().onClick.AddListener (() => { PreviousScreen (); });
|
prevButton.GetComponent<Button>().onClick.AddListener(() => {
|
||||||
|
PreviousScreen(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
Awake();
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateListItemsSize()
|
public void UpdateListItemsSize()
|
||||||
{
|
{
|
||||||
float size = 0;
|
float size = 0;
|
||||||
|
float currentSize = 0;
|
||||||
if (direction == ScrollSnap.ScrollDirection.Horizontal)
|
if (direction == ScrollSnap.ScrollDirection.Horizontal)
|
||||||
{
|
{
|
||||||
size = scrollRectTransform.rect.width / itemsVisibleAtOnce;
|
size = scrollRectTransform.rect.width / itemsVisibleAtOnce;
|
||||||
|
currentSize = listContainerRectTransform.rect.width / itemsCount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size = scrollRectTransform.rect.height / itemsVisibleAtOnce;
|
size = scrollRectTransform.rect.height / itemsVisibleAtOnce;
|
||||||
|
currentSize = listContainerRectTransform.rect.height / itemsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemSize = size;
|
itemSize = size;
|
||||||
|
|
||||||
if (autoLayoutItems && size != itemSize)
|
if (linkScrolrectScrollSensitivity)
|
||||||
|
{
|
||||||
|
scrollRect.scrollSensitivity = itemSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoLayoutItems && currentSize != size && itemsCount > 0)
|
||||||
{
|
{
|
||||||
if (direction == ScrollSnap.ScrollDirection.Horizontal)
|
if (direction == ScrollSnap.ScrollDirection.Horizontal)
|
||||||
{
|
{
|
||||||
foreach (var tr in listContainerTransform)
|
foreach (var tr in listContainerTransform)
|
||||||
{
|
{
|
||||||
GameObject child = ((Transform)tr).gameObject;
|
GameObject child = ((Transform) tr).gameObject;
|
||||||
if (child.activeInHierarchy)
|
if (child.activeInHierarchy)
|
||||||
{
|
{
|
||||||
var childLayout = child.GetComponent<LayoutElement> ();
|
var childLayout = child.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
if (childLayout == null)
|
if (childLayout == null)
|
||||||
{
|
{
|
||||||
childLayout = child.AddComponent<LayoutElement> ();
|
childLayout = child.AddComponent<LayoutElement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
childLayout.minWidth = itemSize;
|
childLayout.minWidth = itemSize;
|
||||||
|
@ -150,14 +183,14 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
foreach (var tr in listContainerTransform)
|
foreach (var tr in listContainerTransform)
|
||||||
{
|
{
|
||||||
GameObject child = ((Transform)tr).gameObject;
|
GameObject child = ((Transform) tr).gameObject;
|
||||||
if (child.activeInHierarchy)
|
if (child.activeInHierarchy)
|
||||||
{
|
{
|
||||||
var childLayout = child.GetComponent<LayoutElement> ();
|
var childLayout = child.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
if (childLayout == null)
|
if (childLayout == null)
|
||||||
{
|
{
|
||||||
childLayout = child.AddComponent<LayoutElement> ();
|
childLayout = child.AddComponent<LayoutElement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
childLayout.minHeight = itemSize;
|
childLayout.minHeight = itemSize;
|
||||||
|
@ -174,22 +207,25 @@ namespace UnityEngine.UI.Extensions
|
||||||
// checking how many children of list are active
|
// checking how many children of list are active
|
||||||
int activeCount = 0;
|
int activeCount = 0;
|
||||||
|
|
||||||
foreach (var tr in listContainerTransform) {
|
foreach (var tr in listContainerTransform)
|
||||||
if (((Transform)tr).gameObject.activeInHierarchy) {
|
{
|
||||||
|
if (((Transform) tr).gameObject.activeInHierarchy)
|
||||||
|
{
|
||||||
activeCount++;
|
activeCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if anything changed since last check reinitialize anchors list
|
// if anything changed since last check reinitialize anchors list
|
||||||
items = 0;
|
itemsCount = 0;
|
||||||
Array.Resize(ref pageAnchorPositions, activeCount);
|
Array.Resize(ref pageAnchorPositions, activeCount);
|
||||||
|
|
||||||
if (activeCount > 0)
|
if (activeCount > 0)
|
||||||
{
|
{
|
||||||
pages = Mathf.Max (activeCount - itemsVisibleAtOnce + 1, 1);
|
pages = Mathf.Max(activeCount - itemsVisibleAtOnce + 1, 1);
|
||||||
|
|
||||||
if (direction == ScrollDirection.Horizontal)
|
if (direction == ScrollDirection.Horizontal)
|
||||||
{
|
{
|
||||||
|
//Debug.Log ("-------------looking for list spanning range----------------");
|
||||||
// looking for list spanning range min/max
|
// looking for list spanning range min/max
|
||||||
scrollRect.horizontalNormalizedPosition = 0;
|
scrollRect.horizontalNormalizedPosition = 0;
|
||||||
listContainerMaxPosition = listContainerTransform.localPosition.x;
|
listContainerMaxPosition = listContainerTransform.localPosition.x;
|
||||||
|
@ -197,6 +233,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
listContainerMinPosition = listContainerTransform.localPosition.x;
|
listContainerMinPosition = listContainerTransform.localPosition.x;
|
||||||
|
|
||||||
listContainerSize = listContainerMaxPosition - listContainerMinPosition;
|
listContainerSize = listContainerMaxPosition - listContainerMinPosition;
|
||||||
|
//itemSize = pages > 1 ? listContainerSize / (float)(pages - 1) : listContainerSize / activeCount;
|
||||||
|
//itemSize *= (pages + itemsVisibleAtOnce) / (pages + 1);
|
||||||
|
|
||||||
for (var i = 0; i < pages; i ++)
|
for (var i = 0; i < pages; i ++)
|
||||||
{
|
{
|
||||||
|
@ -206,9 +244,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
listContainerTransform.localPosition.z
|
listContainerTransform.localPosition.z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Debug.Log (String.Format("min:{0:0.0}, max:{1:0.0}, pages: {2:0}, width: {3:0}", listContainerMinPosition, listContainerMaxPosition, pages, listContainerSize/pages));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//Debug.Log ("-------------looking for list spanning range----------------");
|
||||||
// looking for list spanning range
|
// looking for list spanning range
|
||||||
scrollRect.verticalNormalizedPosition = 1;
|
scrollRect.verticalNormalizedPosition = 1;
|
||||||
listContainerMinPosition = listContainerTransform.localPosition.y;
|
listContainerMinPosition = listContainerTransform.localPosition.y;
|
||||||
|
@ -216,6 +257,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
listContainerMaxPosition = listContainerTransform.localPosition.y;
|
listContainerMaxPosition = listContainerTransform.localPosition.y;
|
||||||
|
|
||||||
listContainerSize = listContainerMaxPosition - listContainerMinPosition;
|
listContainerSize = listContainerMaxPosition - listContainerMinPosition;
|
||||||
|
//itemSize = pages > 1 ? listContainerSize / (float)(pages - 1) : listContainerSize / activeCount;
|
||||||
|
//itemSize *= (pages + itemsVisibleAtOnce) / (pages + 1);
|
||||||
|
|
||||||
for (var i = 0; i < pages; i ++)
|
for (var i = 0; i < pages; i ++)
|
||||||
{
|
{
|
||||||
|
@ -224,22 +267,24 @@ namespace UnityEngine.UI.Extensions
|
||||||
listContainerMinPosition + itemSize * i,
|
listContainerMinPosition + itemSize * i,
|
||||||
listContainerTransform.localPosition.z
|
listContainerTransform.localPosition.z
|
||||||
);
|
);
|
||||||
|
//Debug.Log (String.Format("pos[{0:0}]={1} {2:0%}", i, pageAnchorPositions[i], pages > 1 ? i/(float)(pages-1) : (float)i));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var tr in listContainerTransform) {
|
//Debug.Log (String.Format("min:{0:0.0}, max:{1:0.0}, pages: {2:0}, width: {3:0}", listContainerMinPosition, listContainerMaxPosition, pages, listContainerSize/pages));
|
||||||
if (((Transform)tr).gameObject.activeInHierarchy) {
|
|
||||||
activeCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateScrollbar(linkScrolbarSteps);
|
UpdateScrollbar(linkScrolbarSteps);
|
||||||
startingPage = Mathf.Min(startingPage, pages);
|
startingPage = Mathf.Min(startingPage, pages);
|
||||||
ResetPage();
|
ResetPage();
|
||||||
}
|
}
|
||||||
items = activeCount;
|
|
||||||
listContainerCachedSize.Set (listContainerRectTransform.rect.size.x, listContainerRectTransform.rect.size.y);
|
if (itemsCount != activeCount)
|
||||||
|
{
|
||||||
|
ChangePage(CurrentPage());
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsCount = activeCount;
|
||||||
|
listContainerCachedSize.Set(listContainerRectTransform.rect.size.x, listContainerRectTransform.rect.size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -248,11 +293,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
if (direction == ScrollDirection.Horizontal)
|
if (direction == ScrollDirection.Horizontal)
|
||||||
{
|
{
|
||||||
scrollRect.horizontalNormalizedPosition = pages > 1 ? (float)startingPage / (float)(pages - 1) : 0;
|
scrollRect.horizontalNormalizedPosition = pages > 1 ? (float) startingPage / (float) (pages - 1) : 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scrollRect.verticalNormalizedPosition = pages > 1 ? (float)(pages - startingPage - 1) / (float)(pages - 1) : 0;
|
scrollRect.verticalNormalizedPosition = pages > 1 ? (float) (pages - startingPage - 1) / (float) (pages - 1) : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +339,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void LateUpdate()
|
||||||
{
|
{
|
||||||
UpdateListItemsSize();
|
UpdateListItemsSize();
|
||||||
UpdateListItemPositions();
|
UpdateListItemPositions();
|
||||||
|
@ -311,6 +356,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
lerp = false;
|
lerp = false;
|
||||||
|
|
||||||
UpdateScrollbar(linkScrolbarSteps);
|
UpdateScrollbar(linkScrolbarSteps);
|
||||||
|
|
||||||
|
//Debug.Log(String.Format("Lerp: {0}/{1} page: {2:0}", lerpTarget, listContainerTransform.localPosition, CurrentPage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//change the info bullets at the bottom of the screen. Just for visual effect
|
//change the info bullets at the bottom of the screen. Just for visual effect
|
||||||
|
@ -324,6 +371,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
fastSwipeCounter++;
|
fastSwipeCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Debug.Log(String.Format("Update: {0}", listContainerTransform.localPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool fastSwipe = false; //to determine if a fast swipe was performed
|
private bool fastSwipe = false; //to determine if a fast swipe was performed
|
||||||
|
@ -332,7 +381,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
//Function for switching screens with buttons
|
//Function for switching screens with buttons
|
||||||
public void NextScreen()
|
public void NextScreen()
|
||||||
{
|
{
|
||||||
UpdateListItemPositions ();
|
UpdateListItemPositions();
|
||||||
|
|
||||||
if (CurrentPage() < pages - 1)
|
if (CurrentPage() < pages - 1)
|
||||||
{
|
{
|
||||||
|
@ -346,7 +395,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
//Function for switching screens with buttons
|
//Function for switching screens with buttons
|
||||||
public void PreviousScreen()
|
public void PreviousScreen()
|
||||||
{
|
{
|
||||||
UpdateListItemPositions ();
|
UpdateListItemPositions();
|
||||||
|
|
||||||
if (CurrentPage() > 0)
|
if (CurrentPage() > 0)
|
||||||
{
|
{
|
||||||
|
@ -404,6 +453,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
float page = pos / itemSize;
|
float page = pos / itemSize;
|
||||||
|
|
||||||
|
//Debug.Log (String.Format("min:{0:0.0}, max:{1:0.0}, current:{2:0.0}/{4:0.0}, page:{3:0.0}, target:{5}", listContainerMinPosition, listContainerMaxPosition, pos, page, listContainerTransform.localPosition.x, pageAnchorPositions[Mathf.RoundToInt(page)]));
|
||||||
|
|
||||||
return Mathf.Clamp(Mathf.RoundToInt(page), 0, pages);
|
return Mathf.Clamp(Mathf.RoundToInt(page), 0, pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,6 +463,16 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
startingPage = currentPage;
|
startingPage = currentPage;
|
||||||
|
|
||||||
|
if (nextButton)
|
||||||
|
{
|
||||||
|
nextButton.interactable = currentPage < pages - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevButton)
|
||||||
|
{
|
||||||
|
prevButton.interactable = currentPage > 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (onPageChange != null)
|
if (onPageChange != null)
|
||||||
{
|
{
|
||||||
onPageChange(currentPage);
|
onPageChange(currentPage);
|
||||||
|
@ -428,6 +489,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
positionOnDragStart = eventData.position;
|
positionOnDragStart = eventData.position;
|
||||||
pageOnDragStart = CurrentPage();
|
pageOnDragStart = CurrentPage();
|
||||||
|
|
||||||
|
//Debug.Log (String.Format("pageOnDragStart:{0:0}", pageOnDragStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnEndDrag(PointerEventData eventData)
|
public void OnEndDrag(PointerEventData eventData)
|
||||||
|
|
|
@ -1,558 +0,0 @@
|
||||||
/// Credit BinaryX
|
|
||||||
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-1945602
|
|
||||||
/// Updated by ddreaper - removed dependency on a custom ScrollRect script. Now implements drag interfaces and standard Scroll Rect.
|
|
||||||
/// Update by xesenix - rewrited almost entire code
|
|
||||||
/// - configuration for direction move instead of 2 concurrent class (easiear to change direction in editor)
|
|
||||||
/// - supports list layouted with horizontal or vertical layout need to match direction with type of layout used
|
|
||||||
/// - dynamicly checks if scrolled list size changes and recalculates anchor positions
|
|
||||||
/// and item size based on itemsVisibleAtOnce and size of root container
|
|
||||||
/// if you dont wish to use this auto resize turn of autoLayoutItems
|
|
||||||
/// - fixed current page made it independant from pivot
|
|
||||||
/// - replaced pagination with delegate function
|
|
||||||
using System;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
|
||||||
{
|
|
||||||
[ExecuteInEditMode]
|
|
||||||
[RequireComponent(typeof(ScrollRect))]
|
|
||||||
[AddComponentMenu("UI/Extensions/Scroll Snap")]
|
|
||||||
public class ScrollSnap : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
|
||||||
{
|
|
||||||
// needed becouse of reversed behavior of axis Y compared to X
|
|
||||||
// (positions of children lower in children list in horizontal directions grows when in vertical it gets smaller)
|
|
||||||
public enum ScrollDirection
|
|
||||||
{
|
|
||||||
Horizontal,
|
|
||||||
Vertical
|
|
||||||
}
|
|
||||||
|
|
||||||
public delegate void PageSnapChange(int page);
|
|
||||||
|
|
||||||
public event PageSnapChange onPageChange;
|
|
||||||
|
|
||||||
public ScrollDirection direction = ScrollDirection.Horizontal;
|
|
||||||
|
|
||||||
protected ScrollRect scrollRect;
|
|
||||||
|
|
||||||
protected RectTransform scrollRectTransform;
|
|
||||||
|
|
||||||
protected Transform listContainerTransform;
|
|
||||||
|
|
||||||
protected RectTransform rectTransform;
|
|
||||||
|
|
||||||
int pages;
|
|
||||||
|
|
||||||
protected int startingPage = 0;
|
|
||||||
|
|
||||||
// anchor points to lerp to to see child on certain indexes
|
|
||||||
protected Vector3[] pageAnchorPositions;
|
|
||||||
|
|
||||||
protected Vector3 lerpTarget;
|
|
||||||
|
|
||||||
protected bool lerp;
|
|
||||||
|
|
||||||
// item list related
|
|
||||||
protected float listContainerMinPosition;
|
|
||||||
|
|
||||||
protected float listContainerMaxPosition;
|
|
||||||
|
|
||||||
protected float listContainerSize;
|
|
||||||
|
|
||||||
protected RectTransform listContainerRectTransform;
|
|
||||||
|
|
||||||
protected Vector2 listContainerCachedSize;
|
|
||||||
|
|
||||||
protected float itemSize;
|
|
||||||
|
|
||||||
protected int itemsCount = 0;
|
|
||||||
|
|
||||||
[Tooltip("Button to go to the next page. (optional)")]
|
|
||||||
public Button nextButton;
|
|
||||||
|
|
||||||
[Tooltip("Button to go to the previous page. (optional)")]
|
|
||||||
public Button prevButton;
|
|
||||||
|
|
||||||
[Tooltip("Number of items visible in one page of scroll frame.")]
|
|
||||||
[RangeAttribute(1,100)]
|
|
||||||
public int itemsVisibleAtOnce = 1;
|
|
||||||
|
|
||||||
[Tooltip("Sets minimum width of list items to 1/itemsVisibleAtOnce.")]
|
|
||||||
public bool autoLayoutItems = true;
|
|
||||||
|
|
||||||
[Tooltip("If you wish to update scrollbar numberOfSteps to number of active children on list.")]
|
|
||||||
public bool linkScrolbarSteps = false;
|
|
||||||
|
|
||||||
[Tooltip("If you wish to update scrollrect sensitivity to size of list element.")]
|
|
||||||
public bool linkScrolrectScrollSensitivity = false;
|
|
||||||
|
|
||||||
public Boolean useFastSwipe = true;
|
|
||||||
|
|
||||||
public int fastSwipeThreshold = 100;
|
|
||||||
|
|
||||||
// drag related
|
|
||||||
protected bool startDrag = true;
|
|
||||||
|
|
||||||
protected Vector3 positionOnDragStart = new Vector3();
|
|
||||||
|
|
||||||
protected int pageOnDragStart;
|
|
||||||
|
|
||||||
protected bool fastSwipeTimer = false;
|
|
||||||
|
|
||||||
protected int fastSwipeCounter = 0;
|
|
||||||
|
|
||||||
protected int fastSwipeTarget = 10;
|
|
||||||
|
|
||||||
// Use this for initialization
|
|
||||||
void Awake()
|
|
||||||
{
|
|
||||||
lerp = false;
|
|
||||||
|
|
||||||
scrollRect = gameObject.GetComponent<ScrollRect>();
|
|
||||||
scrollRectTransform = gameObject.GetComponent<RectTransform>();
|
|
||||||
listContainerTransform = scrollRect.content;
|
|
||||||
listContainerRectTransform = listContainerTransform.GetComponent<RectTransform>();
|
|
||||||
|
|
||||||
rectTransform = listContainerTransform.gameObject.GetComponent<RectTransform>();
|
|
||||||
UpdateListItemsSize();
|
|
||||||
UpdateListItemPositions();
|
|
||||||
|
|
||||||
ChangePage(CurrentPage());
|
|
||||||
|
|
||||||
if (nextButton)
|
|
||||||
{
|
|
||||||
nextButton.GetComponent<Button>().onClick.AddListener(() => {
|
|
||||||
NextScreen(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevButton)
|
|
||||||
{
|
|
||||||
prevButton.GetComponent<Button>().onClick.AddListener(() => {
|
|
||||||
PreviousScreen(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
Awake();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateListItemsSize()
|
|
||||||
{
|
|
||||||
float size = 0;
|
|
||||||
float currentSize = 0;
|
|
||||||
if (direction == ScrollSnap.ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
size = scrollRectTransform.rect.width / itemsVisibleAtOnce;
|
|
||||||
currentSize = listContainerRectTransform.rect.width / itemsCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size = scrollRectTransform.rect.height / itemsVisibleAtOnce;
|
|
||||||
currentSize = listContainerRectTransform.rect.height / itemsCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
itemSize = size;
|
|
||||||
|
|
||||||
if (linkScrolrectScrollSensitivity)
|
|
||||||
{
|
|
||||||
scrollRect.scrollSensitivity = itemSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (autoLayoutItems && currentSize != size && itemsCount > 0)
|
|
||||||
{
|
|
||||||
if (direction == ScrollSnap.ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
foreach (var tr in listContainerTransform)
|
|
||||||
{
|
|
||||||
GameObject child = ((Transform) tr).gameObject;
|
|
||||||
if (child.activeInHierarchy)
|
|
||||||
{
|
|
||||||
var childLayout = child.GetComponent<LayoutElement>();
|
|
||||||
|
|
||||||
if (childLayout == null)
|
|
||||||
{
|
|
||||||
childLayout = child.AddComponent<LayoutElement>();
|
|
||||||
}
|
|
||||||
|
|
||||||
childLayout.minWidth = itemSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var tr in listContainerTransform)
|
|
||||||
{
|
|
||||||
GameObject child = ((Transform) tr).gameObject;
|
|
||||||
if (child.activeInHierarchy)
|
|
||||||
{
|
|
||||||
var childLayout = child.GetComponent<LayoutElement>();
|
|
||||||
|
|
||||||
if (childLayout == null)
|
|
||||||
{
|
|
||||||
childLayout = child.AddComponent<LayoutElement>();
|
|
||||||
}
|
|
||||||
|
|
||||||
childLayout.minHeight = itemSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateListItemPositions()
|
|
||||||
{
|
|
||||||
if (!listContainerRectTransform.rect.size.Equals(listContainerCachedSize))
|
|
||||||
{
|
|
||||||
// checking how many children of list are active
|
|
||||||
int activeCount = 0;
|
|
||||||
|
|
||||||
foreach (var tr in listContainerTransform)
|
|
||||||
{
|
|
||||||
if (((Transform) tr).gameObject.activeInHierarchy)
|
|
||||||
{
|
|
||||||
activeCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if anything changed since last check reinitialize anchors list
|
|
||||||
itemsCount = 0;
|
|
||||||
Array.Resize(ref pageAnchorPositions, activeCount);
|
|
||||||
|
|
||||||
if (activeCount > 0)
|
|
||||||
{
|
|
||||||
pages = Mathf.Max(activeCount - itemsVisibleAtOnce + 1, 1);
|
|
||||||
|
|
||||||
if (direction == ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
//Debug.Log ("-------------looking for list spanning range----------------");
|
|
||||||
// looking for list spanning range min/max
|
|
||||||
scrollRect.horizontalNormalizedPosition = 0;
|
|
||||||
listContainerMaxPosition = listContainerTransform.localPosition.x;
|
|
||||||
scrollRect.horizontalNormalizedPosition = 1;
|
|
||||||
listContainerMinPosition = listContainerTransform.localPosition.x;
|
|
||||||
|
|
||||||
listContainerSize = listContainerMaxPosition - listContainerMinPosition;
|
|
||||||
//itemSize = pages > 1 ? listContainerSize / (float)(pages - 1) : listContainerSize / activeCount;
|
|
||||||
//itemSize *= (pages + itemsVisibleAtOnce) / (pages + 1);
|
|
||||||
|
|
||||||
for (var i = 0; i < pages; i ++)
|
|
||||||
{
|
|
||||||
pageAnchorPositions[i] = new Vector3(
|
|
||||||
listContainerMaxPosition - itemSize * i,
|
|
||||||
listContainerTransform.localPosition.y,
|
|
||||||
listContainerTransform.localPosition.z
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Debug.Log (String.Format("min:{0:0.0}, max:{1:0.0}, pages: {2:0}, width: {3:0}", listContainerMinPosition, listContainerMaxPosition, pages, listContainerSize/pages));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Debug.Log ("-------------looking for list spanning range----------------");
|
|
||||||
// looking for list spanning range
|
|
||||||
scrollRect.verticalNormalizedPosition = 1;
|
|
||||||
listContainerMinPosition = listContainerTransform.localPosition.y;
|
|
||||||
scrollRect.verticalNormalizedPosition = 0;
|
|
||||||
listContainerMaxPosition = listContainerTransform.localPosition.y;
|
|
||||||
|
|
||||||
listContainerSize = listContainerMaxPosition - listContainerMinPosition;
|
|
||||||
//itemSize = pages > 1 ? listContainerSize / (float)(pages - 1) : listContainerSize / activeCount;
|
|
||||||
//itemSize *= (pages + itemsVisibleAtOnce) / (pages + 1);
|
|
||||||
|
|
||||||
for (var i = 0; i < pages; i ++)
|
|
||||||
{
|
|
||||||
pageAnchorPositions[i] = new Vector3(
|
|
||||||
listContainerTransform.localPosition.x,
|
|
||||||
listContainerMinPosition + itemSize * i,
|
|
||||||
listContainerTransform.localPosition.z
|
|
||||||
);
|
|
||||||
//Debug.Log (String.Format("pos[{0:0}]={1} {2:0%}", i, pageAnchorPositions[i], pages > 1 ? i/(float)(pages-1) : (float)i));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Debug.Log (String.Format("min:{0:0.0}, max:{1:0.0}, pages: {2:0}, width: {3:0}", listContainerMinPosition, listContainerMaxPosition, pages, listContainerSize/pages));
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateScrollbar(linkScrolbarSteps);
|
|
||||||
startingPage = Mathf.Min(startingPage, pages);
|
|
||||||
ResetPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemsCount != activeCount)
|
|
||||||
{
|
|
||||||
ChangePage(CurrentPage());
|
|
||||||
}
|
|
||||||
|
|
||||||
itemsCount = activeCount;
|
|
||||||
listContainerCachedSize.Set(listContainerRectTransform.rect.size.x, listContainerRectTransform.rect.size.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResetPage()
|
|
||||||
{
|
|
||||||
if (direction == ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
scrollRect.horizontalNormalizedPosition = pages > 1 ? (float) startingPage / (float) (pages - 1) : 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scrollRect.verticalNormalizedPosition = pages > 1 ? (float) (pages - startingPage - 1) / (float) (pages - 1) : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void UpdateScrollbar(bool linkSteps)
|
|
||||||
{
|
|
||||||
if (linkSteps)
|
|
||||||
{
|
|
||||||
if (direction == ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
if (scrollRect.horizontalScrollbar != null)
|
|
||||||
{
|
|
||||||
scrollRect.horizontalScrollbar.numberOfSteps = pages;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (scrollRect.verticalScrollbar != null)
|
|
||||||
{
|
|
||||||
scrollRect.verticalScrollbar.numberOfSteps = pages;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (direction == ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
if (scrollRect.horizontalScrollbar != null)
|
|
||||||
{
|
|
||||||
scrollRect.horizontalScrollbar.numberOfSteps = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (scrollRect.verticalScrollbar != null)
|
|
||||||
{
|
|
||||||
scrollRect.verticalScrollbar.numberOfSteps = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LateUpdate()
|
|
||||||
{
|
|
||||||
UpdateListItemsSize();
|
|
||||||
UpdateListItemPositions();
|
|
||||||
|
|
||||||
if (lerp)
|
|
||||||
{
|
|
||||||
UpdateScrollbar(false);
|
|
||||||
|
|
||||||
listContainerTransform.localPosition = Vector3.Lerp(listContainerTransform.localPosition, lerpTarget, 7.5f * Time.deltaTime);
|
|
||||||
|
|
||||||
if (Vector3.Distance(listContainerTransform.localPosition, lerpTarget) < 0.001f)
|
|
||||||
{
|
|
||||||
listContainerTransform.localPosition = lerpTarget;
|
|
||||||
lerp = false;
|
|
||||||
|
|
||||||
UpdateScrollbar(linkScrolbarSteps);
|
|
||||||
|
|
||||||
//Debug.Log(String.Format("Lerp: {0}/{1} page: {2:0}", lerpTarget, listContainerTransform.localPosition, CurrentPage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
//change the info bullets at the bottom of the screen. Just for visual effect
|
|
||||||
if (Vector3.Distance(listContainerTransform.localPosition, lerpTarget) < 10f)
|
|
||||||
{
|
|
||||||
ChangePage(CurrentPage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fastSwipeTimer)
|
|
||||||
{
|
|
||||||
fastSwipeCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Debug.Log(String.Format("Update: {0}", listContainerTransform.localPosition));
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool fastSwipe = false; //to determine if a fast swipe was performed
|
|
||||||
|
|
||||||
|
|
||||||
//Function for switching screens with buttons
|
|
||||||
public void NextScreen()
|
|
||||||
{
|
|
||||||
UpdateListItemPositions();
|
|
||||||
|
|
||||||
if (CurrentPage() < pages - 1)
|
|
||||||
{
|
|
||||||
lerp = true;
|
|
||||||
lerpTarget = pageAnchorPositions[CurrentPage() + 1];
|
|
||||||
|
|
||||||
ChangePage(CurrentPage() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Function for switching screens with buttons
|
|
||||||
public void PreviousScreen()
|
|
||||||
{
|
|
||||||
UpdateListItemPositions();
|
|
||||||
|
|
||||||
if (CurrentPage() > 0)
|
|
||||||
{
|
|
||||||
lerp = true;
|
|
||||||
lerpTarget = pageAnchorPositions[CurrentPage() - 1];
|
|
||||||
|
|
||||||
ChangePage(CurrentPage() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Because the CurrentScreen function is not so reliable, these are the functions used for swipes
|
|
||||||
private void NextScreenCommand()
|
|
||||||
{
|
|
||||||
if (pageOnDragStart < pages - 1)
|
|
||||||
{
|
|
||||||
int targetPage = Mathf.Min(pages - 1, pageOnDragStart + itemsVisibleAtOnce);
|
|
||||||
lerp = true;
|
|
||||||
|
|
||||||
lerpTarget = pageAnchorPositions[targetPage];
|
|
||||||
|
|
||||||
ChangePage(targetPage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Because the CurrentScreen function is not so reliable, these are the functions used for swipes
|
|
||||||
private void PrevScreenCommand()
|
|
||||||
{
|
|
||||||
if (pageOnDragStart > 0)
|
|
||||||
{
|
|
||||||
int targetPage = Mathf.Max(0, pageOnDragStart - itemsVisibleAtOnce);
|
|
||||||
lerp = true;
|
|
||||||
|
|
||||||
lerpTarget = pageAnchorPositions[targetPage];
|
|
||||||
|
|
||||||
ChangePage(targetPage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//returns the current screen that the is seeing
|
|
||||||
public int CurrentPage()
|
|
||||||
{
|
|
||||||
float pos;
|
|
||||||
|
|
||||||
if (direction == ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
pos = listContainerMaxPosition - listContainerTransform.localPosition.x;
|
|
||||||
pos = Mathf.Clamp(pos, 0, listContainerSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pos = listContainerTransform.localPosition.y - listContainerMinPosition;
|
|
||||||
pos = Mathf.Clamp(pos, 0, listContainerSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
float page = pos / itemSize;
|
|
||||||
|
|
||||||
//Debug.Log (String.Format("min:{0:0.0}, max:{1:0.0}, current:{2:0.0}/{4:0.0}, page:{3:0.0}, target:{5}", listContainerMinPosition, listContainerMaxPosition, pos, page, listContainerTransform.localPosition.x, pageAnchorPositions[Mathf.RoundToInt(page)]));
|
|
||||||
|
|
||||||
return Mathf.Clamp(Mathf.RoundToInt(page), 0, pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
//changes the bullets on the bottom of the page - pagination
|
|
||||||
private void ChangePage(int currentPage)
|
|
||||||
{
|
|
||||||
startingPage = currentPage;
|
|
||||||
|
|
||||||
if (nextButton)
|
|
||||||
{
|
|
||||||
nextButton.interactable = currentPage < pages - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevButton)
|
|
||||||
{
|
|
||||||
prevButton.interactable = currentPage > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onPageChange != null)
|
|
||||||
{
|
|
||||||
onPageChange(currentPage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Interfaces
|
|
||||||
public void OnBeginDrag(PointerEventData eventData)
|
|
||||||
{
|
|
||||||
UpdateScrollbar(false);
|
|
||||||
|
|
||||||
fastSwipeCounter = 0;
|
|
||||||
fastSwipeTimer = true;
|
|
||||||
|
|
||||||
positionOnDragStart = eventData.position;
|
|
||||||
pageOnDragStart = CurrentPage();
|
|
||||||
|
|
||||||
//Debug.Log (String.Format("pageOnDragStart:{0:0}", pageOnDragStart));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnEndDrag(PointerEventData eventData)
|
|
||||||
{
|
|
||||||
startDrag = true;
|
|
||||||
float change = 0;
|
|
||||||
|
|
||||||
if (direction == ScrollDirection.Horizontal)
|
|
||||||
{
|
|
||||||
change = positionOnDragStart.x - eventData.position.x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
change = -positionOnDragStart.y + eventData.position.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useFastSwipe)
|
|
||||||
{
|
|
||||||
fastSwipe = false;
|
|
||||||
fastSwipeTimer = false;
|
|
||||||
|
|
||||||
if (fastSwipeCounter <= fastSwipeTarget)
|
|
||||||
{
|
|
||||||
if (Math.Abs(change) > fastSwipeThreshold)
|
|
||||||
{
|
|
||||||
fastSwipe = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fastSwipe)
|
|
||||||
{
|
|
||||||
if (change > 0)
|
|
||||||
{
|
|
||||||
NextScreenCommand();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PrevScreenCommand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lerp = true;
|
|
||||||
lerpTarget = pageAnchorPositions[CurrentPage()];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lerp = true;
|
|
||||||
lerpTarget = pageAnchorPositions[CurrentPage()];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnDrag(PointerEventData eventData)
|
|
||||||
{
|
|
||||||
lerp = false;
|
|
||||||
|
|
||||||
if (startDrag)
|
|
||||||
{
|
|
||||||
OnBeginDrag(eventData);
|
|
||||||
startDrag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue