Corona Reference: Events

Any interactive app must include some events. There are two major types of event: runtime and local. Runtime events are triggered in response to changes outside the app, such as a change in screen orientation, an incoming phone call, a change in GPS coordinates, etc. Local events are triggered by the user touching a display object on screen, a timer, a physics collision, etc.

The most common event we'll be using are tap and touch events. These events allow the user to interact with the app by touching display objects on screen. A listener must be attached to these objects. When the listener detects an event, a function (often called a handler) is called, resulting in a response to the touch.

Tap and Touch Events

Tap Events

    A tap event occurs when the user taps the screen. The event does not trigger any action until the user releases the point. To add a tap event listener to a display object, use the format
    OBJECT:addEventListener( "tap", handler_name ) 
    The handler is generally defined prior to the object listening for the event, as follows:
    local function handler_name( event )
    	-- action
    end
    
    OBJECT:addEventListener( "tap", handler_name )
    A tap event is the simplest hit event to deal with in Corona, but it does not carry as much information as other events we can listen for. The length of the tap, for instance, is irrelevant. Pressing an object with a tap listener will not cause the handler to fire until the press ends.

Touch Events

    Touch events are similar to a tap event, in that they occur when the user touches a display object. However, touch events are more flexible, as they have more attributes and can pass more information to the handler. The event handler can trigger one action when the touch begins, and another when it ends. This way, we can use a touch event to track the length of the touch, track motion, and more. Adding a touch event listener to a display object is very similar to adding a tap event:
    OBJECT:addEventListener( "touch", touch_handler )
    where "object" is the name of the object you will be touching, and "touch_handler" is the name of the function that will fire when this object is touched.

    The following read-only properties are useful within touch handlers (note that these properties apply only to "touch" events, not "tap"):

    event.phase
    This property is a string which indicates which phase the touch event is currently in. There are four values this string can take:
    • "began" is the initial phase of a touch event, when a touch is first detected.
    • "moved" indicates that the user’s finger has moved on the screen without releasing the object.
    • "cancelled" indicates the touch is no longer being tracked. This may occur when the user’s finger remains on the screen, but has slid off the object.
    • "ended" indicates the user has removed their finger from the screen.

    event.xStart and event.yStart
    These properties give the x and y coordinate of the beginning of the touch. When tracking motion, it's often helpful to compare these values to the event.x and event.y properties, which give the current location of the touch.

Tap and Touch Properties

    The following read-only properties are commonly used within tap and touch handlers:

    event.target
    In a tap or touch handler, event.target refers to the object that received the touch. This is particularly useful when multiple objects share the same event handler. Instead of referring to the object by name in the handler, we can refer to the object that is currently being tapped.

    event.x and event.y
    These properties give the x and y coordinate of the tap or touch. These values update throughout a touch event, tracking the latest location of the touch.

    event.numTaps
    This property of a tap event can be used to detect a single or double tap, and has a value of either 1 or 2.

Tap and Touch Examples

Counting Taps

    In this example, we’ll create a text object in the center of the screen. The text will have an event listener, and will change according to the number of times it has been tapped. To accomplish this, we’ll need to create a counter which will increase by 1 each time a tap occurs. As usual, we’ll declare all variables (including the counter, the text, and the function itself) in the first line of code. We’ll also print the number of taps to the terminal.
    local myText, changeText, counter
    
    counter = 0
    
    function changeText( event )
       counter = counter + 1
       myText.text = "I’ve been tapped ".. counter .. " times" 
       print( counter.." taps")
    	 
       return true
    end
    
    myText = display.newText( "I’ve been tapped 0 times", display.contentCenterX, display.contentCenterY, Arial, 40 )
       myText:setFillColor( 1, 1, 1 )
       
    myText:addEventListener( "tap", changeText )
    As the counter changes, we can update the text using some useful features of the Lua string library. To concatenate strings, we use the .. symbol. This tells Lua to paste two strings together. In this case, we paste three strings - the first one is simply "I’ve been tapped", the second is the counter value, and the last is " times". Lua will automatically convert this value to a string when it appears in a concatenation, so we don’t have to create another string. Notice that spaces will not be put in automatically between strings being pasted together, so we’ve included those in the strings themselves.

Touch Phases

    We’ll draw a square will turn blue when we first touch it, and green when we release.
    local myRectangle, changeRectangle
    
    function changeRectangle( event )
       if ( event.phase == "began" ) then
          myRectangle:setFillColor( 0, 0, 1 )
       elseif ( event.phase == "ended" ) then
          myRectangle:setFillColor( 0, 1, 0 )
       end
    	
       return true
    end
    
    myRectangle = display.newRect( 200, 300, 50, 50 )
       myRectangle:setFillColor( 1, 0, 0 )
    myRectangle:addEventListener( "touch", changeRectangle )
    This is meant to be a minimal example; you'll probably want your handler to include actions for when the event is "cancelled" as well.

Single vs Double Taps

    This time, we’ll draw a rectangle called "myRectangle" on screen, and set it to listen for a tap event. When such an event is detected, we’ll change the color of the rectangle using a function called "changeRectangle".
    local myRectangle, changeRectangle
    
    function changeRectangle( event )
       if event.numTaps == 1 then
          myRectangle:setFillColor( 0, 0, 1 )
       else
          myRectangle:setFillColor( 0, 1, 0 )
       end
    	
       return true
    end
    
    myRectangle = display.newRect( 200, 300, 50, 50 )
       myRectangle:setFillColor( 1, 0, 0 )
       	
    myRectangle:addEventListener( "tap", changeRectangle )
    When tapped a single time, the rectangle will turn blue. When double tapped (two quick taps in succession), the rectangle will turn green.

Color Picker

    The following example is a simple application of a touch event. A single rectangle, the size of the content area, is created and centered on screen. It listens for a touch event. When an event is detected, the initial instructions are made transparent. As the user moves their finger around on screen, the color of the rectangle is changed according to the user’s current touch position. The red value is fixed, but blue is adjusted on a scale from 0 to 1 as the touch moves from left to right, and green is adjusted on a scale from 0 to 1 as the touch moves from top to bottom. Finally, when the touch event ends, the RGB color values are rounded up to the nearest integer and displayed on screen.
    local instructions, bigRectangle, colorChanger
    
    local w = display.contentWidth     
    local h = display.contentHeight 
       
    function colorChanger( event )
       local blueinc = 1/w      -- Percentage of blue per pixel; blue will change with x coordinate
       local greeninc = 1/h     -- Percentage of green per pixel; green will change with y coordinate
    	
       if ( event.phase == "began" ) then
          instructions.alpha = 0     			-- Hide text
       elseif ( event.phase == "moved" ) then
          bigRectangle:setFillColor(0.3, event.x*blueinc, event.y*greeninc)
       elseif ( event.phase == "ended" or event.phase == "cancelled" ) then
          local newred = math.ceil( 0.3*255 )     	-- Round up RGB values
          local newblue = math.ceil( event.x*blueinc * 255 )	
          local newgreen = math.ceil( event.y*greeninc * 255 )
          instructions.text = "RGB Color is ("..newred..", "..newgreen..", "..newblue..")"
          instructions.alpha = 1
       end
    	
       return true
    end
    
    bigRectangle = display.newRect( w/2, h/2, w, h )
       bigRectangle:setFillColor( 1, 1, 1 )
       bigRectangle:addEventListener( "touch", colorChanger )
    	
    instructions = display.newText( "Drag your finger around the screen", w/2, h/2, Arial, 20 )
    instructions:setFillColor( 0, 0, 0 )

