SparkyNZ
SparkyNZ

Reputation: 6676

How can I repeat/retrigger onLongClick in Android

Hi have a "scrub" or "scan" button on a music player that I'm writing. What I'd like my button to do is jump a number of milliseconds ahead in the tune every couple of second if the user holds the button for a long period of time.

How can I get multiple onLongClick() events to occur if I hold the button? At the moment I only get one and thats it. There must be a way to reset the timer so it happens again surely.. I hope?

Upvotes: 0

Views: 966

Answers (3)

GVillani82
GVillani82

Reputation: 17429

As said in the comment, you can listen for onLongClick() and then stop moving cursor on ACTION_UP event:

v.setOnKeyListener(new OnKeyListener() {    
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if(KeyEvent.ACTION_UP == event.getAction())
            if(isMoving)
            {
                isMoving = false;
                stopMovingCursor();
            }

        return false;
    }
});

v.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        isMoving = true;
        startMovingCursor();
        return false;
    }
}); 

Upvotes: 1

SparkyNZ
SparkyNZ

Reputation: 6676

Here's the solution that I cobbled together thats working well for me. I would have accepted the previous answers but they didn't take into account moving outside of the button's view. I hope the below code helps somebody else out in the same predicament. 90% of this code is not mine - so many thanks to the other stackoverflow posting that provided this.

EDIT: Actually, this is not perfect either - it doesn't animate button touches.

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

public class AutoRepeatButton extends Button
{

  private long     initialRepeatDelay                 = 500;
  private long     repeatIntervalInMilliseconds       = 1000;
  private boolean  mRepeatStarted = false;

  private Runnable repeatClickWhileButtonHeldRunnable = new Runnable()
                                                      {
                                                        @Override
                                                        public void run()
                                                        {
                                                          // Perform the present
                                                          // repetition of the
                                                          // click action
                                                          // provided by the
                                                          // user
                                                          // in
                                                          // setOnClickListener().
                                                          mRepeatStarted = true;

                                                          performLongClick();

                                                          // Schedule the next
                                                          // repetitions of the
                                                          // click action, using
                                                          // a faster repeat
                                                          // interval than the
                                                          // initial repeat
                                                          // delay interval.
                                                          postDelayed( repeatClickWhileButtonHeldRunnable, repeatIntervalInMilliseconds );
                                                        }
                                                      };

  private void commonConstructorCode()
  {
    mRepeatStarted = false;

    this.setOnTouchListener( new OnTouchListener()
    {
      @Override
      public boolean onTouch( View v, MotionEvent event )
      {
        int action = event.getAction();

        if( action == MotionEvent.ACTION_DOWN )
        {
          // Just to be sure that we removed all callbacks,
          // which should have occurred in the ACTION_UP
          removeCallbacks( repeatClickWhileButtonHeldRunnable );

          // Schedule the start of repetitions after a one half second delay.
          postDelayed( repeatClickWhileButtonHeldRunnable, initialRepeatDelay );
        }
        else
        if( action == MotionEvent.ACTION_UP )
        {
          // Cancel any repetition in progress.
          removeCallbacks( repeatClickWhileButtonHeldRunnable );

          if( mRepeatStarted == false )
          {
            // PDS: I put this here..
            performClick();
          }

          mRepeatStarted = false;      
          return true;
        }
        else    
        if( action == MotionEvent.ACTION_MOVE )
        {
          int[] l = new int[2];
          v.getLocationOnScreen( l );

          Rect rect = new Rect( l[0], l[1], l[0] + v.getWidth(), l[1] + v.getHeight() );

          if( ! rect.contains( v.getLeft() + (int) event.getX(),
                               v.getTop()  + (int) event.getY())) 
          {
            // User moved outside bounds
            removeCallbacks( repeatClickWhileButtonHeldRunnable );

            mRepeatStarted = false;
          }
        }
        else
        if( action == MotionEvent.ACTION_CANCEL )
        {
          removeCallbacks( repeatClickWhileButtonHeldRunnable );

          mRepeatStarted = false;
        }

        // Returning true here prevents performClick() from getting called
        // in the usual manner, which would be redundant, given that we are
        // already calling it above.
        return true;
      }
    } );
  }

  public AutoRepeatButton( Context context, AttributeSet attrs, int defStyle )
  {
    super( context, attrs, defStyle );
    commonConstructorCode();
  }

  public AutoRepeatButton( Context context, AttributeSet attrs )
  {
    super( context, attrs );
    commonConstructorCode();
  }

  public AutoRepeatButton( Context context )
  {
    super( context );
    commonConstructorCode();
  }
}

Upvotes: 0

SimonSays
SimonSays

Reputation: 10977

Start a Timer on onLongClick() that executes your jump action every second or two. Stop the Timer when you get the ACTION_UP keyEvent.

Upvotes: 1

Related Questions