Tasharen Entertainment Forum

Support => NGUI 3 Documentation => Topic started by: ArenMook on November 20, 2013, 11:19:04 PM

Title: UIToggle
Post by: ArenMook on November 20, 2013, 11:19:04 PM
Overview

A toggle is a generic component that has two states: on, and off. Toggle can be used to create checkboxes, tabs, radio button groups, and other similar widgets.

(http://www.tasharen.com/ngui/toggle.jpg)

Toggle is a perfect example of a small to-the-point component that can be used to do a lot of things. Like most NGUI controls, the look of it is not hard-coded for you like it is in other systems. Instead, it's used in combination with other scripts to achieve the desired behaviour.

By itself, the toggle is simply capable of fading in and fading out the targeted object. Generally this "object" is a checkmark, a highlighted sprite, or some other indicator of an active state.

To create a basic checkbox, create a pair of sprites -- a background, and a foreground (make it a child of the background to make it simple). For the background choose something that looks like a button. For the foreground choose something that looks like a checkmark.

Attach the UIToggle script to the parent (the background), and reference the foreground in the UIToggle's Sprite parameter. That's it, you now have a checkbox.

You can turn it into a Radio Button by specifying a Group ID other than zero. Just set up your checkbox how you want it to be, give it a group ID, and duplicate your checkbox game object a couple of times (CTRL+D with it selected).

You can create an Animation to make your checkmark transition smoother, or just attach an Animation component to your Checkmark and reference the provided "Checkmark" animation clip. Reference this clip in the Animation field on your Toggle, and you will have an even better looking transition.

If you want your toggle to start active, check the Starting State checkbox.

Pro-Tip

You can create a tab using a Toggle by creating two sprites, one on top of the other. First create a dark sprite, then add a child to it and make it brighter. Attach a Toggle component to the dark sprite's object and reference the lighter sprite as the Toggle's Sprite. Give this tab a Group then duplicate it a few times to create a group of tabs.

Use together with the UIToggledObjects script to set up easy enabling and disabling of child panels, thus creating a multi-tabbed window.

Class Documentation

http://tasharen.com/ngui/docs/class_u_i_toggle.html

If you have a question regarding this component or would like me to clarify something, just post a reply here.
Title: Re: UIToggle
Post by: stacktrace on December 22, 2013, 08:03:33 PM
I have a popup window with a set of 6 Grouped UIToggle controls.  I want the currently selected UIToggle to be the first on the list everytime the window is opened, rather than the last control that was selected when the window was last closed.

I am currently using the following code snippet when the window is opened:

  1. _selectToggles[0].value = true;
  2.  
  3. for (_indx = 1; _indx < _selectToggles.Count; _indx++)
  4. {
  5.        _selectToggles[_indx].value = false;
  6. }
  7.  

Where _selectToggles is a List<UIToggle> of all the controls in the group. 

However, when the window is reopened, it shows the Sprite specified as the State Transition sprite (of the UIToggle script) visible for both the first item and the last item that was selected when the window was last closed.  (I do not have an Animation attached)

Is there a way to reset the UIToggle state to its start state, or somehow force it to hide its attached "on" sprite?
Title: Re: UIToggle
Post by: ArenMook on December 23, 2013, 01:57:07 PM
Unfortunately I don't understand your explanation. What list? Some custom list? Why do you need the currently selected toggle to be first? What does selection have to do with it? Do you mean currently active toggle (value == true)?

Selection is not given to some specific component unless you do it yourself. In the controller menu example it's done via the UIButtonKeys script (UIButtonKeys.selectOnClick) and has nothing to do with toggles.
Title: Re: UIToggle
Post by: stacktrace on December 23, 2013, 02:34:20 PM
Sorry that I was not clear, looks like I interchanged "list" for "toggle group".  Let me try again.

I have a group of UIToggle components each attached to a separate UIWidget.  There is also a separate UISprite which is set as the "State Transition Sprite" property of a UIToggle.  These are arranged from top to bottom on a window with a UILabel with a description that overlaps the UIWidget areas, but is not parented to them.  The UISprite mentioned above is just a little bullet, so that whichever UIWidge the player clicks on, the bullet sprite appears next to the label, showing which item is currently selected.

I believe this is a relatively simple and standard setup, and it works just fine (just to be totally clear, all of the UIToggle components have the same Group ID set).

Here is the issue.

What happens by default, is that each time the window is shown, the bullet appears next to the last item clicked on.  The window is not recreated each time, just being hidden and made visible.  I understand this behavior and totally expect it.  But I want to change it.

The behavior I want, is that each time the window is shown, I want the bullet to appear next to the top label.  As I understand it, because the bullet sprite is set as the "State Transition Sprite" of a UIToggle component, its visibility is controlled by that UIToggle's value property.


My code logic was to call a custom function each time the window was opened that looped through all the UIToggle components in the toggle group, and set their value property to "false" except for the top most UIToggle, which would be set to "true".  I thought that this would give the desired result of only showing the Bullet sprite associated with the top most UIToggle only.

What is happening however is that when the window is opened for a second time, two bullet sprites are visible, the one associated with the top UIToggle (as desired) and the one which was visible when the window was closed the last time (unexpected).  (Note: by "top" I mean Y position on the screen as the UIWidgets the UIToggles are attached to are arranged vertically).


What I hope to find out:

- Should my logic work (and I have a problem elsewhere, perhaps with the notify handler used by the UIToggles in the group)?
- And if not, can you suggest an alternate solution/workaround?


Hopefully this is clearer, and not muddled up worse. 

I thank you for your time and help.
Title: Re: UIToggle
Post by: ArenMook on December 23, 2013, 03:27:29 PM
Depending on when you perform this action, the toggles may not be in the UIToggle.list yet. They get added in UIToggle.OnEnable, and removed in UIToggle.OnDisable. If you change the value of one, and other toggles are not yet in the list, then it won't be able to turn off the values of others properly.

Since you're setting the value of a group of toggles, you don't need to loop through them and set them to 'false'. Setting one of them to 'true' automatically sets others to 'false', provided the toggles have executed their OnEnable function already.

So long story short -- modify the script execution order to have your script run after the UIToggle.
Title: Re: UIToggle
Post by: stacktrace on December 23, 2013, 03:40:15 PM
Excellent, thank you for the quick reply!
Title: Re: UIToggle
Post by: shuihuyunyun on January 07, 2014, 09:49:08 PM
How can I use "UIToggledComponents" to receive the second C# script component in a GameObject?
So far, I can only drag the gameobject to the activate's or deactivate's Elements, only the first script of the gameobject could be loaded.
Title: Re: UIToggle
Post by: ArenMook on January 08, 2014, 01:58:57 PM
You can have more than one Inspector window open. You can also lock one inspector (use the lock icon on the top right), so that selecting objects won't clear it. Using this, you can drag & drop a component from one inspector window into a field of another inspector window. Not exactly an NGUI question. :)
Title: Re: UIToggle
Post by: shuihuyunyun on January 08, 2014, 07:23:09 PM
oh,sorry. It is not my question exactly.
I mean, how can I drag the "WindowAutoYaw" script(in the first picture) to Element1 of the "UIToggledComponents" component(picture 2)?

You see, only drag & drop do not work correctly, because I want Element1 to be "Lagposition(WindowAutoYaw)", not "Lagpositon(Lagposition)".
Title: Re: UIToggle
Post by: ArenMook on January 08, 2014, 10:12:22 PM
Yup, and my reply explains exactly that. Instead of drag & dropping the game object from the hierarchy window, you will be drag & dropping the actual script from one inspector window to another.
Title: Re: UIToggle
Post by: shuihuyunyun on January 08, 2014, 10:18:13 PM
aha, Thanks a lot.
Title: Re: UIToggle
Post by: PanCotzky on January 10, 2014, 09:24:18 PM
I'm trying to set my UIToggle a OnValueChanged receiver:

(http://cs408830.vk.me/v408830240/76a7/WarXeH5wYxI.jpg)

But I can't see a way to specify an event receiver method. When I check my UIToggle nothing happens. Trying to debug the reason for this, I've discovered that UIToggle just treats my receiver object as invalid EventDelegate and doesn't run it. Does this function even work? Or I should set all my callback up in the code? Could you please give me some hints on how to use this function (I mean, how to assign the callback receivers in the inspector)?
Title: Re: UIToggle
Post by: ArenMook on January 11, 2014, 06:38:36 PM
Without seeing your function declaration, how can I answer that question? ;)

It needs to be of public void FuncName () type. No parameters, void return, and must be 'public'.

UIToggle.current tells you which toggle triggered this delegate while inside the delegate callback.
Title: Re: UIToggle
Post by: lilyac on January 17, 2014, 10:41:08 AM
Hi Aren,

I seem to be having some issues with an unexpected behaviour with the UI Toggle's notify behaviour. It seems that the function specified in notify is called not only on change, but it is in fact also called once on start up/initialization, before any changes are made. Is there anyway to disable this behaviour or fix this issue ?
Title: Re: UIToggle
Post by: ArenMook on January 18, 2014, 10:31:58 PM
It's intentional for it to be called on start. It's done for consistency, to ensure that callbacks are in the proper state and match the toggle.
Title: Re: UIToggle
Post by: lilyac on January 20, 2014, 04:28:15 AM
understood, thank you !
Title: Re: UIToggle
Post by: FXCarl on February 03, 2014, 12:03:09 PM
How to know who called the callback inside the onChange callback method ?

Write a new script attach to toggle ? is this a "right" way ?

  1.  
  2.         UIToggle toggle;
  3.         GameObject target;
  4.  
  5.         public void OnChange(){
  6.                 target.SendMessage("OnChange", toggle, SendMessageOptions.DontRequireReceiver);
  7.         }
  8.  
  9.  
  10.  

Why not give event a parameter ?
Title: Re: UIToggle
Post by: ArenMook on February 04, 2014, 04:05:52 AM
  1. public void MyChangeFunc ()
  2. {
  3.     Debug.Log("Toggle: " + UIToggle.current.name + " has state of " + UIToggle.current.value);
  4. }
Title: Re: UIToggle
Post by: kaz2057 on February 11, 2014, 09:19:30 AM
I see with new update startChecked is public.

Can you explain me the difference between startActive vs startChecked?

what Starting State control?

Thanks
Title: Re: UIToggle
Post by: ArenMook on February 11, 2014, 09:05:01 PM
UIToggle.startsChecked is older (legacy) functionality, kept for consistency. It should actually not be public. UIToggle.startsActive should be used instead. I'll make it hidden again in the next version.
Title: Re: UIToggle
Post by: kaz2057 on February 12, 2014, 08:52:34 AM
but "statsActive" is equal to "StatingState"?
Title: Re: UIToggle
Post by: ArenMook on February 13, 2014, 03:20:46 AM
Yup.
Title: Re: UIToggle
Post by: natecope on February 17, 2014, 02:01:07 PM
It's intentional for it to be called on start. It's done for consistency, to ensure that callbacks are in the proper state and match the toggle.

I'm having an issue with this functionality. The event is fired on startup, and my code reacts when a toggle is changed. How do I get around that? Can I shut this off, or will that cause more issues? Is there a simple way to get around this without modifying NGUI code? I'm sure it's a simple logic change in my code, but I'm brainfarting hardcore right now regarding this.

thank you!
Title: Re: UIToggle
Post by: ArenMook on February 18, 2014, 10:52:00 AM
Subscribe to the toggle state change in your own script after you do your initialization. Don't be subscribed from the start.
Title: Re: UIToggle
Post by: natecope on February 18, 2014, 12:41:08 PM
Ah of course, how simple.

Inits happen in either Awake() or Start() in my game manager. Is the end of Start() a suitable place to start recognizing toggles?

Thank you for being responsive, btw. I've run into many assets where the author doesn't bother to answer questions, especially from noobs such as myself. It's appreciated.
Title: Re: UIToggle
Post by: ArenMook on February 20, 2014, 12:51:06 PM
Start is the best place, yup.
Title: Re: UIToggle
Post by: sunspider on March 04, 2014, 02:26:16 AM
I've created a tab group, set up the same way as the Tabs demo. Is there a way to toggle between the tabs in the editor, for ease of editing each page?
Title: Re: UIToggle
Post by: ArenMook on March 04, 2014, 03:37:03 AM
Select the page object, ALT+SHIFT+A to toggle its active state.
Title: Re: UIToggle
Post by: Quen on March 06, 2014, 11:03:51 AM
Hi, I got a question about toggle groups: I use a toggle group to select an answer in a quiz. When a new question shows up, I want the status(value) of all toggles to be false. But once I have selected one answer, I cannot deselect all anymore.
How can I reset the initial state of the whole group by script, so that all answers are deselected?

Thanks in advance!
Title: Re: UIToggle
Post by: ArenMook on March 06, 2014, 12:20:32 PM
Set UIToggle.optionCanBeNone = true, and you will be able to set them all to 'false'. Same as setting group to '0'. You will be able to set them all to 'false', and then restore the group afterwards.
Title: Re: UIToggle
Post by: Quen on March 09, 2014, 06:35:55 AM
Thank You

Worked perfectly :-)
Title: Re: UIToggle
Post by: devomage on June 07, 2014, 03:39:35 AM
I have a couple toggles as children of a uisprite working as a menu.

