基本交互和事件检测

事件是 Corona 交互式应用程序的基础。它们用于触发应用程序中的响应,例如屏幕点击、特定系统事件的检测、计时器的完成、两个物理实体的碰撞等。事件使用 object:addEventListener() 方法检测,该方法指示 Corona 在监听器函数中跟踪(监听)关联的事件。有关详细信息,请参阅注册事件部分。

运行时事件

运行时事件被分派到全局运行时监听器。这些事件并非针对任何特定对象;而是广播给所有感兴趣的监听器。常见的运行时事件包括以下内容:

以下代码显示了应用程序如何响应 system 事件。

local function onSystemEvent( event )
    
    local eventType = event.type

    if ( eventType == "applicationStart" ) then
        -- Occurs when the application is launched and all code in "main.lua" is executed
    elseif ( eventType == "applicationExit" ) then
        -- Occurs when the user or OS task manager quits the application
    elseif ( eventType == "applicationSuspend" ) then
        -- Perform all necessary actions for when the device suspends the application, i.e. during a phone call
    elseif ( eventType == "applicationResume" ) then
        -- Perform all necessary actions for when the app resumes from a suspended state
    elseif ( eventType == "applicationOpen" ) then
        -- Occurs when the application is asked to open a URL resource (Android and iOS only)
    end
end

Runtime:addEventListener( "system", onSystemEvent )

局部事件

局部事件通常发送到单个监听器,并且不会广播到全局运行时。常见的局部事件包括以下内容:

局部事件的用法各不相同,将在其主题相关的 指南和/或API 参考中进一步讨论。

函数和表监听器

监听器可以是函数或表/显示对象。

当调用函数监听器时,会向其传递一个表示事件的表。

local myListener = function( event )
    print( "Listener called with event of type: " .. event.name )
end

Runtime:addEventListener( "touch", myListener )
Runtime:addEventListener( "enterFrame", myListener )

有时,函数监听器并不方便,因为在调用监听器时某些变量不在作用域内。在这种情况下,应使用表监听器。表监听器必须具有一个与事件名称对应的实例方法。

-- Assumes "myClass" and "myClass:new()" already exist

function myClass:enterFrame( event )
    print( "enterFrame called at time: " .. event.time )
end

function myClass:touch( event )
    print( "touch occurred at: " .. event.x .. "," .. event.y )
end
 
local myObject = myClass:new() 

Runtime:addEventListener( "touch", myObject )
Runtime:addEventListener( "enterFrame", myObject )

事件监听器

如上例所示,事件被分派到作为基本函数编写的事件监听器。始终会向函数分派一个 event 参数。

local function myTouchListener( event )

    print( "Touch X location" .. event.x )
    print( "Touch Y location" .. event.y )
end
 
local myButton = display.newRect( 100, 100, 200, 50 )
myButton:addEventListener( "touch", myTouchListener )

请注意,传递给 myTouchListener 函数的 event 参数包含表示触摸发生屏幕位置的 xy 属性。与 event 参数关联的属性对于每种事件类型都是唯一的 — 有关详细信息,请参阅事件 API 文档。

注册事件

可以使用 object:addEventListener() 方法注册事件。只需传递事件类型的字符串名称和应处理它的事件监听器函数的名称即可。

-- Standard touch listener on an object
myButton:addEventListener( "touch", myTouchListener )

-- Runtime "system" event listener
Runtime:addEventListener( "system", onSystemEvent )
重要

如上所示,可以使用 object:addEventListener() 方法创建两种类型的事件监听器:附加到显示对象的监听器和附加到全局运行时的监听器。

创建显示对象并向其添加局部触摸事件监听器时,实际上是通过引用该函数来指向一段代码块。这段代码驻留在其自己的内存中,并在显示对象被移除后仍然存在。发生这种情况时,无法感知对象上的未来事件,因此实际上会为您移除局部事件监听器。您无需显式移除它。

另一方面,运行时事件监听器在使用完毕后必须移除。否则,它们将继续运行,因为运行时事件是全局的。这不仅会导致内存泄漏,而且如果在运行时中执行的任何函数尝试引用不再存在的对象,程序将会崩溃。有关更多信息,请参阅下面的移除事件监听器

移除事件监听器

大多数监听器(运行时监听器(如 "enterFrame")除外)会在关联对象被移除时自动移除,例如,当您调用 object:removeSelf()display.remove() 时。但是,您可能需要在不移除对象的情况下显式移除事件监听器。

移除事件监听器是使用内置的 object:removeEventListener() 方法完成的。

调用此函数的方式与 object:addEventListener() 完全相同。例如,如果您想停止监听 myButton 对象上的触摸事件,请按如下方式移除监听器:

myButton:removeEventListener( "touch", myTouchListener )

移除关联的监听器需要类型和函数名称,因为可以将同一类型的多个监听器分配给单个对象。例如,您可以将两个(或更多)不同的监听器函数分配给 myButton 显示对象的 "touch" 事件。因此,在调用 object:removeEventListener() 时,您需要指定要停止监听的事件类型,以及先前分配给该事件的监听器函数。