Search Unity

[SOLVED] Dropdown always selects the first option automatically

Discussion in 'Scripting' started by Quasar47, Feb 17, 2018.

  1. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    I know this is the default setting for dropdowns to always have an option active, but can I tell a dropdown to select nothing, and so having none of its items active ?

    I've made some researches about that, and I found two solutions :

    - The first one : Setting the dropdown value to -1 by default. This solution works, but only once, and you need to change the value manually through the Inspector. I've already tried resetting the value to 0 via script, but either my dropdown automatically sets "0" and so loads the first option without my word to say, OR prevents my script from finishing its execution. (Well, it obviously finishes its execution, but it doesn't go through all my functions...)

    The second one : Creating a temporary option with 0 as value, then immediately removing it so that the dropdown cannot find it, and its selection remains blank. This doesn't work.

    So, i'm out of options. is there a way to prevent the dropdown from selecting its first item ? I'm interested in any ideas you could come up with, provided that they're not too complicated (After 3 years, I'm not really a beginner anymore, but I'm not a competent developer either yet).

    Thanks for your answer.
     
  2. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    I suppose you thought of just leaving the first option blank.
     
  3. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Yes i did, but i'd prefer not to have a blank space before my options. I just would like to get my options only, but with none of them selected, so that I can select the very first item in the list and still trigger the OnValueChanged event.
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I'm not sure how to easily make it so no option is selected.. However, would it suffice to have a method called when an item is selected even if that item was already selected?

    In case that is enough to solve your current issue, an option is to put a script on the item template option that implements the IPointerClick interface and use that to call your method, possibly instead of OnValueChanged.
     
    Last edited: Feb 18, 2018
  5. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    By "called when an item is selected", the only way I can see to achieve this is to assign a button component on each one of my options, then assign to those buttons the method they would call when pressed, and all of this dynamically via script as soon as they are instantiated.

    I don't think this would be that complicated, but I think there is a cleaner solution to do the same thing without adding more components. Because I thought about adding a blank option as the first one like suggested fire7side, and call the method only if the option's name length is > to 0, but I want my dropdown list to have only the maps' names as options, not a fake one. It's partly a matter of preference, but it would be more correct.
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Check my edit in case you didn't see it.
     
  7. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    I've written my post before the thread was updated, so I didn't see your edit. Sorry for that :)

    I briefly checked what an IpointerClick is, but I don't really get how it works :

    https://docs.unity3d.com/ScriptReference/EventSystems.IPointerClickHandler.OnPointerClick.html


    So, what I should try is to create a void like thid one to detect if my cursor is over my options, and if so, call the load method instead of using the OnValueChanged event? Should I place it directly in my load script or create a new one and place it on my options ? Sorry for asking, this is the first time I'm seeing the IPointerClick, I understand what it does, but not really how to implement it. Thanks for your answer.
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay, just to be clear, this won't prevent an option from being already selected. However, it will allow you to call a method on an already selected drop down option, which normally wouldn't trigger on value changed.

    Create a script that implements the interface and attach the script to the item in the template (this is a child of the dropdown). Inside the script, make a reference to the dropdown. Inside the interface's method, check the value of the dropdown (dropDown.value) and use that for whatever you were doing.
    This would essentially be equal to OnValueChanged or StayedTheSame ;) but something was clicked.
    So, you probably want to remove the OnValueChanged event.

    The script might look like this:
    Code (csharp):
    1.  
    2. public class Test12 : MonoBehaviour, IPointerClickHandler
    3. {
    4.     [SerializeField]
    5.     Dropdown dropDown;
    6.     /* You might have another script reference here if needed */
    7.     public void OnPointerClick(PointerEventData eventData)
    8.     {
    9.         // here, dropDown.value is right, whether the value is new or old.
    10.     }
    11. }
     
  9. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    I can see it now, but there's a little problem with that : Just as I said earlier, the items in my dropdown list are instantiated at runtime, and not in the editor. I've searched how to add a script to options dynamically for weeks, but I never found something relevant, and today is not an exception. So, I can't call the method above just by clicking on my option.
     
  10. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Ok, sorry, the problem was I didn't correctly understand what you were meaning my "Item"; in fact, I didn't know that what was in the template was duplicated, I thought it was justan example to show how the item was composed. Yeah, I know, it's in the name "Template", sorry...

    I've put my script on the item, and yes, it worked. However, it doesn't untick the option that isn't selected anymore, and each time I click on them, the drodown list becomes more and more transparent until it becomes invisible.
     
  11. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Hm.. that is odd. For the transparency, I assume you are modifying the alpha somehow?
    As for the not unticking, that is strange. Do you have any errors? That's all I can think of, off hand. I only ran a simple test to print the value, but the options had the correct one ticked/unticked..

    Unless you mean being able to uncheck all, in which case as I said, this solution doesn't cover that, sorry.
     
  12. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    No, I haven't changed the alpha at all. I think it changes like that because the panel is disabled just before the dropdown list collapses again. And because it collapses just a few miliseconds late, it didn't end the fade transition properly. I know, it looks weird, but it's the only explanation. The buttons remain interactable, though.

    to show you exactly what happens :

    The untick issue :

    untick.png


    And the fade issue (This one doesn't appears clearly immediately, I had to load a few maps before it becomes completely visible) :

    trans.png

    See? We can even see the Delete button behind the dropdown list. I don't know why, but it makes me laugh.
     
  13. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Oh, ok.. well that is pretty odd. :) I'm really not sure what to tell you, sorry.
     
  14. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    I think the problem comes from the method I use to auto-hide the panel :

    Code (CSharp):
    1. public void DISPLAY_PANEL()
    2.     {
    3.  
    4.         showGUI = !showGUI;
    5.         Reset_Only_UI_Of_Other_Buttons();
    6.         Proceed_To_showGUI_Verification();
    7.        
    8.     }
    9.  
    10.  
    11.     public void Proceed_To_showGUI_Verification()
    12.     {
    13.         panelLoad.SetActive(showGUI);
    14.     }

    When I click on the Load button you can see on the pictures I've sent, the script inverts the state of showGUI, that I use just after to able/disable the panel, which is the parent of my Dropdown. Display_Panel() is also called once I've finished instantiating my new map. I think the problem comes from the fact that the parent is disabled while the dropdown component is still active. Also, the dropdown GameObject is still marked as active in the Inspector whereas it is grayed in the hierarchy. Lemme try just one single thing that I think would work.
     
  15. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Ok, my test didn't work. What I tried was to simply enable/disable the dropdown component before the panel, just to see if the component was the origin of this bug, but it isn't.

    Well, even of you couldn't help, thanks you a lot for trying. At least your script worked ; I could select an item that was already selected, so at least this problem is solved.
     
  16. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Ok, I've found another solution :

    Since disabling the panel after loading the map is what causes these bugs, I've decided to let the player close it manually either by clicking on the button again, or outside the panel (I have another script that detects a click outside the panel and automatically disables it). Doing the thing this way let me select any map without any visual glitch. Thanks once again for your help, guys :)
     
  17. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    If you comment out your code that disables the object or whatever does it work then?

    Ah okay, cool. I was going to suggest that you could put a small delay (like .2f). I think the delay for the drop down is .15f, if memory serves from looking at the source earlier.
     
  18. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122

    Hey, coincidence or not, this is exactly what I tried :D I didn't commented the line, but instead I've put in in an IEnumerator right after a delay of 0.2f seconds, than I called this coroutine once the map finished loading, and it worked perfectly fine :)

    Code (CSharp):
    1. private void INSTANTIATE(){
    2.  
    3.         // the end of the instantiation
    4.         //print("Niveau chargé.");
    5.         StartCoroutine("HIDE_PANEL");
    6.     }
    7.  
    8.     private IEnumerator HIDE_PANEL()
    9.     {
    10.         yield return new WaitForSeconds(0.2f);
    11.         DISPLAY_PANEL();
    12.     }

    Simply as that.
     
  19. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Nice. :)

    Ya, I edited my post after you mentioned disabling it or what not (adding the part about the delay).
     
  20. LeonelChh

    LeonelChh

    Joined:
    Jun 26, 2023
    Posts:
    1
    have you solved it bro, i need help haha