Multiple Listeners

    We’ve seen how to use a single event handler for multiple objects. We may also have occasion to use multiple handlers for the same object, and even the same type of hit event. We’ll create a rectangle that will have two event listeners, one awaiting a tap and another awaiting a touch. Touching the rectangle will cause it to turn green until the touch ends, when it turns red. Tapping the rectangle returns it to white.
    local myBlock, tapHandler, touchHandler
    
    function tapHandler( event )
       event.target:setFillColor( 1, 1, 1 )
    	
       return true
    end
    
    function touchHandler( event )
       if event.phase == "began" then
          event.target:setFillColor( 0, 1, 0 )
       elseif event.phase == "ended" then
          event.target:setFillColor( 1, 0, 0 )
       end
    	
       return
    end
    
    myBlock = display.newRect( display.contentWidth/2, display.contentHeight/2, 60, 60 )
       myBlock:addEventListener( "touch", touchHandler )
       myBlock:addEventListener( "tap", tapHandler )

Return True

The event handlers in the previous examples ended with the phrase return true. This is not always necessary (and in some cases may not be wanted), but helps avoid some unintentional events from being fired. This command allows you to layer display objects, each with their own event listeners, and prevent these events from interfering with each other.

Consider two rectangles that are overlapping, each with their own event listener. If the user taps the top rectangle, it’s event handler will go into action. But if that handler does not include the return true command, the tap will continue to propagate through to the rectangle below, whose event handler will then fire. In other cases, you may accidentally assign the same event listener to an object more than once. This is generally not a problem, as long as the handler includes return true.

It is a good idea to be in the habit of using return true in your event handlers, unless you have a specific need to avoid it.

Dragging Objects

Many apps require the user to drag an object from one location on the screen to another. We’ve seen an example of how to move an object using an event handler, but the object went to a predefined (or random) location. To create a draggable object, we’ll tell it to listen for a touch event that triggers a dragging function. Conveniently, we only need to define this function once, even if we have multiple objects that will require dragging. This is because we’ll taking advantage of the event.target property - whichever object triggers the function will be the one that moves.

If you're just looking to create a function that does the job of moving an object on the screen, you can use
function dragObject( event )
	if event.phase == "began" then
		self = event.target
		self.markX = self.x
		self.markY = self.y
	elseif event.phase == "moved" then
		self.x = event.x - event.xStart + self.markX
		self.y = event.y - event.yStart + self.markY
	end
	
	return true
end
We’ll walk through what’s going on here. As in the previous handlers for touch events, we have multiple phases of the touch event to deal with. In the first phase, which begins as soon as the user touches the object, we begin by defining a variable called "self" to represent the object begin touched. If more than one object uses this same event handler, whichever one is currently being touched is now called "self" within the function. Next, we record the initial location of the object with the markX and markY properties. These are not Corona defined properties, but rather names we made up. You’re free to use any other property name you like, though these are the ones traditionally used among Corona developers. We set the value self.markX to be the current x coordinate of the object’s anchor point at first touch, and similarly, self.markY is the current y coordinate.

This function will now take advantage of the "moved" event phase. As the user continues to hold the object and move their finger around the screen, the location of "self" is changed by calculating how much the user’s finger has moved, then adding the original position of the object. The x and y coordinates are handled separately. Finally, we return true to make sure we’re not dragging other objects around inadvertently.

Example

    The following code produces a circle that can be dragged around the screen:
    function dragObject( event )
    	if event.phase == "began" then
    		self = event.target
    		self.markX = self.x
    		self.markY = self.y
    	elseif event.phase == "moved" then
    		self.x = event.x - event.xStart + self.markX
    		self.y = event.y - event.yStart + self.markY
    	end
    
    	return true
    end
    
    local myCircle = display.newCircle( 100, 100, 75)
    	myCircle:setFillColor( 1, 1, 1 )
    	myCircle:addEventListener( "touch", dragObject )

Multitouch Events

