Repeat an action as long button is pressed

Go To StackoverFlow.com

5

Let's say you have a TextView that displays an number like 0 and you have a Button. Now if the user presses the Button the Number in the TextView will increase for one (this i know how to do) but if the user presses the Button and don't release it then the number in the TextView should be increased an this should repeat it self as long the user don't release the Button. In other words: How to increase the Number over and over again as long the user holds down the Button?

2012-04-03 22:02
by Miljenko Simovic


6

A general approach (not specific to Android) would be to detect the press and release event separately. The press event starts a periodic task (Runnable or Thread) which adds to the counter (let us say 5 times a second, or once every 200 ms). The release event stops the periodic task.

2012-04-03 22:08
by Tim Bender


2

You'll need to schedule an asynchronous repeating event when you receive a mousePressed event and stop it when you receive a mouseReleased event.

There's lots of ways to handle this in Java. I like using the java.util.concurrent classes, which are quite flexible. There's a few things to keep in mind though:

If your asynchronous events don't happen on the Event Dispatch Thread, you need to set the JButton text using SwingUtilities.invokeLater().

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Frame
{
    public static void main( String[] args )
    {
        JFrame frame = new JFrame( );
        final JButton button = new JButton( "0" );

        final ScheduledExecutorService executor = Executors.newScheduledThreadPool( 1 );

        button.addMouseListener( new MouseAdapter( )
        {
            int counter = 0;
            ScheduledFuture<?> future;

            @Override
            public void mousePressed( MouseEvent e )
            {
                Runnable runnable = new Runnable( )
                {
                    public void run( )
                    {
                        SwingUtilities.invokeLater( new Runnable( )
                        {
                            public void run( )
                            {
                                button.setText( String.valueOf( counter++ ) );
                            }
                        } );
                    }
                };

                future = executor.scheduleAtFixedRate( runnable, 0, 200, TimeUnit.MILLISECONDS );
            }

            @Override
            public void mouseReleased( MouseEvent e )
            {
                if ( future != null )
                {
                    future.cancel( true );
                }
            }

        } );

        frame.add( button );
        frame.setSize( 400, 400 );
        frame.setVisible( true );
    }
}
2012-04-03 22:23
by ulmangt


1

  1. Set up a View.OnLongClickListener for your button
  2. Give your activity a Runnable, and initialize (but don't start it) when you load the activity
  3. Have the OnLongClickListener do its regular async task of updating the textbox and checking the time since it was first clicked
  4. Create an OnTouchListener that pauses the Runnable when the touch event is realeased.

I know that's a rough draft, but this is a really useful pattern to be able to reuse and modify, so it's worth sinking your talons into it...

2012-04-03 22:15
by HoratioCain
+1 This sounds like the Android specific process I was describing more generically - Tim Bender 2012-04-03 22:21