When i toggle the root gameobject in Start the check texture for both toggles disappear.  the values of both toggles are correct but the display is wrong.

  1. //Menu_Test_GO.SetActive(Menu_Test_Toggle);
  2.  

any ideas?  if i comment out the line in Start and leave the menu showing - the toggle works as it should.
Title: Re: UIToggle
Post by: ArenMook on June 07, 2014, 09:42:55 PM
Based on my understanding of your description, no -- I can't say that I do. I gave it a test on my end -- created a toggle as a child of a widget. Put a script on the widget that reacts to OnClick (and gave it a collider). In OnClick I set the SetActive state to the opposite of what it is now, targeting the child game object (the toggle). All works as expected.
Title: Re: UIToggle
Post by: devomage on June 08, 2014, 01:34:56 PM
after struggling with this for several days now.  i do not think it is specific to the uitoggle.  rather that the "check" texture is disappearing.  i am using ngui prefab's.

also, the background of the colored slider disappears around 90% of the time.  oddly enough it does appear at random though.  this control is also a child to the same background sprite.  all the controls/values are working correctly - its the disappearing texture that is the problem.  weird because another slider background works fine that isnt related to that group of controls.

attached is a screenshot of the hierarchy.  i will start over and see if the results are the same.


edit:  adding everything as a child to a parent panel has fixed the toggles.  it must have been some sort of depth issue in combination with bad hierarchy child.
Title: Re: UIToggle
Post by: Huacanacha on June 11, 2014, 04:36:21 PM
I had a problem with this script overriding the alpha of the activeSprite.  My 'on' state sprite had about 60% alpha but UIToggle would always set it to a glaring 100% opacity.  Here's my solution... I recommend adding something like this in an NGUI update.