Both iOS and Android devices are able to detect multitouch events. If you’ve ever pinched your fingers together on screen to make an image smaller, or played a game that required touching the screen in more than one location, then you’ve made use of this feature. Warning While Corona is able to produce apps capable of detecting multitouch events, the simulator is NOT. Running such an app in the simulator will produce this warning, and you will not be able to test your multitouch functions without an actual device. Before we can create an object that listens for a multitouch event, we’ll need to tell the system to activate this feature. We can do this by including the line
system.activate("multitouch")
at the beginning of our main.lua file. It doesn’t really matter where we place it, as long as it appears before adding an event listener. Activating multitouch means that any touch listener has multiple touches in its event variable, each one being given a distinct id. While this generally won’t affect our code, we will see the event.id value appearing on occasion, such as in the improved dragging function below.

A Better Dragging Function

    To resolve the problems caused by a second touch on the screen, we’ll need to make sure that the function focuses only on the touch that triggered the function. This isn’t to say other touches will be ignored - a second touch might be simultaneously triggering another function. In fact, two different objects could be using this same function at the same time. But any other touches that do not apply to the current event target shouldn’t affect the object, and preventing such a scenario from happening requires only minor modification to our code:
    function dragObject( event )
    	if event.phase == "began" then
    		self = event.target				-- abbreviation for event.target
    		display.getCurrentStage():setFocus( self, event.id )	-- focus on this object
    		self.isFocus = true				-- an attribute we've defined for the object self
    		self.markX = self.x				-- record starting x and y values
    		self.markY = self.y
    	elseif self.isFocus then
    		if event.phase == "moved" then	
    			self.x = event.x - event.xStart + self.markX		-- move object to new touch position
    			self.y = event.y - event.yStart + self.markY
    		elseif event.phase == "ended" or event.phase == "cancelled" then
    			display.getCurrentStage():setFocus( self, nil )		-- remove focus
    			self.isFocus = false
    		end 
    	end
    	
    	return true
    end
    Now, we still have an if-then statement, and the first part of it says what to do if the touch has just begun. We again define self = event.target, and then use the setFocus function of Corona to set this object as the current thing we’re focusing on, so no other objects will be affected and no other touches will be used in our calculations. We’ll then create another property called isFocus (again, our naming and not an official Corona property) and set it to true.

    As the user continues the touch, we’re no longer jumping right to the "moved" phase. Instead, we’ll move to the second part of the overall if-then statement, since it is defined to run whenever we’re no longer in the "beginning" phase of the touch and whenever isFocus is set to true. Since both of these requirements are met, we go to an inner if-then statement to see what to do next. As the user moves their finger (the one we’re focusing on) we’re in the "moved" phase of the touch, and we’ll move the object just as we did earlier. As soon as the touch is ended, we go to the "ended" or "cancelled" phase. We didn’t include this in the shorter dragging function, and it doesn’t appear to add much here. But this is where we release the focus of our object and the touch, and set the property isFocus to false to prevent any more motion from occurring.

Pinch-to-Zoom

