2015-11-17 7 views
22

私は回転ノブを作ったが、ノブを特定の角度で2秒間止めたい。私は260fと-20fでそれを止めたい。キャンバスを特定の角度で2秒間回転させないようにするにはどうすればいいですか?

誰でもどのように行うことができますか?

これはブログのコードです。私は自分の要求に応じて多くの変更を加えました。

public class RotatoryKnobView extends ImageView { 

    private float angle = -20f; 
    private float theta_old=0f; 

    private RotaryKnobListener listener; 

    public interface RotaryKnobListener { 
    public void onKnobChanged(float arg); 
    } 

    public void setKnobListener(RotaryKnobListener l) 
    { 
    listener = l; 
    } 

    public RotatoryKnobView(Context context) { 
    super(context); 
    initialize(); 
    } 

    public RotatoryKnobView(Context context, AttributeSet attrs) 
    { 
    super(context, attrs); 
    initialize(); 
    } 

    public RotatoryKnobView(Context context, AttributeSet attrs, int defStyle) 
    { 
    super(context, attrs, defStyle); 
    initialize(); 
    } 

    private float getTheta(float x, float y) 
    { 
    float sx = x - (getWidth()/2.0f); 
    float sy = y - (getHeight()/2.0f); 

    float length = (float)Math.sqrt(sx*sx + sy*sy); 
    float nx = sx/length; 
    float ny = sy/length; 
    float theta = (float)Math.atan2(ny, nx); 

    final float rad2deg = (float)(180.0/Math.PI); 
    float thetaDeg = theta*rad2deg; 

    return (thetaDeg < 0) ? thetaDeg + 360.0f : thetaDeg; 
    } 

    public void initialize() 
    { 
    this.setImageResource(R.drawable.rotoron); 
    setOnTouchListener(new OnTouchListener() 
     { 
@Override 
public boolean onTouch(View v, MotionEvent event) { 
    float x = event.getX(0); 
    float y = event.getY(0); 
    float theta = getTheta(x,y); 

    switch(event.getAction() & MotionEvent.ACTION_MASK) 
    { 
    case MotionEvent.ACTION_POINTER_DOWN: 
     theta_old = theta; 
     break; 
    case MotionEvent.ACTION_MOVE: 
     invalidate(); 
     float delta_theta = theta - theta_old; 
     theta_old = theta; 
     int direction = (delta_theta > 0) ? 1 : -1; 
     angle += 5*direction; 
     notifyListener(angle+20); 
     break; 
    } 
    return true; 
} 
     }); 
    } 

    private void notifyListener(float arg) 
    { 
    if (null!=listener) 
     listener.onKnobChanged(arg); 
    } 

    protected void onDraw(Canvas c) 
    {if(angle==257f){ 
     try { 
      synchronized (c) { 

       c.wait(5000); 
       angle=260f; 
      } 

     } catch (InterruptedException e) { 
     } 
    } 
    else if(angle==-16f) 
    { 
     try { 
      synchronized (c) { 
       c.wait(5000); 
       angle=-20f; 
      } 

     } catch (InterruptedException e) { 

     } 
    } 
    else 
     if(angle>260f) 
      { 

      angle=-20f; 
     } 
     else if(angle<-20f) 
      { 

      angle=260f; 
     } 
     else{ 
      c.rotate(angle,getWidth()/2,getHeight()/2); 

     } 
    super.onDraw(c); 
    } 
} 
+1

以下の回答を無効にするために、完全に異なるものに疑問を変更停止してください。 –

答えて

5

私はここに究極の答えはSurfaceViewを拡張して、onDraw(キャンバスキャンバス)をオーバーライドすることで独自のクラスを実装することだと思います

次に、あなたのコントロールをレンダリングするためにキャンバス・ルーチンを使用することができます。

グーグルなら、多くの優れた例があります。

// So things actually render 
    setDrawingCacheEnabled(true); 
    setWillNotDraw(false); 
    setZOrderOnTop(true); 

    // Controls the drawing thread. 
    getHolder().addCallback(new CallbackSurfaceView()); 

