No ended or canceled phases on touch event

I’ve got a feature in my app where the user can press and hold a button for 3 seconds to set the current page as the default for the app. If they release before 3 seconds is up, I cancel the timer that sets it as default.

However, if I touch and move off the the button before releasing, I only get began and moved event phases. I can cancel the timer in move, too, but I would have thought I would have seen an ended or canceled event phase.

Is this expected behavior? This is in build 826. [import]uid: 58455 topic_id: 27006 reply_id: 327006[/import]

I posted code with a similar problem here

That code worked once I fixed the minor spelling error so you can get an idea about how to do it. [import]uid: 106158 topic_id: 27006 reply_id: 109580[/import]

I was having trouble getting a cancelled phase as well but since I didn’t rely upon it I didn’t bother looking into it further. I will say that using ‘move’ wouldn’t be good unless you did some logic to see how far the touch has moved from the originating point. It’s real use to accidently move a pixel or two, especially when you are holding it down for 3 seconds. [import]uid: 147305 topic_id: 27006 reply_id: 109603[/import]

Ae you using a button on top of a scroll view, by chance? That’s a good way to not have an ended event… [import]uid: 41884 topic_id: 27006 reply_id: 109614[/import]

No scroll view…just a plain old image with a touch listener. [import]uid: 58455 topic_id: 27006 reply_id: 109615[/import]

I suggest you watch Dr. Hernandez’s video tutorials on Corona SDK. He solved this problem in this video:

http://www.youtube.com/watch?v=pR37-szANDo

Basically, use the display.getStage and setFocus to keep the button focused, and a premature release will still get an ended phase.
[import]uid: 6084 topic_id: 27006 reply_id: 109622[/import]

Yes, pbligh posted that solution, too. That will make sure I get the “ended” phase, but the question is, is that really a touch to the user? If you touch an app icon on your iPhone desktop, and then move it off before releasing, the app does not get launched. i.e., you undid the touch.

[import]uid: 58455 topic_id: 27006 reply_id: 109669[/import]

I have a possible workaround.

You can save the coordinates of the first touchdown, then compare it with coordinates of the “release.” If the distance between the two points is greater than a particular threshold you set, then it’s not a touch, but a “slide” which you can determine whether or not to accept it as such.

I haven’t tested if the “releasing” coordinates are still bound to the actual pixel dimensions of the object, but you’re welcome to give this a shot and report back for others who may be similarly interested.

[code]local function distanceBetweenPoints( startX, startY, endX, endY )

local xFactor = endX - startX ; local yFactor = endY - startY
local distanceBetween = math.sqrt(( xFactor * xFactor ) + ( yFactor * yFactor ))
return distanceBetweenPoints
end[/code]

UPDATE: In reading the touch listeners on http://developer.anscamobile.com/content/events-and-listeners, you don’t have to capture the start coordinates at the “began” phase, as it’s already done for you as event.xStart / event.yStart. [import]uid: 6084 topic_id: 27006 reply_id: 109678[/import]

davemikesell: Sounds a bit like you’re confusing a touch with an event.

Typically when writing touch code you do this:

[code]if event.phase == “began” then

– set focus (ensures no other hijinks)

event.target.isFocus = true – prevents being able to “slide over” object and trigger move code

elseif event.target.isFocus then

if event.phase == “moved” then
– do whatever movement stuff you want here

elseif event.phase == “ended” then
– at this point, the user has lifted their finger.

– check to see if the finger was still on the object/icon!
local isWithinBounds = event.x > event.target.contentBounds.xMin and event.x < event.target.contentBounds.xMax and event.y > event.target.contentBounds.yMin and event.y < event.target.contentBounds.yMax
if isWithinBounds then
– execute whatever the icon/button/object should do
end
end
end [/code]

The iOS main screen works very similarly.

  1. When you press down, focus is set to prevent you from affecting other buttons (notice how you can’t slide your finger over to another button and release to target that instead)
  2. When you move, it triggers scrolling code. Your focus is still “set” but you can no longer trigger the button. (So basically like saying isFocus = false)
  3. When you release, it checks to see if isFocus = true and decides to execute based on that. [import]uid: 41884 topic_id: 27006 reply_id: 109689[/import]

Good explanation, richard. I wish the Corona docs were that good. [import]uid: 58455 topic_id: 27006 reply_id: 109696[/import]

I guess you would need to decide what behavior you want.

As far as Icons go:

I know on the iPad if you touch an icon it darkens. If you then without releasing, move your finger, you scroll the page over. The icon loses its color as soon as you move your finger. So it appears that it has lost focus. It acts as if you clicked on the background and dragged rather than the icon.
As far as buttons go:

If you open the settings menu on the iPad and touch any of the menu items you will notice that they highlight a different color. If you then, without releasing, drag your finger of the button/menu item it will lose its highlight color. I think this is a good way to show that your event is not targeting the button anymore.

I don’t know if this is the case with an iPhone.

But I would expect that if you were moving on a button to the point of where your finger is no longer touching it you would probably want it to lose focus just like it does on the iPad.

The solution I linked above does not do that. I use it for some fader controls that I made. I wanted them to function like a mouse click on the computer. Once the event has started on a control you can drag the cursor anywhere on screen and still effect the control as long as you don’t release.
[import]uid: 106158 topic_id: 27006 reply_id: 109697[/import]

Just FYI; pretty sure I cribbed the .isFocus solution from an old Beebe entry or something. It’s pretty important because if you write your touch code the old way, ie:

if event.phase == "began" then -- do this elseif event.phase == "moved" then -- do this elseif event.phase == "ended" then -- do this end

…you introduce a critical vulnerability in your code, namely: what happens if the object gets a “moved” call (or ended!) but not a “began”? This is very easy to test - just start your touch somewhere else (say, somewhere where there is no touch listener) and slide onto the object. You’ll catch a bunch of “moved” calls.

Which sucks because most code is written with “began” in mind and now you’re triggering touch calls without focus! Setting .isFocus ensures that you only execute the touch code if you began the touch there in the first place.
[import]uid: 41884 topic_id: 27006 reply_id: 109713[/import]

Wow, I learn something new everyday. object.contentBounds is powerful stuff. [import]uid: 6084 topic_id: 27006 reply_id: 109768[/import]