Many apps will make use of multitouch gestures to scale, drag, and zoom objects. Unfortunately, only dragging can be tested in the simulator. However, if you'd like to apply a pinch-to-zoom function to an object, you can use the code below:
function pinchtozoom( event )
   local phase = event.phase
   local eventTime = event.time

   local previousTouches = self.previousTouches   

   if not self.xScaleStart then
      self.xScaleStart, self.yScaleStart = self.xScale, self.yScale
   end
	
   local numTotalTouches = 1
	
   if previousTouches then
      numTotalTouches = numTotalTouches + self.numPreviousTouches
      if previousTouches[event.id] then
         numTotalTouches = numTotalTouches - 1
      end
   end
	
   if "began" == phase then
      if not self.isFocus then
         display.getCurrentStage():setFocus( self )
         self.isFocus = true

         self.x0 = event.x - self.x
         self.y0 = event.y - self.y

         previousTouches = {}
         self.previousTouches = previousTouches
         self.numPreviousTouches = 0
         self.firstTouch = event    
      elseif not self.distance then
         local dx,dy
         local cx,cy

         if previousTouches and numTotalTouches >= 2 then
            dx,dy = calculateDelta( previousTouches, event )
            cx,cy = calculateCenter( previousTouches, event )
         end

         if dx and dy then
            local d = math.sqrt( dx*dx + dy*dy )
				
            if d > 0 then
               self.distance = d
               self.xScaleOriginal = self.xScale
               self.yScaleOriginal = self.yScale

               self.x0 = cx - self.x
               self.y0 = cy - self.y
            end
         end   
      end

      if not previousTouches[event.id] then
         self.numPreviousTouches = self.numPreviousTouches + 1
      end
		
      previousTouches[event.id] = event

   elseif self.isFocus then
      if "moved" == phase then
         if self.distance then
            local dx,dy
            local cx,cy
				
            if previousTouches and numTotalTouches == 2 then
               dx,dy = calculateDelta( previousTouches, event )
               cx,cy = calculateCenter( previousTouches, event )
            end
							
            if dx and dy then
               local newDistance = math.sqrt( dx*dx + dy*dy )
               local scale = newDistance / self.distance
									
               if scale > 0 then
                  self.xScale = self.xScaleOriginal * scale
                  self.yScale = self.yScaleOriginal * scale
                  self.x = cx - ( self.x0 * scale )
                  self.y = cy - ( self.y0 * scale )
               end
            end
				
         else
            if event.id == self.firstTouch.id then
               self.x = event.x - self.x0
               self.y = event.y - self.y0
            end
         end
			
         if event.id == self.firstTouch.id then
            self.firstTouch = event
         end
			
         if not previousTouches[event.id] then
            self.numPreviousTouches = self.numPreviousTouches + 1
         end
			
         previousTouches[event.id] = event
					
      elseif "ended" == phase or "cancelled" == phase then
					
         local dx = math.abs( event.xStart - event.x )
         local dy = math.abs( event.yStart - event.y )
			
         if eventTime - previousTouches[event.id].time < 150 and dx < 10 and dy < 10 then
            if not self.tapTime then
               self.tapTime = eventTime
               self.tapDelay = timer.performWithDelay( 300, function() self.tapTime = nil end )
            elseif eventTime - self.tapTime < 300 then
               timer.cancel( self.tapDelay )
               self.tapTime = nil
					
               if self.xScale == self.xScaleStart and self.yScale == self.yScaleStart then
                  transition.to( self, { time=300, transition=easing.inOutQuad, xScale=self.xScale*2, yScale=self.yScale*2, x=event.x - self.x0*2, y=event.y - self.y0*2 } )
               else
                  local factor = self.xScaleStart / self.xScale
                  transition.to( self, { time=300, transition=easing.inOutQuad, xScale=self.xScaleStart, yScale=self.yScaleStart, x=event.x - self.x0*factor, y=event.y - self.y0*factor } )
               end
            end
         end
					
         if previousTouches[event.id] then
            self.numPreviousTouches = self.numPreviousTouches - 1
            previousTouches[event.id] = nil
         end
			
         if self.numPreviousTouches == 1 then
            self.distance = nil
            local id,touch = next( previousTouches )
            self.x0 = touch.x - self.x
            self.y0 = touch.y - self.y
            self.firstTouch = touch
         elseif self.numPreviousTouches == 0 then
            display.getCurrentStage():setFocus( nil )
            self.isFocus = false
            self.distance = nil
            self.xScaleOriginal = nil
            self.yScaleOriginal = nil
            self.previousTouches = nil
            self.numPreviousTouches = nil
         end
      end
   end

   return true
end
That's a lot of code! To use it, add a touch event listener to your object that calls the pinchtozoom handler.

Runtime Events

So far, all of the event listeners and handlers we’ve seen have applied to display objects. But we can also assign handlers to all registered listeners using global Runtime events. The idea of registered listeners becomes especially important when dealing with Android devices, when we have to request special permission to access many of these listeners. Apple devices running iOS accept these events, and permission is considered during the app review process.

