2011-10-21 79 views
2

我想旋转他的中心周围的图片(ImageView中的位图)。 通过使用preRotate方法以及位图的宽度/ 2和高度/ 2以及1或-1度作为旋转因子,可以很好地工作。按下按钮时增加/减少计数器

但我实现了旋转功能作为按钮。每次按下“向右旋转”按钮时,Imageview将向右旋转一度,依此类推。按下按钮并且在按下按钮的同时,图片开始旋转直到按钮被释放。

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

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

+0

显示一些代码。 OnTouchListener方法是正确的。 –

回答

8

简答:您需要实现相应的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 

} 
+0

谢谢你的回答。它帮助我很多。我只需要添加一个额外的Threadhandler来更新UI线程,但现在它工作得很好:) – Vion

+0

不客气。如果你找到一个用户的答案,你应该投票。如果你认为这是正确的,你应该接受它。 –

2

假设button是一个私有成员,所以你可以在运行的成员访问它。这是我会尝试的。您可以考虑使用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; 
    } 
}); 
+0

谢谢你的回答。关于精确和基于时间的轮换的想法很好。现在旋转看起来非常好。 – Vion

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

}