Unity Dropdown Slider

Hello, Gahwon here. Let’s start off this blog with a tutorial!

For one of my Unity projects, I was prompted to make a slider that expands from and retracts into a button. Here’s how I made it.

hierarchy

Here’s how each of them looks in the hierarchy. As a basic overview, the Mask hides anything outside its region. Meanwhile, the RockSlider moves anything within DropDown up or down when the Button is pressed.

Let’s get started. Create a canvas an put a Panel inside. This will be the parent object for all other components.
Create a new panel and put a mask component. Now, create another panel as a child object. This will be the dropdown that is shown. Make the mask a child of the parent panel.
Put a button as a child object. This button will be in charge of opening and closing the dropdown.
Let’s write code to toggle the visibility of the dropdown object.

public class DropdownSlider : MonoBehavior
{
	public RectTransform Dropdown;

	private bool _opened;

	public bool Opened
	{
		get { return _opened; }
		set
		{
			_opened = value;

			Dropdown.gameObject.SetActive(value);
		}
	}

	public void OnClick()
	{
		Opened = !Opened;
	}
}

You can put this DropdownSlider component within the parent panel and select the dropdown object for the Dropdown field. On the button, add a new function for the On Click () event. Select the parent, and select DropdownSlider.OnClick().

If you run the game now, you can toggle the visibility of the dropdown. But we want it to be more gradual. So lets update our code. Add these lines to DropdownSlider.

// what percentage of the dropdown is visible
private float _percentage;

// how the dropdown animation will play
public AnimationCurve Animation = AnimationCurve.EaseInOut(0, 0, 1, 1);

// length of the total dropdown animation (from completely retracted to fully expanded)
public float AnimationDuration = 1f;

// y position of the dropdown when either fully retracted or expanded
public float RetractedY = 0f;
public float ExpandedY = 100f;

private void Update()
{
	// all animation finished playing
	if (_percentage = 1 && Opened)
		return;

	// update how much is visible
	_percentage += (Opened ? 1 : -1) * Time.unscaledDeltaTime / AnimationDuration;

	if (_percentage = 1)
	{
		_percentage = 1;
	}

	PositionSlider(_percentage);
}

private void PositionSlider(float percentage)
{
	// move the dropdown itself
	var pos = Dropdown.anchoredPosition;
	pos.y = Mathf.Lerp(RetractedY, ExpandedY, Animation.Evaluate(percentage));
	Dropdown.anchoredPosition = pos;
}

Change the setter for the Opened property.

public bool Opened
{
	get { return _opened; }
	set
	{
		_opened = value;

		if (value)
		{
			Dropdown.gameObject.SetActive(true);
		}
	}
}

Now the dropdown should be fully functional.

If you want to change whether the dropdown starts retracted or expanded, use this code:

[SerializeField]
[Tooltip("Whether to start retracted (false) or expanded (true)")]
private bool _opened;

private void Start()
{
	if (!Opened)
	{
		UpdateDropdownVisibility(false);
		PositionSlider(0f);
	}
	else
	{
		UpdateDropdownVisibility(true);
		PositionSlider(1f);
		_percentage = 1f;
	}
}

Here’s the final code:

public class DropdownSlider : MonoBehavior
{
	public RectTransform Dropdown;

	private bool _opened;

	public bool Opened
	{
		get { return _opened; }
		set
		{
			_opened = value;

			if (value)
			{
				Dropdown.gameObject.SetActive(true);
			}
		}
	}

	// what percentage of the dropdown is visible
	private float _percentage;

	// how the dropdown animation will play
	public AnimationCurve Animation = AnimationCurve.EaseInOut(0, 0, 1, 1);

	// length of the total dropdown animation (from completely retracted to fully expanded)
	public float AnimationDuration = 1f;

	// y position of the dropdown when either fully retracted or expanded
	public float RetractedY = 0f;
	public float ExpandedY = 100f;

	private void Start()
	{
		if (!Opened)
		{
			Dropdown.gameObject.SetActive(false);
			PositionSlider(0f);
		}
		else
		{
			Dropdown.gameObject.SetActive(true);
			PositionSlider(1f);
			_percentage = 1f;
		}
	}

	private void Update()
	{
		// all animation finished playing
		if (_percentage = 1 && Opened)
			return;

		// update how much is visible
		_percentage += (Opened ? 1 : -1) * Time.unscaledDeltaTime / AnimationDuration;

		if (_percentage = 1)
		{
			_percentage = 1;
		}

		PositionSlider(_percentage);
	}

	private void PositionSlider(float percentage)
	{
		// move the dropdown itself
		var pos = Dropdown.anchoredPosition;
		pos.y = Mathf.Lerp(RetractedY, ExpandedY, Animation.Evaluate(percentage));
		Dropdown.anchoredPosition = pos;
	}

	public void OnClicked()
	{
		Opened = !Opened;
	}
}

Thanks for reading! Please let me know if any of this was helpful or if I made any mistakes. Also let me know if you would like more images/gifs.