オーバーライドonDrawとあなたのレンダリングルーチンを追加します。表面のビューを初期化し始めるため

。あなたはそれらをレイヤーすることができます。

public void onDraw(Canvas canvas) { 

     // Always Draw 
     super.onDraw(canvas); 

     drawBackground(canvas); 

     drawKnobIndentWell(canvas); 

     drawKnob(canvas); 

     drawKnobLED(canvas); //etc.... 
} 

コールバックと更新スレッドの例:あなたはこのルートを行くことに決めた場合

/** 
* This is the drawing callback. 
* It handles the creation and destruction of the drawing thread when the 
* surface for drawing is created and destroyed. 
*/ 
class CallbackSurfaceView implements SurfaceHolder.Callback { 
    Thread threadIndeterminant; 
    RunnableProgressUpdater runnableUpdater; 
    boolean done = false; 

    /** 
    * Kills the running thread. 
    */ 
    public void done() { 
     done = true; 
     if (null != runnableUpdater) { 
      runnableUpdater.done(); 
     } 
    } 

    /** 
    * Causes the UI to render once. 
    */ 
    public void needRedraw() { 
     if (runnableUpdater != null) { 
      runnableUpdater.needRedraw(); 
     } 
    } 


    /** 
    * When the surface is created start the drawing thread. 
    * @param holder 
    */ 
    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     if (!done) { 
      threadIndeterminant = new Thread(runnableUpdater = new RunnableProgressUpdater()); 
      threadIndeterminant.start(); 
     } 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

    } 

    /** 
    * When the surface is destroyed stop the drawing thread. 
    * @param holder 
    */ 
    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 

     if (null != runnableUpdater) { 
      runnableUpdater.done(); 
      threadIndeterminant = null; 
      runnableUpdater = null; 
     } 
    } 
} 

/** 
* This is the runnable for the drawing operations. It is started and stopped by the callback class. 
*/ 
class RunnableProgressUpdater implements Runnable { 

    boolean surfaceExists = true; 
    boolean needRedraw = false; 

    public void done() { 
     surfaceExists = false; 
    } 

    public void needRedraw() { 
     needRedraw = true; 
    } 


    @Override 
    public void run() { 

     canvasDrawAndPost(); 

     while (surfaceExists) { 

      // Renders continuously during a download operation. 
      // Otherwise only renders when requested. 
      // Necessary so that progress bar and cirlce activity update. 
      if (syncContext.isRunning()) { 
       canvasDrawAndPost(); 
       needRedraw = true; 
      } else if (needRedraw) { 
       canvasDrawAndPost(); 
       needRedraw = false; 
      } 


      try { 
       Thread.sleep(100); 
      } catch (InterruptedException e) { 
       // Don't care 
      } 
     } 


     // One final update 
     canvasDrawAndPost(); 

    } 

    /** 
    * Routine the redraws the controls on each loop. 
    */ 
    private synchronized void canvasDrawAndPost() { 
     Canvas canvas = getHolder().lockCanvas(); 

     if (canvas != null) { 
      try { 
       draw(canvas); 
      } finally { 
       getHolder().unlockCanvasAndPost(canvas); 
      } 
     } 
    } 


} 

あなたは カスタム値を使用してXMLからあなたのコントロールをカスタマイズすることができます。

<com.killerknob.graphics.MultimeterVolumeControl 
     android:id="@+id/volume_control" 
     android:layout_below="@id/divider_one" 
     android:background="@android:color/white" 
     android:layout_width="match_parent" 
     android:layout_height="60dp" 
     android:minHeight="60dp" 
     custom:ledShadow="#357BBB" 
     custom:ledColor="#357BBB" 
     custom:knobBackground="@color/gray_level_13" 
     custom:knobColor="@android:color/black" 
     /> 

あなたはそのパッケージ名でそれを参照するカスタムコントロールを作成します。 /values以下のリソースファイルにカスタム変数を作成し、クラス内で を参照します。ここ

詳細:これは、より多くの仕事であってもよい

http://developer.android.com/training/custom-views/create-view.html

