按下按钮时递增/递减计数器

时间:2011-10-21 16:23:13

标签: android graphics

我想围绕他的中心旋转图片(ImageView中的位图)。 通过使用preRotate方法和Bitmap的值width / 2和height / 2以及1或-1度作为旋转因子,这非常有效。

但是我将旋转功能实现为按钮。每次按下“向右旋转”按钮时,Imageview会向右旋转一度,依此类推。按下按钮会很不错,按下按钮时图片开始旋转,直到按钮被释放。

我在这里阅读了一些线程,其中这些功能实现为OnTouchListener而不是OnClickListener,但它对我不起作用。如果我在MotionEvent.ACTION_DOWN事件中实现循环,那么它们是无限的。如果我不使用循环,那么事件只处理一次(如在OnClickListener中)。

那么在按下按钮时如何递增/递减旋转因子?

3 个答案:

答案 0 :(得分:9)

简短回答:您需要实现相应的MotionEvent.ACTION_UP来停止添加。当用户按下时,ACTION_DOWN只被触发一次。这就是为什么当你没有循环时,你只有一个增量。你需要的是一个单独的线程,当MotionEvent.ACTION_DOWN完成时开始进行增量,并在触发MotionEvent.ACTION_UP时停止它们。这样的事情应该有效。

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

}

答案 1 :(得分:8)

我已将Knickedi的答案扩展到一个更通用的案例。希望有所帮助。

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);

}

答案 2 :(得分:2)

假设button是私有成员,因此您可以在runnable成员中访问它。这就是我想要的。您可以考虑使用System.currentTimeMillis()进行精确和基于时间的旋转值计算。

这是一个想法(谨慎,未经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;
    }
});