Long Touch event with Timer and Confirmation Box for iOS deployment in AS3 - actionscript-3

I have a project where I have a scrolling list. I would like for my user to be able to "long touch" an item on the list so that they can delete it.
I am developing in Air for iOS using Flash CS6 so I don't really know much about the appropriate MultiTouch gestures for iOS deployment.
In my mind, the animation steps I would like to go like so..
Previously invisible button called btn_delete inside the Item movieclip will appear when Long Touch starts + timer begins
Intermediate step: btn_delete will rotate 90 degrees using TweenMax Rotate (I have this covered)
Final step: when timer reaches it's conclusion, a dialog box / confirmation box will pop up and ask the user if they are sure if they want to delete the item.
So here is some generic code I've written quickly to give you an idea of my structure so far (I've omitted the interlinking listener functions):
function exampleFunction {
_item.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
}
//-- Long Press Listener Functions--//
function onTouchBegin(eBegin:TouchEvent) {
trace("start");
}
function onTouchRotate(eEnd:TouchEvent) {
trace("rotation of image");
}
function onTouchEnd(eEnd:TouchEvent) {
trace("end");
}
If anyone has a piece of code they've already written that roughly matches my criteria then please post it!

I would just use MouseEvent for this.
var timer:Timer = new Timer( 500 ); //ms
timer.addEventListener( TimerEvent.TIMER_COMPLETE, timerCompleteHandler );
listItem.addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
function mouseDownHandler( e:MouseEvent ):void {
timer.start();
stage.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
}
function mouseUpHandler( e:MouseEvent ):void {
//just some clean up to reset the timer and remove the mouse up event listener from the stage
timer.reset();
stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
}
function timerCompleteHandler( e:TimerEvent ):void {
timer.reset();
stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
//do delete actions here
}
So on mouse down, you start your timer and listen for a mouse up event (on the stage and not the component. That is important. If you want to know why, try it on the component and experiment). On mouse up, you reset the timer so the next time you mouse down, it starts at 0 (reset() has the added benefit of stopping the timer). On timer complete, you do the same as in mouse up in addition to your delete code.
I'm using a MouseEvent here just because it behaves identical to TouchEvent (for the most part) in this instance and it could be used on the desktop (meaning you can test in the emulator and you could add this to other projects if you wanted)
UPDATE:
Just reread your question and realized I missed the rotate. For this, just add another timer with a separate complete handler that and in that function, ONLY do the rotation and reset that timer.

Related

How to play animation and then play reverse on hover, start playing again until end on hover out using in Adobe Animate (Flash)?