Before we begin defining Runtime events, we’ll consider some examples. You’ve probably used an app that changed orientation when you turned your phone or tablet. Perhaps you’ve used a "shake to shuffle" feature in a music app, or found your location with GPS. Maybe you’ve played a game where objects moved simply by tilting the device. All of these scenarios, and more, used Runtime events.

Many of these events, such as enterFrame, will not have much meaning until we have seen a little more (in this case, we’ll need to learn how to create apps with multiple scenes). However, we’ll now look at a comprehensive list of types of Runtime events and how to use them. When assigning an event listener to a display object, we have to specify what type of event to listen for - a "touch" or a "tap". For Runtime events, we’ll use the basic format

Runtime:addEventListener( event_type, handler_name )
where "event_type" is a string equal to either enterFrame, orientation, accelerometer, system, location, heading, or memoryWarning, and "handler_name" is the name of the function that will fire when the device detects a change to one of these event types.

Tap Events

    A tap listener can be added to the entire screen using

    Runtime:addEventListener( "tap", handler_name )
    This is a convenient way of adding a tap listener without having to bind it to a display object, but use caution when other listeners are involved.

enterFrame Events

    The basic format for a Runtime event listening for en enterFrame event would be

    Runtime:addEventListener( "enterFrame", handler_name )
    We’ll see how this is used when building multi-scene apps later.

Orientation Events

    The basic format for a Runtime event listening for a change in orientation would be

    Runtime:addEventListener( "orientation", handler_name )
    where "handler_name" is the name of the function that handles what to do when such a change is detected. Note that detecting an orientation change will not automatically make any changes to your app - you’ll need to handle those manually.

    There are only two orientation event properties:
    • event.type - a string indicating the new orientation. This may be either "portrait", "land- scapeLeft", "portraitUpsideDown", "landscapeRight", "faceUp", or "faceDown". The last two may not be available on all devices.
    • event.delta - reports the difference between the ending and starting orientation angle. This will have a value of 0 if the different orientations lie in different planes (for instance, the phone was flat on a table in portrait mode, and lifted up to stand on its side in landscape mode).

Example: Detecting Orientation

    In this example, we’ll change the color background based on the current orientation of the device. To try the example in the simulator, choose Rotate Right or Rotate Left from the Hardware menu.

    local w = display.contentWidth
    local h = display.contentHeight
    
    local bg = display.newRect( w/2, h/2, w, h )
    	bg:setFillColor( 0, 1, 0 )
    	
    local function changeColor( event )
    	if event.type == "portrait" then
    		bg:setFillColor( 0, 1, 0 )
    	elseif event.type == "portraitUpsideDown" then
    		bg:setFillColor( 0, 0, 1 )
    	elseif event.type == "landscapeLeft" then
    		bg:setFillColor( 1, 0, 1 )
    	elseif event.type == "landscapeRight" then
    		bg:setFillColor( 1, 0, 0 )
    	end
    end
    
    Runtime:addEventListener( "orientation", changeColor )
    If you want objects to move with the orientation changes, you'll need to reposition the objects manually in such a handler. This is not an easy task!

Accelerometer Events

    In this case, we’ll assign the "accelerometer" event to Runtime using the format

    Runtime:addEventListener( "accelerometer", handler_name )
    where handler_name is the name of the function. When the accelerometer detects motion, it will send information about the event to the handler function, which will decide what to do. We can use the same handler for multiple types of events.

    The accelerometer (a piece of hardware included in most mobile devices) can report the following:
    • event.xGravity - provides the acceleration due to gravity as the device is tilted relative to the x-axis (from left to right). This value is relative to portrait orientation, regardless of the default or current orientation of your app. If using a landscape orientation, you’ll need to compensate for this. Includes smoothing to improve user experience.
    • event.yGravity - as above, but relative to the y-axis (from front to back).
    • event.zGravity - as above, but relative to the z-axis (up and down).
    • event.xInstant - provides the change in acceleration due to gravity as the device is tilted relative to the x-axis. This can be used to detect a "jerking" motion.
    • event.yInstant - as above, but relative to the y-axis.
    • event.zInstant - as above, but relative to the z-axis.
    • event.xRaw, event.yRaw, and event.zRaw - same basic functionality as event.xGravity, event.yGravity, and event.zGravity, respectively, but does not include any smoothing.Objects that are moved with these readings may appear jittery.
    • event.isShake - a true or false value. Returns true if the accelerometer has detected the user shaking the device. This event isn’t used to often, and for some good reasons. Many people don’t feel entirely comfortable shaking their expensive mobile devices intentionally, for one. Also, many accelerometers are not sensitive enough to detect shaking unless it is relatively severe. But there are some applications for it, and it’s a simple Runtime event to begin with.

