2011-10-21 9 views
2

彼の中心の周りの画像(ImageView内のビットマップ)を回転したいと思います。 これは、ビットマップの幅/ 2と高さ/ 2と回転因子として1または-1度の値でpreRotateメソッドを使用することで、うまく動作します。ボタンが押されている間の増減カウンター

しかし、私はボタンとして回転機能を実装しました。 「右回転」ボタンが押されるたびに、画像ビューが右に1度回転するなどします。ボタンを押すといいでしょう。ボタンが押されている間、ボタンが離されるまで画像が回転し始めます。

ここでは、これらの機能がOnClickListenerではなくOnTouchListenerとして実装されているスレッドを読んでいますが、それは私のためには機能しません。 MotionEvent.ACTION_DOWNイベント内にループを実装すると、無限になります。ループを使用しない場合、イベントはOnClickListenerのように一度だけ処理されます。

ボタンを押している間、どのように回転係数を増減できますか?

+0

コードを表示してください。 OnTouchListenerのアプローチは正しいです。 –

答えて

8

短い答え:追加を停止するには、対応するMotionEvent.ACTION_UPを実装する必要があります。 ACTION_DOWNは、ユーザが押し下げたときに一度だけ起動されます。だからあなたがループしていないときには、あなたは1つ増分しか得られないのです。必要なのは、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

あなたの答えをありがとう。それは私に多くの助けになる。私はUIスレッドを更新するために追加のスレッドハンドラを追加するだけでしたが、今はかなりうまくいきます:) – Vion

+0

あなたは大歓迎です。あなたが答えを見つけたら、投票してください。それが正しいと思うなら、それを受け入れるべきです。 –

2

buttonはあなたが実行可能な部材内からアクセスできるようにプライベートメンバであると仮定します。これが私が試みるものです。正確な時間ベースの回転値計算にはSystem.currentTimeMillis()を使用することを検討できます。

ここでアイデア(注意、IDEなしでテストして書かれていない)です:私はより一般的なケースにKnickediの答えを拡張しました

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

が。誰かを助けることを願っています。

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

} 
関連する問題