1. Add a float targetAlpha field.

2. Put this first thing in Start()
  1. if (activeSprite != null) {
  2.         targetAlpha = activeSprite.color.a;
  3. }

3. Replace the 3-4 instances of "1f" with targetAlpha

Enjoy!
Title: Re: UIToggle
Post by: ArenMook on June 12, 2014, 02:41:49 AM
Don't modify code. Remember -- alpha is nested. So if you have this:

UIWidget (alpha 60%)
- Sprite (tween alpha)

...then everything will work as expected.
Title: Re: UIToggle
Post by: Huacanacha on June 12, 2014, 02:53:48 AM
Ok.  I've reverted to this method.  I'd much rather not modify code unless absolutely necessary.

It does seem counter-intuitive to me that a toggle has side effects.  Wouldn't turning the game object on/off be a much cleaner way to achieve this?
Title: Re: UIToggle
Post by: derkoi on June 15, 2014, 11:00:43 AM
I'm instantiating a group of Toggles but laid out like a list box (see attached image) for each .txt file in a folder.

I need to know if any of the Toggles in the groups state has changed and if so, run a function in my script. Now I know I can get the active toggle but I'm not sure when I should do this? Not every frame I assume? Hence why I'd like to know when a toggle in the groups state has changed then I can get the active toggle and process accordingly.

