Author Topic: Want UI elements to detect clicks outside themselves. [Solved]  (Read 1787 times)

Peacewise

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 12
    • View Profile
Hello,

Let's say I have a UI Panel that covers part of the screen, and other UI buttons in the HUD outside the panel that trigger other panels. I want to do two things:

  • If the player clicks outside the panel, I want the panel to close.
  • Additionally, if the player's click falls outside the panel on another button, I'd like it to close the current panel and open the new target panel.

I could hack #1 by adding an invisible collider in the empty space around each panel, but that would make #2 difficult. And I'd rather not have to add extra colliders to every panel I have.

What I'm looking for is a way for each UI element to receive an event like, "There was a click and it wasn't on me." That way I could use that to deactivate the panel, and the click can then run its normal course, whether it fell on another UI button or not.

Is there a way to do this?
« Last Edit: June 19, 2014, 02:30:03 PM by Peacewise »

Peacewise

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: Want UI elements to detect clicks outside themselves.
« Reply #1 on: June 19, 2014, 02:29:02 PM »
Okay, I've coded up a solution in the form of a component that I can put on any panel that I want to exhibit this auto-close behavior on external taps. If someone has a better way, or if there's some accepted method, let me know.

Here's the code if anyone is curious. The "Timer" and "InputManager" are my own classes, but this should be readable enough to communicate how it works:

  1.  
  2.  
  3. using UnityEngine;
  4.  
  5. /// <summary>
  6. /// Attach this Component to an NGUI object to disable it any time a tap occurs outside of it and its children.
  7. /// </summary>
  8. public class Component_NGUI_CloseWithExternalTap : MonoBehaviour
  9. {
  10.         /// <summary>This makes the UI immune to auto-closing with this behavior within this amount of time after the ui becomes active.
  11.         /// In particular, this helps prevent the same touch that enables the UI to count as an external touch that will then disable it (this was
  12.         /// a problem on tablet with double-taps).</summary>
  13.         private Timer m_delayTimer = new Timer(0.2f); // Seconds
  14.  
  15.         void OnEnable()
  16.         {
  17.                 m_delayTimer.Reset();
  18.         }
  19.  
  20.         void Update()
  21.         {
  22.                 // While the delay timer is active, this component won't be able to auto-disable the UI. (See note above on the timer.)
  23.                 if(m_delayTimer.Going)
  24.                 {
  25.                         m_delayTimer.Update(Time.deltaTime);
  26.                         return;
  27.                 }
  28.  
  29.                 if(InputManager.InputJustPressed(KeyInputID.MainAction) == false)
  30.                 {
  31.                         // No tap this frame
  32.                         return;
  33.                 }
  34.  
  35.                 if(UICamera.hoveredObject == null)
  36.                 {
  37.                         // Tap this frame, and it was not on any UI. Close this ui element!
  38.                         this.gameObject.SetActive(false);
  39.                         return;
  40.                 }
  41.  
  42.                 if(UICamera.hoveredObject.transform.IsChildOf(this.transform) == false)
  43.                 {
  44.                         // Tap this frame, and it was not on this object or any of its children. Close this ui element!
  45.                         this.gameObject.SetActive(false);
  46.                         return;
  47.                 }
  48.         }
  49. }
  50.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Want UI elements to detect clicks outside themselves. [Solved]
« Reply #2 on: June 19, 2014, 06:48:05 PM »
I do something similar in case of a popup list in order to close it. What I do is give selection to the popup list, and close it when I get the OnSelect(false) notification. OnSelect(false) is guaranteed to be sent to the selected object when the user presses on something else.