Example: Magic 8 Ball

    We’ll create a simple Magic 8 Ball app that changes an on screen message with each shake. We’ll first create a text object that displays the message, and a table containing ten possible fortunes to display. In the handler, when a shake is detected, a random number between 1 and 10 is chosen. The message with that id in the message table will then be displayed.

    local w = display.contentWidth
    local h = display.contentHeight
    
    local mt = display.newText( "Ask me a yes or no question", w/2, h/2, Arial, 30)
    
    local fortunes = {
    	"Details are hazy - try again later",
    	"Absolutely.  Try again!",
    	"Definitely not.  Try again!",
    	"Yes.  Try again!",
    	"No.  Try again!",
    	"Probably.  Try again!",
    	"Probably not.  Try again!",
    	"I’d rather not say.  Try again!",
    	"Maybe someday.  Try again!",
    	"Could be.  Try again!" 
    	}
    	
    local function magic8( event )
    	if event.isShake then
    		local randommessage = math.random( 1, 10 )
    		mt.text = fortunes[randommessage]
    	end
    end
    
    Runtime:addEventListener( "accelerometer", magic8 )
    To test your app in the simulator, select Shake from the Hardware menu.

System Events

    System changes that need to be addressed by the app can be handled using a system event listener:

    Runtime:addEventListener( "system", handler_name )
    You mostly likely will not need to use these, and instead allow your config and build files to handle these system events. But, Corona does give you the option of creating your own function to a change to the value event.type - a string representing the kind of system event to look for. This could be "applicationStart", in which case we’d define a function that handles the launching of the application itself. Another possibility is "applicationExit", which allows us to define a function for when the user quits the app. Finally, there’s "applicationSuspend" and "applicationResume", which allow you to design a function that handles an interruption to your app, such as a phone call, and one that handles what to do when the interruption is over.

Memory Warnings (iOS Only)

    The format

    Runtime:addEventListener( "memoryWarning", handler_name )
    allows you to build a function that fires when the iOS low memory warning is exposed. This is a warning that the app will be shut down in 5 seconds. If this warning is received, you’ll want to free as much memory as possible to prevent your app from being shut down.

GPS Events

    For devices with a GPS, you can set up a listener with format

    Runtime:addEventListener( "location", handler_name )
    that passes the following properties to the handler function:
    • event.xGravity - provides the acceleration due to gravity as the device is tilted relative to the x-axis (from left to right). This value is relative to portrait orientation, regardless of the default or current orientation of your app. If using a landscape orientation, you’ll need to compensate for this. Includes smoothing to improve user experience.
    • event.latitude and event.longitude - give the latitude and longitude of the device, in degrees.
    • event.altitude - gives the altitude, in meters.
    • event.accuracy - gives the accuracy of the location, in meters.
    • event.speed - gives the instantaneous speed of the device, in meters per second.
    • event.direction - gives the direction the device is travelling in, in degrees clockwise from true North.
    • event.time - gives the timestamp of the location event.

Heading Events (Requires Compass)

    For devices with a compass, you can set up a listener with format

    Runtime:addEventListener( "heading", handler_name )
    that passes the following properties to the handler function:
    • event.geographic - gives a heading, in degrees, relative to the geographic North Pole (true North).
    • event.magnetic - gives a heading, in degrees, relative to the magnetic North Pole.