• CoronaSDK之交互系统和事件检测


    事件(Event)是Corona应用程序的基础。他们用来触发不同事件对应的响应,例如触摸屏幕、检测一个特定的系统事件、定时器的完成、两个物理体的碰撞,等等。通常我们使用display object的对象方法addEventListener来添加处理函数,以关联需要监听的事件。

    1 Runtime事件(似乎也可以叫做全局事件)

    Runtime事件被分配给全局的Runtime监听器。这些事件并不直接和任何具体的对象相关;当然他们广播给所有感兴趣的监听器。Runtime event包括下列这些:

    • enterFrame:发生在每秒帧数间隔之间的事件(corona渲染一般每秒30或60帧)
    • system:某种由系统状况引发的事件,例如设备挂起应用或退出应用
    • orientation:当改变设备的方向,横向到竖向或者反之,而发生的事件

    下面的代码展示了一个应用如何响应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 )

    2 本地事件(local event)

    本地事件被发送给一个单独的Listener,而不是广播给全局的运行时环境。一般本地事件包括下列事件:

    hit:当用户触摸设备屏幕时发生的事件

    collision:物理对象碰撞时发生的事件

    timer:在运行timer完成时发生的事件

    audio:当一个音频播放完成时分发的事件

     

    3 function listener 和 table listener

    Listener可以是一个function,也可以是一个table。

    当你一个function Listener被调用,它会接受一个table参数,作为event。

    local myListener = function( event )
        print( "Listener called with event of type: "..event.name )
    end
    
    Runtime:addEventListener( "touch", myListener )
    Runtime:addEventListener( "enterFrame", myListener )

    有时一个function Listener并不方便,因为当Listener被调用时一些变量并不在作用域里。在这种情况里,table Listener应该被使用。table Listener必须有一个有对应事件名的实例方法:

    --assume 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 )

    注意:

    这里是对象方法,用的是“:”,而不是“.”。所以实际上函数内部是可以访问self引用的。这里的self就是myObject的引用。

    4 理解hit事件

    当用户触摸屏幕时,一个hit事件会生成并分发给显示层次中的显示对象(display object)。只有那些在屏幕上位置和触摸点位置发生交集的对象会收到事件。hit事件会以一个特定的顺序穿过这些对象。默认情况下,第一个收到事件的对象是发生交集的对象中最上层的显示对象,往下一个发生交集的显示对象会第二个收到事件,如此类推。

    hit事件会一直传递下去,除非它被处理掉。这意味着如果你有多个层叠在一起的对象,并且一个hit事件监听器被应用到所有这些对象,hit事件将会穿过着所有的对象。然而,你可以停止传递给下一个低层对象,这就需要你告诉corona这个event已经被处理了。简单的方法就是在事件处理函数直接返回一个true--这将会停止传递周期,并且阻止任何底下对象响应这个hit事件。

    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 touch propagation to underlying objects
    end
    
    local myButton = display.newRect( 100, 100, 200, 50 )
    myButton:addEventListener( "touch", myTouchListener )

    注意:如果hit事件遍历了整个显示层次中所有的显示对象,仍然没有被处理,它将会像全局事件一样广播给Runtime Listener。换言之,runtime listener还有机会对未命中任何对象的触摸事件做出反应。

    4.1 设置焦点

    你可以直接发送任何hit事件给一个指定的display object,来为这个对象设置焦点。比如一个典型的button,如果用户触摸这个按钮--还没有抬起手-又滑出了按钮,这个按钮一般不应该激发一个行为。同理,如果手指滑出按钮并接触到另一个交互对象,你可能不想激活那个对象,因为触摸是从按钮开始的,而不是交互对象。

    解决这个问题的简单方法就如下,进入按钮时设置焦点,结束和取消时再取消焦点。这样滑出到其他对象时,其他对象都收不到事件

    local function myTouchListener( event )
    
        if ( event.phase == "began" ) then
            display.getCurrentStage():setFocus( event.target )  --'event.target' is the touched object
    
        elseif ( event.phase == "ended" or event.phase == "cancelled" ) then
            display.getCurrentStage():setFocus( nil )  --setting focus to 'nil' removes the focus
    
        end
        return true
    end
    
    local myButton = display.newRect( 100, 100, 200, 50 )
    myButton:addEventListener( "touch", myTouchListener )

    4.2 hit event具体分为

    • Tap
    • Touch
    • Multitouch

    5 event 参数

    上面举出的每个例子,事件都会被分发给事件监听函数。一个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参数中包含手指接触屏幕位置的x和y坐标。event参数关联的属性和event类型是一一关联的。什么事件 对应哪些属性。

    6 注册EventListener

    我们一般用对象方法addEventListener()来注册事件。只要传入事件名称字符串,以及对应处理这个事件的处理函数即可。

    --standard touch listener on an object
    myButton:addEventListener( "touch", myTouchListener )
    
    --Runtime 'system' event listener
    Runtime:addEventListener( "system", onSystemEvent )

    重要提示:

    如上所示,两种类型的事件监听器都可以通过addEventListener对象方法来创建:监听器附着到显示对象,或者监听器附着到全局Rumtime。

    当你创建一个显示对象或添加一个本地的touch事件监听器 给它,你需要通过引用函数来指定一个代码块给事件。这些代码处于他们自己内存的代码段当中,并且当显示对象被删除后依然存在。不过当显示对象被删除后,就没办法检测到新的事件,因为本地事件监听器(注意:是监听器,不是代码)已经被有效的删除,并不需要你显式地删除监听器。

    另一方面,Runtime事件监听器需要在你用完之后手动删除。此外,他们将继续运行,因为全局Runtime事件是全局的。不仅仅会导致内存泄漏,而且如果函数继续存在于Runtime中,并引用了不再存在的对象,程序也会崩溃。

    7 删除Event Listener

    大多数监听器(Listener),除了“enterFrame”之类的Runtime监听器,在显示对象被删除(obj:removeSelf或display.remove(obj))时将会被自动删除。但是,你也可以不删除对象,而只手动删除事件监听器。

    删除(摘除)一个事件监听器,需要依靠内建的removeEventListener对象方法。

    这个函数调用方式和addEventListener差不多。比如,你想让一个按钮停止监听touch事件,就可以摘除其监听器,如下:

    myButton:removeEventListener( "touch", myTouchListener )

    删除关联的事件监听器,需要提供事件名和函数名,因为有可能一个对象连接了同一类对象的多个监听器。例如,你可以有两个或更多监听函数关联到myButton的touch事件。然而当调用removeEventListener()时,你需要指定你想要停止监听的事件的类型,以及之前关联到这个事件上的函数。

  • 相关阅读:
    ping和telnet
    nginx下No input file specified错误的解决
    【Git】删除某个全局配置项
    windows7使用Sphinx+PHP+MySQL详细介绍
    TortoiseGit需要重复填写用户名和密码的问题
    【算法】字符串数组的排序时间复杂度问题
    java随机生成6位随机数 5位随机数 4位随机数
    Linux下MySQL报Table 'xxx' doesn't exist错误解决方法,表名存在大小写区分
    Cannot find ./catalina.sh The file is absent or does not have execute permission This file is nee
    Linux 服务器安装jdk,mysql,tomcat简要教程
  • 原文地址:https://www.cnblogs.com/leezj/p/4238641.html
Copyright © 2020-2023  润新知