Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repeat an action as long button is pressed

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?

like image 282
Miljenko Simovic Avatar asked Apr 03 '12 22:04

Miljenko Simovic


3 Answers

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.

like image 119
Tim Bender Avatar answered Oct 19 '22 15:10

Tim Bender


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 );
    }
}
like image 2
ulmangt Avatar answered Oct 19 '22 16:10

ulmangt


  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...

like image 1
HoratioCain Avatar answered Oct 19 '22 16:10

HoratioCain