Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Handling event "ended" when touch exits object.
Started by coolromin Jan 05 2014 08:36 AM

- - - - -
5 replies to this topic

Best Answer Brent Sorrentino , 06 January 2014 - 01:53 PM

Hi all,

I'm re-naming this thread because it's not a bug, but rather a behavioral tendency you must handle. The ended phase is never triggered (and has never been) unless the touch ends on that object.

 

There are ways to handle scenarios where you want an ended phase to be triggered when the touch drifts off the object. One method that comes to mind is placing an invisible but .isHitTestable=true rectangle behind the button, then when a moved phase is detected on that rectangle, you dispatch an ended event back to the button using the dispatchEvent API. This method may not work for all scenarios, but I think it could be placed into use in most cases.

 

Best regards,

Brent

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

coolromin

[GLOBAL: userInfoPane.html]
coolromin
  • Starter
  • PipPipPipPipPipPip
  • 163 posts
  • Jedi

This bug has stalled my finished game, please someone, a guru or corona staff help me with it please.

 

The bug is that corona doesn't register "cancel" or "end" event.phase on an object if you keep dragging over the object until you fall from the edges of that object. let me explain the bug with the following simple example...

 

	local num = 0
	
	local function bugFunc(event)
		if(event.phase == "began")then
			num = 1
		end
                
                --WILL NEVER GET FIRED IF YOU DRAG OVER THE BUTTON UNTIL YOU ARE NOT TOUCHING THE BUTTON ANYMORE
		if(event.phase == "ended" or event.phase == "cancelled")then
			num = 0
		end
	end
	
	local function bugTester()
		print(num)
	end
	
	--ButtonA
        local buttonA = display.newCircle( 150, 150, 50 )
        buttonA.name = "buttonA"
        buttonA.alpha=0.3
        buttonA:addEventListener ( "touch", bugFunc )
	
	Runtime:addEventListener("enterFrame", bugTester)

 

In the above example the variable "num" will be always equal to "1" if you drag over the button until you are not touching the button anymore.



[TOPIC: post.html]
#2

xnailbender

[GLOBAL: userInfoPane.html]
xnailbender
  • Pro
  • PipPipPipPipPipPip
  • 248 posts
  • Jedi

@coolromin,

 

Not sure how far you want the user to be able to drag before your num value changes, but I think you could use 'event.phase == "moved" ' to change the num value to anything you'd like.

 

Nail



[TOPIC: post.html]
#3

horacebury

[GLOBAL: userInfoPane.html]
horacebury
  • Pro
  • PipPipPipPipPipPip
  • 1,987 posts
  • Jedi

@coolromin, what is the actual bug you're trying to describe? That a touch even which is not happening over the button is not received by the button? The bug would be if the button DID receive the event when the touch event happens outside the button's borders.

 

I think what you want is to test for the "moved" phase. If you want the button to be sent ALL touch events once the touch has started on the button, you need to set the event's focus to that button. Like this:

 

local btn = display.newCircle( 100, 100, 25 )

function btn:touch(e)
 if (e.phase == "began") then
  btn.hasFocus = true
  display.getCurrentStage():setFocus( btn )
  return true
 elseif (e.target.hasFocus) then
  if (e.phase == "moved") then
   -- do what you want here
  else -- ended/cancelled
   display.getCurrentStage():setFocus(nil)
   e.target.hasFocus = false
  end
  return true
 end
 return false -- returned when the touch event did not start on the btn
end
btn:addEventListener("touch",btn)



[TOPIC: post.html]
#4

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Corona Staff
  • 9,387 posts
  • Jedi

Translating what @horacebury said back to your code:

 

    local num = 0
    
    local function bugFunc(event)
        print(event.phase)
        if(event.phase == "began")then
            display.getCurrentStage():setFocus(event.target)
            num = 1
        end
                
        --WILL NEVER GET FIRED IF YOU DRAG OVER THE BUTTON UNTIL YOU ARE NOT TOUCHING THE BUTTON ANYMORE
        if(event.phase == "ended" or event.phase == "cancelled")then
            num = 0
            display.getCurrentStage():setFocus(nil)
        end
        return true
    end
    
    local function bugTester()
        print(num)
    end
    
    --ButtonA
        local buttonA = display.newCircle( 150, 150, 50 )
        buttonA.name = "buttonA"
        buttonA.alpha=0.3
        buttonA:addEventListener ( "touch", bugFunc )
    
    Runtime:addEventListener("enterFrame", bugTester)

 

Basically you need to give your button focus.  When you do that, it knows when you leave it to send the ended phase.  Adding those two focus lines makes your code work the way I think you intend for it to work.

 

Rob



[TOPIC: post.html]
#5

russm305

[GLOBAL: userInfoPane.html]
russm305
  • Basic
  • PipPipPipPipPipPip
  • 358 posts
  • Jedi

Does that work also with widgets.  I have a button that doesn't go to "ended" stage if you drag your finger off the button.  How would I do that in this case?
[lua=auto:0]
 
 
onButtonEvent = function (event )
        if event.phase == "began" then
            myButton:scale(1.2,1.2)
            audio.play(click)
   
        elseif    event.phase == "ended" then
            timer.cancel(tmr1)
            storyboard.gotoScene('loading')
          
        end
    end
 
    myButton = widget.newButton{
        defaultFile = "Replay.png",
         left = 0,
        top = 65,        
       width =55, height = 50,
         onEvent = onButtonEvent
    }
    group:insert(myButton)


[TOPIC: post.html]
#6

Brent Sorrentino

[GLOBAL: userInfoPane.html]
Brent Sorrentino
  • Corona Staff
  • 4,240 posts
  • Jedi

  Best Answer

Hi all,

I'm re-naming this thread because it's not a bug, but rather a behavioral tendency you must handle. The ended phase is never triggered (and has never been) unless the touch ends on that object.

 

There are ways to handle scenarios where you want an ended phase to be triggered when the touch drifts off the object. One method that comes to mind is placing an invisible but .isHitTestable=true rectangle behind the button, then when a moved phase is detected on that rectangle, you dispatch an ended event back to the button using the dispatchEvent API. This method may not work for all scenarios, but I think it could be placed into use in most cases.

 

Best regards,

Brent




[topic_controls]
[/topic_controls]