本指南解释了轻触、触摸和多点触摸之间的区别,以及如何处理与每种方法相关的事件。
如果您是 Corona 新手,并且尚未了解基本的屏幕交互和事件,请先阅读基本交互和事件检测指南。
轻触事件是最基本的屏幕交互形式。本质上,轻触是指用户触摸屏幕并在 تقریباً 同一点抬起手指。仅当用户在该点触摸并释放时,轻触事件才被视为成功。
在 Corona 中,您可以通过在大多数常见的显示对象上注册 "tap"
事件监听器来监听轻触事件。
local function tapListener( event ) -- Code executed when the button is tapped print( "Object tapped: " .. tostring(event.target) ) -- "event.target" is the tapped object return true end local myButton = display.newRect( 100, 100, 200, 50 ) myButton:addEventListener( "tap", tapListener ) -- Add a "tap" listener to the object
从轻触返回的 event
属性包括:
event.target
— 对被轻触对象的引用。
event.name
— 字符串值 "tap"
。
event.numTaps
— 屏幕上的轻触次数。被视为序列中下一次轻触的默认延迟为 0
,但可以使用system.setTapDelay() 函数调整此时间。
event.x
/ event.y
— 轻触的x 和y 坐标,以内容坐标表示。
与触摸事件不同,轻触事件不包含 phase
属性 — 轻触是涉及触摸和释放的单一操作,因此您无需以任何特殊方式处理阶段。
使用 event.numTaps
属性,您可以轻松确定某个对象是否被多次轻触,并同时忽略该对象的单次轻触。为此,只需确保 event.numTaps
等于 2
或更高,并忽略返回 true
local function tapListener( event ) if ( event.numTaps == 2 ) then print( "Object double-tapped: " .. tostring(event.target) ) elseif ( event.numTaps == 3 ) then print( "Object triple-tapped: " .. tostring(event.target) ) else return true end end local myButton = display.newRect( 100, 100, 200, 50 ) myButton:addEventListener( "tap", tapListener )
触摸事件提供了更高级别的屏幕交互。使用触摸事件,您可以检测用户何时首次触摸屏幕以及何时将触摸从屏幕上抬起。您还可以跟踪触摸在屏幕上移动时的运动轨迹。为此,Corona 在四种状态之一中提供了 event.phase
属性:
"began"
— 指示触摸已在屏幕上开始。"moved"
— 指示触摸已在屏幕上移动。"ended"
— 指示触摸已从屏幕上抬起。"cancelled"
— 指示系统取消了对触摸的跟踪(不要与 "ended"
混淆)。您可以通过在大多数常见的显示对象上注册 "touch"
事件监听器来监听触摸事件。
local function myTouchListener( event ) if ( event.phase == "began" ) then -- Code executed when the button is touched print( "object touched = " .. tostring(event.target) ) -- "event.target" is the touched object elseif ( event.phase == "moved" ) then -- Code executed when the touch is moved over the object print( "touch location in content coordinates = " .. event.x .. "," .. event.y ) elseif ( event.phase == "ended" ) then -- Code executed when the touch lifts off the object print( "touch ended on object " .. tostring(event.target) ) end return true -- Prevents tap/touch propagation to underlying objects end local myButton = display.newRect( 100, 100, 200, 50 ) myButton:addEventListener( "touch", myTouchListener ) -- Add a "touch" listener to the object
从触摸返回的事件属性包括:
event.id
— 一个唯一标识符,用于区分不同触摸事件中的多个触摸。有关更多详细信息,请参阅下面的多点触摸。
event.target
— 对被触摸对象的引用。
event.name
— 字符串值 "touch"
。
event.phase
— 如上所述的触摸阶段。
event.pressure
— 指示触摸压力的数字,通常用于检测兼容 iOS 设备上的“3D 触摸”事件。有关更多信息,请参阅文档。
event.time
— 自应用程序启动以来的毫秒数,可从触摸侦听器函数内部访问。
event.x
/ event.y
— 触摸的x 和y 坐标,以内容坐标表示。
event.xStart
/ event.yStart
— 触摸序列 "began"
阶段的触摸x 和y 坐标,以内容坐标表示。
在应用中启用多点触摸可以让您同时检测和处理屏幕上的多个用户触摸。
多点触摸功能仅在实际移动设备
都支持多点触摸。
-- Activate multitouch system.activate( "multitouch" ) -- Create a display object on the screen local newRect1 = display.newRect( display.contentCenterX, display.contentCenterY, 280, 440 ) newRect1:setFillColor( 1, 0, 0.3 ) -- Touch event listener local function touchListener( event ) print( "Phase: " .. event.phase ) print( "Location: " .. tostring(event.x) .. "," .. tostring(event.y) ) print( "Unique touch ID: " .. tostring(event.id) ) print( "----------" ) return true end -- Add a touch listener to the object newRect1:addEventListener( "touch", touchListener )
当用户触摸屏幕时,事件将分派到显示层次结构。只有与屏幕上触摸位置相交的显示对象才会接收该事件。
轻触和触摸事件按特定顺序在这些对象中传播。默认情况下,第一个接收事件的对象是显示层次结构中与触摸位置相交的
轻触和触摸事件会一直传播,直到被“处理”为止。这意味着,如果您在显示层次结构中有多个对象相互重叠,并且每个对象都应用了轻触或触摸事件侦听器,则该事件将传播通过所有这些对象。但是,您可以通过告诉 Corona 该事件已被处理来停止向下一个基础对象的传播。这就像从事件侦听器返回 true
一样简单 — 这将停止传播周期并阻止任何基础对象响应命中事件。
local function myTouchListener( event ) if ( event.phase == "began" ) then -- Code executed when the button is touched print( "object touched = " .. tostring(event.target) ) -- "event.target" is the touched object end return true -- Prevents tap/touch propagation to underlying objects end local myButton = display.newRect( 100, 100, 200, 50 ) myButton:addEventListener( "touch", myTouchListener )
如果在遍历整个显示层次结构后仍未处理轻触或触摸事件,则它将作为全局事件广播到运行时侦听器。
您可以通过在对象上设置焦点来将所有触摸事件定向到特定显示对象。这将指示系统将所有未来的触摸事件传递给该对象,有效地使其“拥有”它在其生命周期内接收的第一个触摸。
考虑一个典型的按钮 — 如果用户触摸按钮并在不抬起/释放触摸的情况下滑出按钮边界,则该按钮可能不应在触摸释放时触发操作。同样,如果触摸从按钮上滑落并与另一个
要设置显示对象的焦点,请将其对象引用传递给StageObject:setFocus()。这可以是触摸侦听器中的 event.target
,也可以是对对象本身的任何直接引用。
相反,当您希望释放对象上的焦点时,只需将 nil
传递给StageObject:setFocus()即可。
display.getCurrentStage():setFocus( nil )
此示例显示了如何处理多个对象的焦点和释放:
-- Create two display objects on the screen local newRect1 = display.newRect( display.contentCenterX, 160, 60, 60 ) newRect1:setFillColor( 1, 0, 0.3 ) local newRect2 = display.newRect( display.contentCenterX, 320, 60, 60 ) newRect2:setFillColor( 0.3, 0, 1 ) -- Touch event listener local function touchListener( event ) if ( event.phase == "began" ) then event.target.alpha = 0.5 -- Set focus on object display.getCurrentStage():setFocus( event.target ) elseif ( event.phase == "ended" or event.phase == "cancelled" ) then event.target.alpha = 1 -- Release focus on object display.getCurrentStage():setFocus( nil ) end return true end -- Add a touch listener to each object newRect1:addEventListener( "touch", touchListener ) newRect2:addEventListener( "touch", touchListener )
当通过system.activate()启用多点触摸时,也可以实现触摸焦点。但是,由于同一对象上可能存在多个触摸,因此您必须通过唯一的内部标识符来专用它接收的第一个触摸。这是通过将从触摸侦听器收集的 event.id
属性作为第二个参数传递给StageObject:setFocus()来完成的。
display.getCurrentStage():setFocus( event.target, event.id )
然后,当您希望释放对象上的焦点时,只需将 nil
作为第二个参数传递给StageObject:setFocus()即可。
display.getCurrentStage():setFocus( event.target, nil )
此示例显示了如何在启用多点触摸时处理多个对象的焦点和释放:
-- Activate multitouch system.activate( "multitouch" ) -- Create two display objects on the screen local newRect1 = display.newRect( display.contentCenterX, 160, 60, 60 ) newRect1:setFillColor( 1, 0, 0.3 ) local newRect2 = display.newRect( display.contentCenterX, 320, 60, 60 ) newRect2:setFillColor( 0.3, 0, 1 ) -- Touch event listener local function touchListener( event ) print( "Unique touch ID: " .. tostring(event.id) ) if ( event.phase == "began" ) then event.target.alpha = 0.5 -- Set focus on object using unique touch ID display.getCurrentStage():setFocus( event.target, event.id ) elseif ( event.phase == "ended" or event.phase == "cancelled" ) then event.target.alpha = 1 -- Release focus on object display.getCurrentStage():setFocus( event.target, nil ) end return true end -- Add a touch listener to each object newRect1:addEventListener( "touch", touchListener ) newRect2:addEventListener( "touch", touchListener )