Corona SDK: Avoid touch events through layered screens

Haakon Langaas Lageng

This trick is really handy. If you ever find yourself struggling with layered screens and touch events propagating through the screen in front, triggering something on the screen behind, you'll soon know a really simple way to solve it...

Imagine you have a screen with a lot of touchable elements, for instance a list. Imagine that you also have a button somewhere on the screen that loads a modal window on top of the before mentioned screen. It can look like this:

The main screen, before loading a modal window on top.

The modal screen has been loaded on top of the main screen, but the main screen’s items are still reacting to touch events.

If the user touches outside the modal window’s buttons, the items on the main screen can be triggered – they are still alive and receiving touch events. Create a rectangle that fills the screen, alpha it to 0 and add touch and tap events to it that does nothing but return.

local rect = display.newRect(0, 0, 960, 640)
rect.alpha = 0
rect.isHitTestable = true -- Only needed if alpha is 0
rect:addEventListener("touch", function() return true end)
rect:addEventListener("tap", function() return true end)

You can of course use the rect for greying out the background by setting a background color and an alpha higher than 0, like we did in the example images above.

Jonathan Beebe has written a great blog post called The Corona Event Model explained, read it if you want to get to know the event model well.

Ansca has superb documentation on events as well. Here’s the relevant excerpt:

Hit events propagate until they are handled. You can stop propagation to the next object (all listeners of the current object still get the event) by telling the system that the event was handled. This boils down to making a listener return true. If at least one of the listeners of the current object returns true, event propagation ends; the next object will not get the event. If the event is still unhandled at the end of this traversal, it is broadcast as a global event to the global Runtime object.