Rumata
Rumata

Reputation: 1047

How to set a scrolling distance limit for the scrollable UI (Unity)?

I work on a simple scrollable UI in Unity.

I use the following script (assigned to the Empty) to make it scrollable:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class PageSwiper : MonoBehaviour, IDragHandler, IEndDragHandler
{
    private Vector3 scrollableUILocation;



    // Start is called before the first frame update
    void Start()
    {
        scrollableUILocation = transform.position;
    }
    public void OnDrag(PointerEventData data)
    {
        float difference = data.pressPosition.x - data.position.x;
        transform.position = scrollableUILocation - new Vector3(difference, 0, 0);
    }
    public void OnEndDrag(PointerEventData data)
    {
        scrollableUILocation = transform.position;

    } 
}

The problem is that I can scroll the UI panel outside of the screen. So I need to make it impossible, or make it so that if I scroll it too far, it smoothly returns back (to the end or to the start of the UI panel, depending on which is closer)

How can I do it?


I tried to implement the following solution but it doesn't work:

I added two Empty object on the left and on the right from the UI panel. I tried to make my UI panel to smoothly move at the position of one of those empty objects in case if I would move it close enough to them. But it doesn't work.

 public void OnEndDrag(PointerEventData data)
{
    if (Vector3.Distance(transform.position, StartPoint.transform.position) < 1.0f)
    {
        StartCoroutine(SmoothMove(transform.position, StartPoint.transform.position, easing));
    }

    else if (Vector3.Distance(transform.position, EndPoint.transform.position) < 1.0f)
    {
        StartCoroutine(SmoothMove(transform.position, EndPoint.transform.position, easing));
    }


}

IEnumerator SmoothMove(Vector3 startpos, Vector3 endpos, float seconds)
{
    float t = 0f;
    while (t <= 1.0)
    {
        t += Time.deltaTime / seconds;
        transform.position = Vector3.Lerp(startpos, endpos, Mathf.SmoothStep(0f, 1f, t));
        yield return null;
    }
}

Upvotes: 2

Views: 8392

Answers (2)

  • Unrestricted The content can move forever. basically you can lose the content with a big scroll
  • Elastic The content is allowed to temporarily move beyond the container, but is pulled back elastically useless
  • Clamped The content can not be moved beyond its container useless

Upvotes: 0

Everts
Everts

Reputation: 10701

So you'd be better off with a ScrollRect as it already contains all the needed actions for this kind of feature.

MovementType will define how the system reacts when reaching the end of the container (from the documentation):

  • Unrestricted The content can move forever.
  • Elastic The content is allowed to temporarily move beyond the container, but is pulled back elastically.
  • Clamped The content can not be moved beyond its container.

Considering you have a long button system, maybe it needs to be dynamic, so you'd look into ContentSizeFitter.

You add a scroll view object. This will include by default:

  • Scrollview
  • Viewport
  • Content

Now add a Text component to the Content object, NOT a text child, a component to it. Also add a ContentSizeFitter and set the vertical fit to prefered size. This is because I will deal with vertical expansion.

Make sure the Viewport occupies the space that should serve as mask. For first practice, place the ScrollView object in the middle and set the anchors of Viewport to 0,1 so it takes the whole parent.

There is plenty more you can do and I would suggest to look into the free Unity UI extension library as it has some fancy accordeon or endless scrolling effects.

Upvotes: 2

Related Questions