Sorry this is so specific but I have combed through so many pages and videos and tutorials and can't figure this out.
I have all of my animations within a MovieClip. In the movie clip is also a stage sized white square button with the instance name "btn". Back on the main stage I have a second layer called "actions" with the following code applied to the first (and only) frame. It's not working. At all. (HUGE) tia
stop(); // this will stop the movie from playing at the start
btn.addEventListener((MouseEvent.ROLL_OVER, playMovie);
btn.addEventListener((MouseEvent.ROLL_OUT, stopMovie);
function playMovie(evt:MouseEvent):void {
play();
}
function stopMovie(evt:MouseEvent):void {
stop();
}
The problem is when you say play(); or stop(); which object are you really commanding? Your playMovie function could be in theory used to control many MovieClips at once, in different ways, so be specific with your commands...
btn.play(); //start the playback of "btn" MC
btn.stop(); //stop the playback of "btn" MC
Also consider using MOUSE_OVER/OUT instead ROLL_OVER/OUT etc but whatever works for you.
For reversing you will use btn.prevFrame(); together with an ENTER_FRAME event function. This function reads your Document settings for the FPS. For example, if you set 30 frames-per-sec then whatever instructions you put inside the event function will be processed 30 times per second.
See this other Answer for advice about reversing the playback of a MovieClip.
#VC.One is correct in how you should implement a solve to your issue, however in response to your comment on their answer, I thought I would demonstrate how to implement this fully for you - incase they don't.
var removeUpdate = false;
btn.addEventListener(MouseEvent.MOUSE_OVER, playMovie);
btn.addEventListener(MouseEvent.MOUSE_OUT, stopMovie);
function playMovie(evt:MouseEvent):void {
// Stop rewinding the movie clip and play it
if(removeUpdate){
stage.removeEventListener(Event.ENTER_FRAME, update);
removeUpdate = false;
}
// play our button
btn.play();
}
function stopMovie(evt:MouseEvent):void {
// stop our button
btn.stop();
// ... and rewind it
stage.addEventListener(Event.ENTER_FRAME, update);
removeUpdate = true;
}
function update(evt: Event){
// moves the button movie clip backwards one frame.
btn.prevFrame();
// If we have finished rewinding the movie clip, then stop
if(btn.currentFrame == 1){
stage.removeEventListener(Event.ENTER_FRAME, update);
removeUpdate = false;
}
}
It is important that you remove the update event because if you don't, the movie will never play again, because it will go one frame forward and then back again every frame due to; btn.play(); btn.prevFrame();

Remove a MouseEvent.MOUSE_MOVE event listener if no user interaction occurs

I'm new to AS3 and need help figuring out how to remove my MouseEvent.MOUSE_MOVE listener if no user interaction occurs.
I have built an animation that does the following:
A solid line and some text appear on top of an image. After this finishes a mouse event is enabled that allows the user to move the line up and down. When the user stops interacting with the line, the line disappears and the final screen of the animation appears.
In the event that the user does not interact with the animation at all (the line never moves), I need to incorporate some way to remove the event listener, then have the final screen of the animation appear. I think adding a TimerEvent is the correct approach for doing what I want, but I'm not sure how to incorporate it. This also may not be the best or correct method. In that case, does anyone have suggestions as to what should be done?
Any help will be appreciated!
Here is my code:
import com.greensock.*;
//objects on the stage
line_mc.y=250;
raisingTxt.alpha=0;
arrow_mc.alpha=0;
final_mc.alpha=0;
logo_mc.alpha=1 ;
//move line mc to y:125
TweenLite.to(line_mc, 1, {y:125});
TweenLite.to(raisingTxt, .5, {alpha:1, delay:1.2});
TweenLite.to(arrow_mc, .5, {alpha:1, delay:1.2, onComplete:followMouse});
//calls MouseEvent onComplete of tween
function followMouse() {
stage.addEventListener(MouseEvent.MOUSE_MOVE, moveIt);
}
function moveIt(e:MouseEvent):void {
TweenLite.to(line_mc, 0.5, {y:this.mouseY});
TweenLite.to([raisingTxt,arrow_mc], 0.5, {alpha:0, onComplete:finalScreen} );
}
//calls final screen onComplete of MouseEvent
function finalScreen() {
TweenLite.to(line_mc, 0.5, {alpha:0} );
TweenLite.to(final_mc, 0.5, {alpha:1} );
}
You can accomplish this with the built in Timer class. I like it a bit more than the setTimeout function because it's simpler to manage.
First create a class wide variable (assuming you are doing this in the Flash IDE, just create it near the top)
var timeout:Timer;
Then in your followMouse():
private function followMouse():void {
timeout = new Timer( 3000, 1 );
timeout.addEventListener( TimerEvent.TIMER_COMPLETE, removeMouseListener );
timeout.start();
stage.addEventListener(MouseEvent.MOUSE_MOVE, moveIt);
}
Last create the removeMouseListener():
private function removeMouseListener( e:Event=null ):void {
timeout.removeEventListener( TimerEvent.TIMER_COMPLETE, removeMouseListener );
stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveIt);
}
If you want to keep resetting the timer every time the mouse moves, you can add these two lines to your moveIt():
timeout.reset();
timeout.start();
I made the removeMouseListener() have an optional parameter so you can call it any time regardless of the timer.
Hope that helps! Good luck!

EnterFrame handler to run only while timeline is stopped on a certain frame

I have some code in a frame. It's basically
this.addEventListener(Event.ENTER_FRAME, handleUpdate);
function handleUpdate(e:Event):void
{...}
I want the code to be executed only when on that frame. But the handleUpdate function keeps getting called even when I'm out of that frame.
The timeline is stopped on this frame, and I want the handleUpdate to run continuously until the timeline moves off the frame.
If you're set on having the code for this on the frame in question, then you could do this:
var tmpCurFrame:int = currentFrame; //store the current frame
this.addEventListener(Event.ENTER_FRAME, handleUpdate)
function handleUpdate(e:Event):void {
if (tmpCurFrame != currentFrame) { //if the frame has changed, stop the frame handler
this.removeEventListener(Event.ENTER_FRAME, handleUpdate);
return;
}
//do your code
}
handleUpdate(null);
As an aside, it's much cleaner to have a document class and other class files that manage this sort of thing instead of using frame scripts. But if you all you're looking for is a quick and dirty tweak to your existing code, this should do the trick.
Haven't you heard about addFrameScript ?
It's perfect for your needs.
var desiredFrame = 25; // Timeline frame (starts from 1)
this.addFrameScript(desiredFrame-1, onFrame25); // 1st param is zero-based
function onFrame25():void
{
trace("I'm on frame", desiredFrame);
}
There's a few things you should consider with your approach:
Adding an ENTER_FRAME listener on the frame you care about happens after you enter that frame, so if the movieclip is playing you won't get an ENTER_FRAME event until the next frame (at which time it may have moved off that frame).
Be aware that code on a frame executes every time the playhead enters that frame, and you should be careful to remove listeners when appropriate for memory leak purposes.
So one approach would be to place this code on the frame in question - note that it also nicely removes its listener:
var thisFrame:int = currentFrame;
function handleUpdate(e:Event) {
if (currentFrame==thisFrame) {
// your code here...
} else {
// remove listener if we moved off the frame
removeEventListener(Event.ENTER_FRAME, handleUpdate);
}
}
// call it now because the listener won't fire until next frame
handleUpdate(null);
// add listener in prep for next ENTER_FRAME, though note that
// if we move off this frame, then the listener is removed above
addEventListener(Event.ENTER_FRAME, handleUpdate);
Another approach would be adding the following code on frame 1, so the listener always runs and is never cleaned up, and only performs the code when on frame 12:
addEventListener(Event.ENTER_FRAME, handleUpdate);
function handleUpdate(e:Event):void
{
if (currentFrame==12) {
// your code here...
}
}

Disabling button rollover for certain number of frames Flash actionscript 3.0

I'm constructing an area with selectable buttons that transition and appear every 10 frames. During these 10 frame transition periods I don't want the buttons to be selectable and if possible to disable the rollover.
I've tried creating an If statement on the addEventListener so that it only works when currentFrame is 11,21,31 etc but this didn't work. I then also tried the same principal on the function to which the Event Listener relates but still no success.
Does anyone have any ideas?
Add a listener for the ENTER_FRAME event, and put the if in the callback function.
For example
this.addEventListener (Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame (evt:Event):void {
if (currentFrame == 21) {
yourButton.enabled = false;
} else {
yourButton.enabled = true;
}
}
You could do 2 things:
1:
You manually add and remove the listener.
So when you start the transition, the listener is removed,
then when the transition ends, the listener is added.
2:
You make a custom listener which checks for the state of the frame to see whether it should execute its body.
EXAMPLE:
public void listener(event:Event) {
if (event.getSource().stage.getCurrentFrame() == 10) {//This is an example, I don't know whether this specific way will work.
//Run your code here
}
}

Is every MOUSE_DOWN guaranteed a MOUSE_UP?

Are there any circumstances under which a Flash application could receive two MouseEvent.MOUSE_DOWN without a MouseEvent.MOUSE_UP in between?
In my ActionScript 3 application, I want to track the user dragging a sprite. My plan is to listen for a MouseEvent.MOUSE_DOWN, start an indefinitely repeating timer that records the mouse position, and stop the timer on MouseEvent.MOUSE_UP. Is that a good plan?
Click but do not release the button.
While keeping the button down move the cursor outside.
Release the button outside.
Come back inside and click again.
You will get two down event without an up event.
A better solution to drag-and-drop might be to listen MOUSE_MOVE event and in the event handler check buttonDown property. If the button is down while moving, this will be true, otherwise false.
EDIT: For stage even if you release the button outside the flash window then up event is fired. So for stage this can work, but still instead of timer using MOUSE_MOVE with buttonDown looks better to me. You can check yourself with the following code:
public class StageEventTest extends Sprite
{
public function StageEventTest()
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
}
private function onDown(evt:MouseEvent):void {
trace("down");
}
private function onUp(evt:MouseEvent):void {
trace("up");
}
private function onMove(evt:MouseEvent):void {
trace("move", evt.buttonDown);
}
}
it will miss the mouse up event if the mouse is outside of the stage and continue it's mouse tracking when mousing over the stage since the mouse up event was never called. this likely problem can be mitigated by using Event.MOUSE_LEAVE - forward the mouse leave event to the mouse up event handler so that if the user mouses away from the stage the mouse up event will be called.
Yes, but unless you are listening to the stage, I think you can miss the mouseup event if the mouse has gone outside the Flash movie. Nothing beats an experiment though.
Below you can find the code I always use for custom dragging. Normally, it should work fine. I listen to the MOUSE_MOVE-event for repositioning and tracking the sprite, but you can just as well use the Event.ENTER_FRAME-event or use a timer instead.
ObjectToDrag.addEventListener(MouseEvent.MOUSE_DOWN, startCustomDrag);
public function startCustomDrag(e:MouseEvent):void
{
_prevX= e.stageX;
_prevY= e.stageY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject); //REPLACE BY TIMER OR Event.ENTER_FRAME
stage.addEventListener(MouseEvent.MOUSE_UP, stopCustomDrag);
}
private function dragObject(e:MouseEvent):void
{
ObjectToDrag.x += _prevX - e.stageX; //OR ANY OTHER CALCULATION
ObjectToDrag.y += _prevY - e.stageY; //OR ANY OTHER CALCULATION
_prevX= e.stageX;
_prevY= e.stageY;
}
public function stopCustomDrag(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject); //REPLACE BY TIMER OR Event.ENTER_FRAME
stage.removeEventListener(MouseEvent.MOUSE_UP, stopCustomDrag);
}