- Home /
How to create a dropdown without having an item selected?
Hi all,
I created a dropdown and populated it with several country names for the user to choose from. The dropdown's value starts at 0, so the first country is already selected. I want the caption text to initially be "Country" and not "Afghanistan" so I manually changed it:
CountryDropdown.captionText.text = "Country";
This works fine almost always, but if the user chooses "Afghanistan" the caption text does not change and stays "Country" and onValueChanged doesn't trigger. This happens because the value was and still is 0.
I tried to set the value property of the dropdown to -1 but Unity treats it as 0. Apparently, it's also not possible to choose a value bigger than the last item on the list. I know I can just add a country to the top of the list and call it "Country" but it seems like an ugly solution.
Is there a way to do what I want?
Thanks for the help!
I ran into a similar problem. Not exactly the same, but similar.
In my case I have a collection of possible values the user can select from, save and change later on when they reload the game. This was all working fine however when I created the content for the drop down list, I would also set the CaptionText to the value the user had previously selected and saved. However as you've also found out, the value on the list would always be 0. $$anonymous$$eaning the user could never select the first item on the list. Hopefully I've explained that well enough.
I really do consider this a bug and have submitted a bug report. We should be able to set a default value of -1 OR if we are setting the captiontext to the same text thats in the drop list, the value should default to that item. That's how other drop down list components work.
At any rate, I created a little routine that would itterate through all the items on the list and do a text match. This is a pretty brute force way to do it, but my list of options is quite small (about 6) and it's a UI component where speed isn't really a concern.
SetDropValue($$anonymous$$yDropList, DesiredCaptionString);
/// <summary>
/// Sets the caption text and selected item index to the specified string.
/// </summary>
/// <param name="_DropDown">The dropdown list we want to update</param>
/// <param name="_CaptionText">The caption we want to set. $$anonymous$$ust be an item on the list.</param>
private void SetDropValue(Dropdown _DropDown, string _CaptionText)
{
string Caption = _CaptionText.ToUpper();
//Set the caption we want
_DropDown.captionText.text = Caption;
//Now we have to hack our way through and set the value based on the caption.
for (int OptIndex = 0; OptIndex <= (_DropDown.options.Count - 1); OptIndex++)
{
if (_DropDown.options[OptIndex].text.ToUpper() == Caption)
{
_DropDown.value = OptIndex;
break; //don't bother checking the rest
}
}
}
So now, anytime I need to set a preselected value for a drop list, I just call that function. There's no error handling and doesn't handle cases where the caption is for an item that is not on the list (so your problem may still occur).
Hope that helps someone.
Answer by Rajeesh_AR · Dec 17, 2015 at 10:57 AM
Hi, I checked the inbuilt possibility, but didn't get any option. But I found one method. First of all, I hope that you are using Unity UI drop down. I am telling the option for that. As you said, unity dropdown value starts from 0 and we cannot give the title to the dropdown.
create a 3dtext, with "country" as title and place over the dropdown box.
Adjust the 3dtext size so that, the arrow of the dropdown can be seen
Add (+) one option to "On Value Changed (Int 32) " of the DropDown
drag and drop this 3dtext- gameobject to the "On Value Changed (Int 32) " box.
In that option select "Game Object" > set Active (bool) to false .
Now you could see that, initially "country" will be the title of the dropdown and when the dropdown value is selected, the "country" title is off and the value is seen.
Hope this helps. for further help on this, pls msg me. Happy coding.. :)
The OnValueChanged does not trigger when choosing the first item on the list (since the value stays 0). This means I can't relay on OnValueChanged to make changes to the 3dtext, just as I can't relay on it to change the in-built caption-text of the dropdown.
I did find another workaround, though it's not pretty: When the user clicks on the dropdown button, it creates a child named "Dropdown List" which holds all the items. I can set the caption-text to be the title I wanted (or use a 3dtext like you suggested) and constantly search for the child object in Update(). When I find it, I clear the caption-text / 3dtext and now wait for this item to be destroyed. When it is destroyed I set he caption-text to be the string of the selected value (so that if the first item was selected we don't get an empty string).
If anyone has a better idea please let me know.
Hello from 2019! It's alar$$anonymous$$g that almost 3.5 years after this answer, Unity still hasn't added a "default label" or similar option to this component. For shame.
For anyone else reading, though, I can confirm that this "extra default label" approach gives us what really should be the dropdown's default behavior, and you can ignore the other answers. I would however recommend simply duplicating the Label that Unity gives you, ins$$anonymous$$d of creating and placing a new one from scratch - no need for 3D text when the 2D label already looks perfect - and disabling the "real" label until OnValueChanged is fired. Then as long as you make sure to enable the real label when that event fires, in addition to disabling the duplicate, you're (almost) good to go - just have to fix spitz7's last issue.
The cleanest fix there appears to be to simply set the Dropdown's "Value" field to anything either lower than 0 or higher than the number of items in the list; then "OnValueChanged" will fire just fine on the first click of any item. I used "-1".
Answer by Giovannino82 · Mar 17, 2016 at 01:41 PM
Add an option you will not use, select it and then remove it via script. The dropdown will show unchecked options. Strange and tricky but it is working for me.
I tried this by dropdown.options.removeAt(0) but it auto selects the new item at index 0 then. How were you able to do this?
Thanks.
// Add a blank dropdown option you will then remove at the end of the options list
dropdown.GetComponent<Dropdown> ().options.Add (new Dropdown.OptionData() {text=""});
// Select it
dropdown.GetComponent<Dropdown>().value = dropdown.GetComponent<Dropdown>().options.Count - 1;
// Remove it
dropdown.GetComponent<Dropdown>().options.RemoveAt(dropdown.GetComponent<Dropdown>().options.Count - 1);
// Done!
It works fairly well, thanks for your suggestion!
The only tiny thing I noticed is that if I alt-tab Unity editor and come back, it automatically selects the new last option (after removing the extra one by code).
It doesn't happen in the build though, so we can safely hack away :D
This trick doesn't work anymore in 2018.1.1f version. Any other ideas?
Answer by Gnaarf · Jun 23, 2017 at 01:13 PM
Kind of old topic, but I just had a similar Problem and found that ISelectHandler triggers at the right time.
I adjusted my code a little to fit your problem. Just add it to the GameObject with the Dropdown-Component:
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(Dropdown))]
public class DropdownWithTitle : MonoBehaviour, ISelectHandler
{
[SerializeField] Dropdown.OptionData title;
bool wasNeverSelected = true;
Dropdown dropdown;
void Start()
{
dropdown = GetComponent<Dropdown>();
dropdown.options.Insert(dropdown.value, title);
dropdown.RefreshShownValue();
}
public void OnSelect(BaseEventData eventData)
{
if (wasNeverSelected)
RemoveTitle();
wasNeverSelected = false;
}
private void RemoveTitle()
{
dropdown.options.RemoveAt(dropdown.value);
dropdown.RefreshShownValue();
}
}
Hey @Gnaarf,
This is very useful, thank you.
The only $$anonymous$$or issue I've spotted is that it doesn't fire an onValueChanged event.
As an example;
the title is displayed
the dropdown is selected
the title is removed from the list
the next option is immediately "ticked" and is now the default value
..but if I click away from the dropdown menu, it looks as if that item is selected but it didn't fire the onValueChanged event, so anything relying on it doesn't know the value has changed from "title" to the new value.
If the user doesn't click away, where-by the control loses focus, and clicks on the option with the tick then it behaves as expected.
private void RemoveTitle()
{
dropdown.options.RemoveAt(dropdown.value);
dropdown.onValueChanged.Invoke(dropdown.value);
dropdown.RefreshShownValue();
}
Could probably do with a little validation, to check that there are actually items in the list and so on, but this seemed to work.
Rob
Thanks @Gnaarf and @Rob-$$anonymous$$eade
I wanted $$anonymous$$e to be programatically changed and not necessarily on Start(). Here is my version.
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(Dropdown))]
public class DropdownWithTitle : $$anonymous$$onoBehaviour, ISelectHandler
{
[SerializeField] Dropdown.OptionData title;
bool wasNeverSelected = true;
Dropdown dropdown;
public void SetTitleAndReset(string newTitle)
{
dropdown = GetComponent<Dropdown>();
wasNeverSelected = true;
title.text = newTitle;
dropdown.options.Insert(dropdown.value, title);
dropdown.RefreshShownValue();
}
public void OnSelect(BaseEventData eventData)
{
if (wasNeverSelected)
RemoveTitle();
wasNeverSelected = false;
}
private void RemoveTitle()
{
dropdown.options.RemoveAt(dropdown.value);
dropdown.onValueChanged.Invoke(dropdown.value);
dropdown.RefreshShownValue();
}
}
Answer by tcz8 · Jun 05, 2020 at 06:00 AM
Here's another one:
[SerializeField] string defaultText = "Default Text"; // We use public to much
bool init = true;
void OnGUI() { // Runs right when drawing the UI, nothing can stop my default text now!
if init {
init = false;
dropdownMenu.captionText.text = defaultText;
}
}
void OnDisable() {
init = true;
}
How I use it:
I load data into my dropdown on Start() and the dropdown gets displayed as a result of enabling it's game object. When it's game object is disabled the default text is reset and will appear again the next time it's enabled.
Why OnGui ?
Because it's the very last moment before the UI gets drawn. This way nothing gets the chance to override your default text.
Answer by AlvinHerawan · Apr 09, 2016 at 02:54 PM
I've been having the same issue and doing a country picker myself. After playing around, I notice that the most effective method is to actually set the Dropdown value MORE than the number of options I have. So, if you have 100 countries in your options, just input 101 or more from the Inspector panel.
I also change the text via script by writing this:
private var SelectedLocation : Text;
function Start () {
SelectedLocation = LocationPickerLabel.GetComponent(UI.Text);
SelectedLocation.text = "Select a location ...";}
I do feel that there ought to be a more elegant solution. But for now, this will do.
I'm adding options by code and then I set the dropdown value to 1 more than the number of items but in my case the last option is shown as selected. I'm using Unity 5.3.4f1.
Yes, the last option will be shown. But as you run the script, if you add the code like what I've suggested as above, then it will be changed to whatever text you need it to be. You can edit the text manually by changing the Text.text component of the label object, which is normally a child of the dropdown object.
Your answer
Follow this Question
Related Questions
How to make dropdown start at value on click 0 Answers
TextMeshPro dropdown default value change 0 Answers
using enum value in cs? 1 Answer
Findinga GameObject Transform 1 Answer
Unexpected token? 1 Answer