Last active
October 3, 2024 00:54
-
-
Save phosphoer/5c6bdb93a6e518200f6ce680489ad4b3 to your computer and use it in GitHub Desktop.
Custom Unity ScrollRect
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
public class ScrollRectTransform : MonoBehaviour | |
{ | |
public Vector2 ScrollPosition | |
{ | |
get => _content.anchoredPosition; | |
set => SetScrollPosition(value); | |
} | |
public bool EnableHorizontal = true; | |
public bool EnableVertical = true; | |
[SerializeField] | |
private RectTransform _content = null; | |
// Calculate the absolute scroll position that will bring targetTransform | |
// directly to the center of the scroll view | |
public Vector2 GetCenterScrollPos(RectTransform targetTransform) | |
{ | |
RectTransform viewport = transform as RectTransform; | |
Bounds elementBounds = targetTransform.TransformBoundsTo(viewport); | |
float offsetX = EnableHorizontal ? viewport.rect.center.x - elementBounds.center.x : 0; | |
float offsetY = EnableVertical ? viewport.rect.center.y - elementBounds.center.y : 0; | |
return new Vector2(offsetX, offsetY) + _content.anchoredPosition; | |
} | |
// Calculate the absolute scroll position such that the target transform | |
// is brought into view with optional padding with the minimal movement necessary | |
public Vector2 GetClampedScrollPos(RectTransform targetTransform, float padding = 0) | |
{ | |
RectTransform viewport = transform as RectTransform; | |
Rect viewportRect = viewport.rect; | |
Bounds elementBounds = targetTransform.TransformBoundsTo(viewport); | |
elementBounds.Expand(padding); | |
float offsetX = Mathf.Max(0, viewportRect.min.x - elementBounds.min.x) | |
- Mathf.Max(0, elementBounds.max.x - viewportRect.max.x); | |
float offsetY = Mathf.Max(0, viewportRect.min.y - elementBounds.min.y) | |
- Mathf.Max(0, elementBounds.max.y - viewportRect.max.y); | |
return new Vector2(EnableHorizontal ? offsetX : 0, EnableVertical ? offsetY : 0) + _content.anchoredPosition; | |
} | |
private void SetScrollPosition(Vector2 scrollPos) | |
{ | |
_content.anchoredPosition = scrollPos; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.UI; | |
public static class UIExtensions | |
{ | |
/// <summary> | |
/// Transform the bounds of the current rect transform to the space of another transform. | |
/// </summary> | |
/// <param name="source">The rect to transform</param> | |
/// <param name="target">The target space to transform to</param> | |
/// <returns>The transformed bounds</returns> | |
private static Vector3[] _corners = new Vector3[4]; | |
public static Bounds TransformBoundsTo(this RectTransform source, Transform target) | |
{ | |
// Based on code in ScrollRect's internal GetBounds and InternalGetBounds methods | |
var bounds = new Bounds(); | |
if (source != null) | |
{ | |
source.GetWorldCorners(_corners); | |
var vMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); | |
var vMax = new Vector3(float.MinValue, float.MinValue, float.MinValue); | |
var matrix = target.worldToLocalMatrix; | |
for (int j = 0; j < 4; j++) | |
{ | |
Vector3 v = matrix.MultiplyPoint3x4(_corners[j]); | |
vMin = Vector3.Min(v, vMin); | |
vMax = Vector3.Max(v, vMax); | |
} | |
bounds = new Bounds(vMin, Vector3.zero); | |
bounds.Encapsulate(vMax); | |
} | |
return bounds; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment