Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

OnDeselect and OnClick order

Discussion in 'UGUI & TextMesh Pro' started by illinar, Feb 17, 2015.

  1. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    857
    I'm implementing a dropdown button and I'm using Deselect event to catch a click outside of the dropdown list, when it is active, to close it. But I cant click on the buttons in dropdown menu because as soon as I click them the list gets deselected and Click does not register.

    I can work around that by delaying deactivation of the list by one frame, but is there another way to control an order of events?

    Edit: coroutines won't work for me since my time scale is 0... But I'm surprized that this doesn't work:

    public void OnDeselect ()
    {
    StartCoroutine("DeselectCoroutine");
    }

    public IEnumerator DeselectCoroutine ()
    {
    yield return new WaitForEndOfFrame();
    yield return new WaitForEndOfFrame();
    yield return new WaitForEndOfFrame();
    yield return new WaitForEndOfFrame();
    yield return new WaitForEndOfFrame();
    yield return new WaitForEndOfFrame();
    Fold();
    }

    OnDeselect() gets called normally, then few frames later the Fold() method disables the dropdown list. But still buttons on it don't recieve OnClick event! When I disable OnDeselect event, buttons do work.
     
    Last edited: Feb 17, 2015
  2. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
  3. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    857
    Thank you. Although I just need to deal with Deselect. I already got the small extendable class that fits my needs perfectly and generates dropdown button based on my projects data.

    This reliable and elegant solution worked:
    Code (CSharp):
    1.     public IEnumerator DeselectCoroutine ()
    2.     {
    3.         yield return new WaitForEndOfFrame();
    4.         yield return new WaitForEndOfFrame();
    5.         yield return new WaitForEndOfFrame();
    6.         yield return new WaitForEndOfFrame();
    7.         yield return new WaitForEndOfFrame();
    8.         yield return new WaitForEndOfFrame();
    9.         yield return new WaitForEndOfFrame();
    10.         yield return new WaitForEndOfFrame();
    11.         yield return new WaitForEndOfFrame();
    12.         yield return new WaitForEndOfFrame();
    13.         yield return new WaitForEndOfFrame();
    14.         yield return new WaitForEndOfFrame();
    15.         yield return new WaitForEndOfFrame();
    16.         yield return new WaitForEndOfFrame();
    17.         yield return new WaitForEndOfFrame();
    18.         yield return new WaitForEndOfFrame();
    19.         yield return new WaitForEndOfFrame();
    20.         yield return new WaitForEndOfFrame();
    21.         yield return new WaitForEndOfFrame();
    22.         yield return new WaitForEndOfFrame();
    23.         yield return new WaitForEndOfFrame();
    24.         yield return new WaitForEndOfFrame();
    25.         yield return new WaitForEndOfFrame();
    26.         yield return new WaitForEndOfFrame();
    27.         yield return new WaitForEndOfFrame();
    28.         yield return new WaitForEndOfFrame();
    29.         yield return new WaitForEndOfFrame();
    30.         yield return new WaitForEndOfFrame();
    31.         yield return new WaitForEndOfFrame();
    32.         yield return new WaitForEndOfFrame();
    33.         yield return new WaitForEndOfFrame();
    34.         Fold();
    35.     }
    But what's the proper way to do this? Is UI event system work in t's own parallel timeline?
     
    Last edited: Feb 18, 2015
  4. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    857
    The best worst solution I've found so far is to use Selectable component instead of Button, because delay between Deselect event and Click event is about 100 - 200 ms, and delay between Deselect and Select is one frame. OnPointerDown works with the delay also, but intuitively I would expect it to work before Deselect happens...

    But that will do. That does look reliable at least.
     
    Last edited: Feb 18, 2015
  5. BluishGreenPro

    BluishGreenPro

    Joined:
    May 14, 2017
    Posts:
    8
    I'm sure this answer comes too late to be useful to the original asker, but having come up against the same problem myself, here is the solution I arrived at; Use information about whether the mouse pointer is above the UI panel to determine if the menu should ACTUALLY be closed on a click. I also found it necessary to constantly reset the "SelectedGameObject" to the panel on pointer exit / enter. Here's everything you should need to make this work:
    Code (CSharp):
    1. using UnityEngine.EventSystems;
    2.       public class CLASSNAME : MonoBehaviour, IDeselectHandler, IPointerEnterHandler, IPointerExitHandler
    3.       {
    4.  
    5.        private bool mouseIsOver = false;
    6.  
    7.        private void OnEnable() {
    8.             EventSystem.current.SetSelectedGameObject(gameObject);
    9.         }
    10.  
    11.         public void OnDeselect(BaseEventData eventData) {
    12.     //Close the Window on Deselect only if a click occurred outside this panel
    13.             if (!mouseIsOver)
    14.                 CloseSelf();
    15.         }
    16.  
    17.         public void OnPointerEnter(PointerEventData eventData) {
    18.             mouseIsOver = true;
    19.             EventSystem.current.SetSelectedGameObject(gameObject);
    20.         }
    21.      
    22.         public void OnPointerExit(PointerEventData eventData) {
    23.             mouseIsOver = false;
    24.             EventSystem.current.SetSelectedGameObject(gameObject);
    25.         }
    26. }
     
  6. Braza

    Braza

    Joined:
    Oct 11, 2013
    Posts:
    126
    On mobile I still get many cases when OnDeselect arrives earlier than OnPointerEnter...