So, how can I find which toggle in a group is active only when the selection changes?

Thanks
Title: Re: UIToggle
Post by: ArenMook on June 16, 2014, 09:12:12 AM
@Huacanacha: Toggle transitions smoothly by adjusting the alpha. Swapping active state won't give a smooth transition.

@derkoi: UIToggle.curent always tells you what toggle triggered the event, and UIToggle.list is an up-to-date list of all the active toggles in the scene that you can loop through if you like.
Title: Re: UIToggle
Post by: ArtemKoval on July 07, 2014, 05:06:08 AM
Hi!

I'm not sure whether my question belongs here, but it's for sure related to UIToggle.

I've got simple controls setup:
1. Grid of buttons which are tabs headers. Buttons have UIToggle and UIToggled objects.
2. For each header tab I've got Widget -> ScrollView -> Grid -> Bunch of buttons.
3. Each header tab is set up to activate it's ScrollView and deactivate others.

Each button in a ScrollView has a script attached with logic to disable this button and disable specified button in other ScrollView (which is inactive at the time when child button is disabled).

So logically everything works fine. But I've got strange visual effect.

1. Press and effectively disable button in active scroll view
2. Then click on other header tab and its' ScrollView become visible
3. (BUG) For a split second disabled button in a newly activated ScrollView is enabled and then it become disabled.