は、あなたは何をしたいが、私はあなたがよりプロフェッショナルな外観のコントロールで終わるだろうと思うと、アニメーションがよりスムーズになります。

いずれにしても、楽しいプロジェクトのようです。がんばろう。

+0

カスタム値の使用方法とカスタム表示クラスの参照方法を示すリンクを追加しました。 – mjstam

+0

進捗状況コードは必要ありません。私は既存のプロジェクトからそのコードを取り出し、更新スレッドとコールバックメカニズムの例を提供しました。 – mjstam

+2

商用コードではありませんし、私のものでもありません。 – mjstam

5

固定角度を設定し、2秒後にpostDelayedを使用してクリアすることができます。

public class RotatoryKnobView extends ImageView { 

    private float angle = -20f; 
    private float theta_old=0f; 

    private RotaryKnobListener listener; 

    private Float fixedAngle; 
    private float settleAngle; 

    private Runnable unsetFixedAngle = new Runnable() { 
     @Override 
     public void run() { 
      angle = settleAngle; 
      fixedAngle = null; 
      invalidate(); 
     } 
    }; 

    public interface RotaryKnobListener { 
     public void onKnobChanged(float arg); 
    } 

    public void setKnobListener(RotaryKnobListener l) 
    { 
     listener = l; 
    } 

    public RotatoryKnobView(Context context) { 
     super(context); 
     initialize(); 
    } 

    public RotatoryKnobView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     initialize(); 
    } 

    public RotatoryKnobView(Context context, AttributeSet attrs, int defStyle) 
    { 
     super(context, attrs, defStyle); 
     initialize(); 
    } 

    private float getTheta(float x, float y) 
    { 
     float sx = x - (getWidth()/2.0f); 
     float sy = y - (getHeight()/2.0f); 

     float length = (float)Math.sqrt(sx*sx + sy*sy); 
     float nx = sx/length; 
     float ny = sy/length; 
     float theta = (float)Math.atan2(ny, nx); 

     final float rad2deg = (float)(180.0/Math.PI); 
     float thetaDeg = theta*rad2deg; 

     return (thetaDeg < 0) ? thetaDeg + 360.0f : thetaDeg; 
    } 

    public void initialize() 
    { 
     this.setImageResource(R.drawable.rotoron); 
     setOnTouchListener(new OnTouchListener() 
     { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       float x = event.getX(0); 
       float y = event.getY(0); 
       float theta = getTheta(x,y); 

       switch(event.getAction() & MotionEvent.ACTION_MASK) 
       { 
        case MotionEvent.ACTION_POINTER_DOWN: 
         theta_old = theta; 
         break; 
        case MotionEvent.ACTION_MOVE: 
         invalidate(); 
         float delta_theta = theta - theta_old; 
         theta_old = theta; 
         int direction = (delta_theta > 0) ? 1 : -1; 
         angle += 5*direction; 
         notifyListener(angle+20); 
         break; 
       } 
       return true; 
      } 
     }); 
    } 

    private void notifyListener(float arg) 
    { 
     if (null!=listener) 
      listener.onKnobChanged(arg); 
    } 

    void setFixedAngle(float angle, float settleAngle) { 
     fixedAngle = angle; 
     this.settleAngle = settleAngle; 
     postDelayed(unsetFixedAngle, 2000); 
    } 

    protected void onDraw(Canvas c) 
    { 
     if(fixedAngle==null) { 
      if (angle > 270) { 
       setFixedAngle(270, -15); 
      } else if (angle < -20f) { 
       setFixedAngle(-20, 260); 
      } 
     } 
     Log.d("angle", "angle: " + angle + " fixed angle: " + fixedAngle); 
     c.rotate(fixedAngle == null ? angle : fixedAngle,getWidth()/2,getHeight()/2); 

     super.onDraw(c); 
    } 
} 

`

+2

サンプルコードでsetFixedAngle()呼び出しを変更しました。 –

+2

申し訳ありませんが、ノブの希望する動作を理解できません。より明確に指定できますか? –

+2

非常に良い答え –

関連する問題