How to scroll to a specific element in ScrollRect with Unity UI?

后端 未结 10 2260
野的像风
野的像风 2021-02-12 04:03

I built a registration form for a mobile game using Unity 5.1. To do that, I use Unity UI components: ScrollRect + Autolayout (Vertical layout) + Text (labels)

相关标签:
10条回答
  • 2021-02-12 04:27

    here's the way I clamped selected object into ScrollRect

    private ScrollRect scrollRect;
    private RectTransform contentPanel;
    
    public void ScrollReposition(RectTransform obj)
    {
        var objPosition = (Vector2)scrollRect.transform.InverseTransformPoint(obj.position);
        var scrollHeight = scrollRect.GetComponent<RectTransform>().rect.height;
        var objHeight = obj.rect.height;
    
        if (objPosition.y > scrollHeight / 2)
        {
            contentPanel.localPosition = new Vector2(contentPanel.localPosition.x,
                contentPanel.localPosition.y - objHeight - Padding.top);
        }
    
        if (objPosition.y < -scrollHeight / 2)
        {
            contentPanel.localPosition = new Vector2(contentPanel.localPosition.x,
    contentPanel.localPosition.y + objHeight + Padding.bottom);
        }
    }
    
    0 讨论(0)
  • 2021-02-12 04:28

    In case anyone looking for a smooth scroll (using lerp).

    [SerializeField]
    private ScrollRect _scrollRectComponent; //your scroll rect component
    [SerializeField]
    RectTransform _container; //content transform of the scrollrect
    private IEnumerator LerpToChild(RectTransform target)
    {
        Vector2 _lerpTo = (Vector2)_scrollRectComponent.transform.InverseTransformPoint(_container.position) - (Vector2)_scrollRectComponent.transform.InverseTransformPoint(target.position);
        bool _lerp = true;
        Canvas.ForceUpdateCanvases();
    
        while(_lerp)
        {
            float decelerate = Mathf.Min(10f * Time.deltaTime, 1f);
            _container.anchoredPosition = Vector2.Lerp(_scrollRectComponent.transform.InverseTransformPoint(_container.position), _lerpTo, decelerate);
            if (Vector2.SqrMagnitude((Vector2)_scrollRectComponent.transform.InverseTransformPoint(_container.position) - _lerpTo) < 0.25f)
            {
                _container.anchoredPosition = _lerpTo;
                _lerp = false;
            }
            yield return null;
        }
    }
    
    0 讨论(0)
  • 2021-02-12 04:30

    I am going to give you a code snippet of mine because i feel like being helpful. Hope this helps!

    protected ScrollRect scrollRect;
    protected RectTransform contentPanel;
    
    public void SnapTo(RectTransform target)
        {
            Canvas.ForceUpdateCanvases();
    
            contentPanel.anchoredPosition =
                (Vector2)scrollRect.transform.InverseTransformPoint(contentPanel.position)
                - (Vector2)scrollRect.transform.InverseTransformPoint(target.position);
        }
    
    0 讨论(0)
  • 2021-02-12 04:33

    None of the suggestions worked for me, the following code did

    Here is the extension

    using UnityEngine;
    using UnityEngine.UI;
    
    namespace BlinkTalk
    {
        public static class ScrollRectExtensions
        {
            public static Vector2 GetSnapToPositionToBringChildIntoView(this ScrollRect instance, RectTransform child)
            {
                Canvas.ForceUpdateCanvases();
                Vector2 viewportLocalPosition = instance.viewport.localPosition;
                Vector2 childLocalPosition   = child.localPosition;
                Vector2 result = new Vector2(
                    0 - (viewportLocalPosition.x + childLocalPosition.x),
                    0 - (viewportLocalPosition.y + childLocalPosition.y)
                );
                return result;
            }
        }
    }
    

    And here is how I used it to scroll a direct child of the content into view

        private void Update()
        {
            MyScrollRect.content.localPosition = MyScrollRect.GetSnapToPositionToBringChildIntoView(someChild);
        }
    
    0 讨论(0)
提交回复
热议问题