What can be the source of such problem?

Thanks, Artem.
Title: Re: UIToggle
Post by: ArenMook on July 08, 2014, 01:20:52 PM
Only set things it should activate. The deactivate state is going to be done by default.
Title: Re: UIToggle
Post by: ArtemKoval on July 08, 2014, 01:56:28 PM
Hi!

It's setup like you've said. But unwanted effect is still there. Please take a look at this short video https://dl.dropboxusercontent.com/u/19764309/Caelum%202014-07-08%2022-48-05-01.avi

And this is screenshot of how things are setup at the moment
Title: Re: UIToggle
Post by: ArenMook on July 09, 2014, 02:34:46 PM
Button state change is not immediate unless you make it so. Look at UIButton.SetState function. It has a boolean that determines whether the change should be immediate or not.
Title: Re: UIToggle
Post by: ArtemKoval on July 10, 2014, 01:25:02 AM
Hi!

Thanks, that was the problem together with minor logic bug.

Regards, Artem.
Title: Re: UIToggle
Post by: jimbob926 on July 15, 2014, 11:09:23 AM
How do I make it so that the original sprite fades out and the new one fades in, like a toggleable button? At the moment, the new sprite just gets faded in on top of the original one.
Title: Re: UIToggle
Post by: ArenMook on July 16, 2014, 12:02:01 AM
Exactly like that. Have one sprite cover the other and fade out the top one.
Title: Re: UIToggle
Post by: devomage on August 07, 2014, 04:08:48 AM
after struggling with this for several days now.  i do not think it is specific to the uitoggle.  rather that the "check" texture is disappearing.  i am using ngui prefab's.

also, the background of the colored slider disappears around 90% of the time.  oddly enough it does appear at random though.  this control is also a child to the same background sprite.  all the controls/values are working correctly - its the disappearing texture that is the problem.  weird because another slider background works fine that isnt related to that group of controls.

attached is a screenshot of the hierarchy.  i will start over and see if the results are the same.


edit:  adding everything as a child to a parent panel has fixed the toggles.  it must have been some sort of depth issue in combination with bad hierarchy child.

when loading a large amount of data in the Start() method, NGUI in general does weird stuff.  i moved my data init's to another scene and it fixed the oddities completely.  for example, my scrollview scrollbars were disabling themselves randomly at start.  similar to the uitoggle problems several weeks back.

fyi for someone who might have a similar problem...
Title: Re: UIToggle
Post by: hangemHigh on September 06, 2014, 04:20:07 AM
I want to toggle UIToggle programmatically. I've been stuck here for hours. Is there any function to do this?
Below is what I have.
public UIToggle soundchkbox;
soundchkbox= soundchkbox.GetComponent<UIToggle>();
soundchkbox.startsActive = true;

I can read the value but I want to be able to toggle it programmatically. Any help will be appreciated. Thanks.

Title: Re: UIToggle
Post by: ArenMook on September 07, 2014, 08:51:17 AM
UIToggle.value = true;
Title: Re: UIToggle
Post by: radu1234 on October 28, 2014, 06:59:34 PM
Hello,

Hope this isn't already answered somewhere else. So I have two UIToggles which both do exactly the same thing, but are placed on different "pages" and have different names. And I want when I modify one of them, the other to change it's state automatically. Basically like reverse radio buttons, when I press one, the other changes accordingly to match it, not be opposite.

Is there an easy way to do this ?

