Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Make button style 'selected' or 'toggled' through script

Discussion in 'UI Toolkit' started by alexanderameye, Feb 16, 2020.

  1. alexanderameye

    alexanderameye

    Joined:
    Nov 27, 2013
    Posts:
    1,259
    I have a toolbar like this with several sections.

    upload_2020-2-16_20-29-43.png

    I want the active section to be a different color when clicked on. Is there a way to change the button through script to some kind of 'selected' or 'toggled' state that will change its color? I want it to look native and work for both light and dark theme.
     
  2. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    788
    Use the ToolbarToggle or regular Toggle and set it's value property to true or false instead of a button.
     
    alexanderameye likes this.
  3. alexanderameye

    alexanderameye

    Joined:
    Nov 27, 2013
    Posts:
    1,259
    And how can I check if the button was clicked?

    Before for my buttons I used

    Button.clickable.clickedWithEventInfo += Function;

    but the Toggle does not seem to have the clickable property.
     
  4. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    788
    Like this:

    Code (CSharp):
    1. Toggle toggle = new Toggle("Option A");
    2. toggle.value = true; // Set toggle active in script.
    3. toggle.RegisterValueChangedCallback(evt =>
    4. {
    5.     Debug.Log("Toggle was changed to value: " + evt.newValue);
    6. });
     
  5. VOTRUBEC

    VOTRUBEC

    Joined:
    Dec 17, 2014
    Posts:
    70
    These are what I use:

    Code (CSharp):
    1. yourToggle.RegisterValueChangedCallback<bool> ( x => Function() );
    2. yourButton.RegisterCallback<MouseUpEvent> ( x => Function ( ) );
     
  6. alexanderameye

    alexanderameye

    Joined:
    Nov 27, 2013
    Posts:
    1,259
    Yeah but this callback is triggered whenever the value changes right? Not when I click on the toggle?

    I want the sections to be selected one by one, how do I achieve this?

    So right now I have this code.

    Code (CSharp):
    1.   supportToggle.RegisterValueChangedCallback(evt =>
    2.             {
    3.                 aboutToggle.value = false;
    4.                 acknowledgementsToggle.value = false;
    5.                 detectIssuesToggle.value = false;
    6.             });
    7.  
    8.             aboutToggle.RegisterValueChangedCallback(evt =>
    9.            {
    10.                supportToggle.value = false;
    11.                acknowledgementsToggle.value = false;
    12.                detectIssuesToggle.value = false;
    13.            });
    14.  
    15.             acknowledgementsToggle.RegisterValueChangedCallback(evt =>
    16.            {
    17.                supportToggle.value = false;
    18.                aboutToggle.value = false;
    19.                detectIssuesToggle.value = false;
    20.            });
    21.  
    22.             detectIssuesToggle.RegisterValueChangedCallback(evt =>
    23.            {
    24.                supportToggle.value = false;
    25.                aboutToggle.value = false;
    26.                acknowledgementsToggle.value = false;
    27.            });
    Because let's say I press the support toggle, I want the button to be toggled, and the rest to be off, so I set the values to 'false', but that triggers the other callbacks since the callback is simply for a value change, and it gets stuck...
     
    Last edited: Feb 17, 2020
  7. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    788
    What you're describing sounds like "radio buttons". I believe this would be a nice use-case for SetValueWithoutNotify:

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEngine.UIElements;
    4.  
    5. public class MyWindow : EditorWindow
    6. {
    7.     [MenuItem("Window/MyWindow")]
    8.     private static void ShowWindow()
    9.     {
    10.         GetWindow<MyWindow>("MyWindow");
    11.     }
    12.  
    13.     private Toggle[] radioButtons;
    14.  
    15.     private void OnEnable()
    16.     {
    17.         radioButtons = new Toggle[]
    18.         {
    19.             new Toggle("Option A") { name = "A" },
    20.             new Toggle("Option B") { name = "B" },
    21.             new Toggle("Option C") { name = "C" },
    22.         };
    23.  
    24.         for (int i = 0; i < radioButtons.Length; i++)
    25.         {
    26.             radioButtons[i].RegisterValueChangedCallback(OnToggleChanged);
    27.             rootVisualElement.Add(radioButtons[i]);
    28.         }
    29.     }
    30.  
    31.     private void OnToggleChanged(ChangeEvent<bool> evt)
    32.     {
    33.         // Turn off all other toggles except the one that is currently active.
    34.         for (int i = 0; i < radioButtons.Length; i++)
    35.         {
    36.             if (radioButtons[i] != evt.target)
    37.                 radioButtons[i].SetValueWithoutNotify(false);
    38.         }
    39.  
    40.         Debug.Log("Now active: " + ((VisualElement)evt.target).name);
    41.     }
    42. }
    43.  
    When one of the toggles changes, you set the value of all other toggles, but without sending any further changed events.
     
    FuguFirecracker and JoNax97 like this.
  8. FuguFirecracker

    FuguFirecracker

    Joined:
    Sep 20, 2011
    Posts:
    289
    I may be over-thinking this ( over-engineering ) ; Here's my solution :

    Code (CSharp):
    1.  
    2. public class ToggleGroup
    3. {
    4.     private readonly ToolbarToggle[] _toggles = new ToolbarToggle[2];
    5.  
    6.     public void SetToggle(ToolbarToggle tbt)
    7.     {
    8.         if (_toggles[0] == tbt)
    9.         {
    10.             tbt.SetValueWithoutNotify(true);
    11.             return;
    12.         }
    13.  
    14.         _toggles[0] = tbt;
    15.         _toggles[1]?.SetValueWithoutNotify(false);
    16.         _toggles[1] = _toggles[0];
    17.     }
    18. }
    19.  
    And call with :
    Code (CSharp):
    1.  
    2. private void Callback(ChangeEvent<bool> evt)
    3. {
    4.     _toggleGroup.SetToggle(evt.target as ToolbarToggle);
    5. }
    6.  
    Basically:Turn this one on; Turn that other one off.

    Despite only keeping track of 2 toggle buttons, it works for any number.
    I realized that if someone gave a quick glance, one might think it was just a 2 toggle solution lol.
     
unityunity