Button increase / decrease counter

I want to rotate the image (the bitmap inside the ImageView) around its center. This works pretty well, using the preRotate method with width / 2 and height / 2 Bitmap and 1 or -1 degrees as the rotation coefficient.

But I implemented rotation functions like buttons. Each time the "Rotate Right" button is pressed, the image is viewed one degree to the right and so on. It would be nice to press the button, and when the button is pressed, the image will begin to rotate until the button is released.

I read some topics here in which this function is implemented as OnTouchListener and not OnClickListener, but this does not work for me. If I implement loops in the MotionEvent.ACTION_DOWN event, then they are infinite. If I do not use loops, the event is processed only once (for example, in OnClickListener).

So, how can I increase / decrease the speed of rotation when a button is pressed?

+2
android graphics
source share
3 answers

Short answer: you need to implement the corresponding MotionEvent.ACTION_UP in order to stop adding. ACTION_DOWN is only triggered once when the user clicks down. Therefore, when you did not go in cycles, you received only one gain. You need a separate thread to start doing increments when executing MotionEvent.ACTION_DOWN and stop them when starting MotionEvent.ACTION_UP. Something like this should work.

public MyActivity extends Activity{ private bool continueIncrementing; private Runnable incrementerThread; //put this OnTouchListener on your button View.OnTouchListener downListener = new View.OnTouchListner(){ public onTouch(View v, MotionEvent event){ if(event == MotionEvent.ACTION_DOWN){ startIncrmenting(); } else if(event == MotionEvent.ACTION_UP){ stopIncrementing(); } } }; private void startIncrmenting(){ setIsIncrementing(true); new Thread(new Runnable() { public void run() { while(isIncrementing()){ //do incrementing in here } } }).start(); } sychronized private void stopIncrmenting(){ setIsIncrementing(false); } sychronized private bool isIncrmenting(){ return continueIncrementing; } synhronized void setIsIncrmenting(bool newSetting){ continueIncrementing = newSetting; } //rest of your activity } 
+9
source share

I extended Nikkedi's answer to a more general case. Hope that helps someone.

 import android.view.MotionEvent; import android.view.View; public abstract class OnTouchContinuousListener implements View.OnTouchListener { private final int mInitialRepeatDelay; private final int mNormalRepeatDelay; private View mView; /** * Construct listener with default delays */ public OnTouchContinuousListener() { this.mInitialRepeatDelay = 500; this.mNormalRepeatDelay = 200; } /** * * Construct listener with configurable delays * * * @param initialRepeatDelay * delay to the first repeat in millis * @param normalRepeatDelay * delay to subsequent repeats in millis */ public OnTouchContinuousListener(int initialRepeatDelay, int normalRepeatDelay) { this.mInitialRepeatDelay = initialRepeatDelay; this.mNormalRepeatDelay = normalRepeatDelay; } private final Runnable repeatRunnable = new Runnable() { @Override public void run() { // as long the button is press we continue to repeat if (mView.isPressed()) { // Fire the onTouchRepeat event onTouchRepeat(mView); // Schedule the repeat mView.postDelayed(repeatRunnable, mNormalRepeatDelay); } } }; /** * Called when a touch event is dispatched to a view. This allows listeners to * get a chance to respond before the target view. * * @param v * The view the touch event has been dispatched to. * @param event * The MotionEvent object containing full information about the * event. * @return True if the listener has consumed the event, false otherwise. */ @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mView = v; // Fire the first touch straight away onTouchRepeat(mView); // Start the incrementing with the initial delay mView.postDelayed(repeatRunnable, mInitialRepeatDelay); } // don't return true, we don't want to disable buttons default behavior return false; } /** * Called when the target item should be changed due to continuous touch. This * happens at first press, and also after each repeat timeout. Releasing the * touch will stop the repeating. * */ public abstract void onTouchRepeat(View view); } 
+8
source share

Suppose button is a private member, so you can access it in an executable element. This is what I would like to try. You can use System.currentTimeMillis() to accurately calculate the rotation time in time.

Here's the idea (carefully, not tested, and written without an IDE):

 private Runnable rotationRunnable = new Runnable() { @Override public void run() { // perform rotation step here // as long the button is press we fire the rotation again if (button.isPressed()) { button.postDelayed(rotationRunnable, 40); } } }; // in onCreate button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // inital start of rotation v.post(rotationRunnable); } // don't return ture, we don't want to disable buttons default behavior return false; } }); 
+2
source share

All Articles