Thank you in advance ! Great GUI by the way ;)
Title: Re: UIToggle
Post by: ArenMook on October 29, 2014, 05:37:11 AM
Hmm... well, you can have one toggle's OnChange state call a function that would set the other's state as well. Problem is I assume you want it backwards as well, but if you set the 2nd one's state to change the first, then you effectively end up with a circular reference, which is bad. I would suggest having some kind of a controller class. When you change one toggle's value, it tells the controller which then ensures that both toggles have the correct state.
Title: Re: UIToggle
Post by: radu1234 on October 29, 2014, 09:29:47 AM
Hmm, I understand, so i'll have to program some trick to do it.

Thanks a lot for your quick response ;)

Have a nice day !
Title: Re: UIToggle
Post by: PabloAM on November 07, 2014, 12:53:03 PM
Hello I have done a toggle buttons that shows a list.

When loads Scene, the button is clicked and shows correct list. But when I press a button to move the panels of list, button toggle disappear.

Why that happen?

Attached some screens:


Thanks!!
Title: Re: UIToggle
Post by: srgcrafty on January 29, 2015, 04:00:43 PM
Hey ArenMook,

I am having an issue with the fact that UIToggle calls OnValueChanged on startup. I have a couple UIToggles in a menu, as part of a HUD, one of which is for enabling/disabling the minimap. Because this menu is not enabled when the payer starts the game, and only when they hit the Options button, I don't want the minimap to suddenly get turned off (or on for that matter) when they open up the menu with the UIToggle component in it. Is there a way to make sure that this is not called when the player first opens up the menu (thus, disabling the GameObject)?

Thanks
Title: Re: UIToggle
Post by: ArenMook on January 30, 2015, 03:06:41 PM
OnValueChanged is called for consistency to ensure that the callbacks are in the same state as the toggle. If you don't want it, check something inside your callback itself -- is it done loading etc? No? Ignore.
Title: Re: UIToggle
Post by: KeithT on October 23, 2015, 03:45:27 AM
We have 3 windows, each of which have their own buttons which run a tween to open and close them. The buttons also have a toggle to highlight or not depending on whether the window is open or closed.

Each button can also close either of the other windows if the are open, by running the other window's tween.

The problem is how to control the toggle on the button associated with the "other" windows.

I can't see how to do this using standard NGUI features, and after having been through all the posts on here but don't see how to control the state of a toggle from script.

Thanks in advance for any suggestions.
Title: Re: UIToggle
Post by: ArenMook on October 24, 2015, 04:59:07 AM
Control the toggle on the button associated with the other windows? I am not sure what you mean.

Assuming your toggles are in the same group, one toggle's activation will automatically deactivate others.
Title: Re: UIToggle
Post by: KeithT on October 29, 2015, 03:43:55 AM
Thanks for the response, have found it which is simply:

UIToggle B1Tog = GameObject.Find("B1").GetComponent<UIToggle>();
B1Tog.value = false;
Title: Re: UIToggle
Post by: amraffay on October 02, 2016, 02:42:01 PM
In some other ui kits, whenever there is UIToggle, there is also another component like ToggleGroup which is used for adding event listeners.

Currently if we have 10 toggles with a group of lets say 2 (radio buttons) then we have to attach event to all those 10 toggles. But with a single ToggleGroup we can do the same thing.

I checked UIToggle code
  1. // Uncheck all other toggles
  2.                         if (group != 0 && state)
  3.                         {
  4.                                 for (int i = 0, imax = list.size; i < imax; )
  5.                                 {
  6.                                         UIToggle cb = list[i];
  7.                                         if (cb != this && cb.group == group) cb.Set(false);
  8.                                        
  9.                                         if (list.size != imax)
  10.                                         {
  11.                                                 imax = list.size;
  12.                                                 i = 0;
  13.                                         }
  14.                                         else ++i;
  15.                                 }
  16.                         }

A quick dirty solution is to dispatch a static event from there, so no need of a adding listeners to all 10 toggles.

Can you provide a better solution here?
Title: Re: UIToggle
Post by: ArenMook on October 11, 2016, 10:55:21 AM
You don't need to assign listeners to all of them. Just one. When you have a grouped toggle, activating one will automatically deactivate another. Inside your callback, simply check which toggle in your group has the 'true' state.