Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// 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 - rewrote almost the entire code
- /// - configuration for direction move instead of 2 concurrent class (easier to change direction in editor)
- /// - supports list layout with horizontal or vertical layout need to match direction with type of layout used
- /// - dynamic checks if scrolled list size changes and recalculates anchor positions
- /// and item size based on itemsVisibleAtOnce and size of root container
- /// if you don't wish to use this auto resize turn of autoLayoutItems
- /// - fixed current page made it independent 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 Modified")]
- public class scrollSnapModified : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
- {
- // needed because of reversed behaviour 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;
- GridLayoutGroup lg;
- 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;
- lg = GetComponentInChildren<GridLayoutGroup>();
- scrollRect = gameObject.GetComponent<ScrollRect>();
- scrollRectTransform = gameObject.GetComponent<RectTransform>();
- listContainerTransform = scrollRect.content;
- listContainerRectTransform = listContainerTransform.GetComponent<RectTransform>();
- rectTransform = listContainerTransform.gameObject.GetComponent<RectTransform>();
- UpdateListItemsSize();
- UpdateListItemPositions();
- PageChanged(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 == scrollSnapModified.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 == scrollSnapModified.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)
- {
- // looking for list spanning range min/max
- scrollRect.horizontalNormalizedPosition = 0;
- listContainerMaxPosition = listContainerTransform.localPosition.x;
- scrollRect.horizontalNormalizedPosition = 1;
- listContainerMinPosition = listContainerTransform.localPosition.x;
- listContainerSize = listContainerMaxPosition - listContainerMinPosition;
- for (var i = 0; i < pages; i++)
- {
- float extra = 0;
- extra = lg.spacing.x*i;
- pageAnchorPositions[i] = new Vector3(
- listContainerMaxPosition - itemSize * i - extra,
- listContainerTransform.localPosition.y,
- listContainerTransform.localPosition.z
- );
- }
- }
- 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;
- for (var i = 0; i < pages; i++)
- {
- pageAnchorPositions[i] = new Vector3(
- listContainerTransform.localPosition.x,
- listContainerMinPosition + itemSize * i,
- listContainerTransform.localPosition.z
- );
- }
- }
- UpdateScrollbar(linkScrolbarSteps);
- startingPage = Mathf.Min(startingPage, pages);
- ResetPage();
- }
- if (itemsCount != activeCount)
- {
- PageChanged(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);
- }
- //change the info bullets at the bottom of the screen. Just for visual effect
- if (Vector3.Distance(listContainerTransform.localPosition, lerpTarget) < 10f)
- {
- PageChanged(CurrentPage());
- }
- }
- if (fastSwipeTimer)
- {
- fastSwipeCounter++;
- }
- }
- 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];
- PageChanged(CurrentPage() + 1);
- }
- }
- //Function for switching screens with buttons
- public void PreviousScreen()
- {
- UpdateListItemPositions();
- if (CurrentPage() > 0)
- {
- lerp = true;
- lerpTarget = pageAnchorPositions[CurrentPage() - 1];
- PageChanged(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];
- PageChanged(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];
- PageChanged(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+(lg.spacing.x));
- return Mathf.Clamp(Mathf.RoundToInt(page), 0, pages);
- }
- public void ChangePage(int page)
- {
- if (0 <= page && page < pages)
- {
- lerp = true;
- lerpTarget = pageAnchorPositions[page];
- PageChanged(page);
- }
- }
- //changes the bullets on the bottom of the page - pagination
- private void PageChanged(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();
- }
- 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
- }
- }
Add Comment
Please, Sign In to add comment