2015-11-17 16 views
22

Tôi đã thực hiện núm xoay, nhưng tôi muốn dừng núm ở các góc cụ thể trong 2 giây. Tôi muốn dừng nó trên 260f và -20f.Làm cách nào để tạm dừng canvas xoay trong 2 giây ở các góc cụ thể?

Có ai có thể đề xuất cách thực hiện không?

Đây là mã từ blog. Tôi đã thực hiện nhiều thay đổi theo yêu cầu của tôi.

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

Hãy dừng việc thay đổi câu hỏi để một cái gì đó hoàn toàn khác nhau để làm mất hiệu lực các câu trả lời dưới đây. –

Trả lời

5

Tôi nghĩ câu trả lời cuối cùng ở đây là để thực hiện lớp của riêng bạn bằng cách mở rộng SurfaceView và sau đó trọng onDraw (Canvas canvas)

Sau đó bạn có thể sử dụng các thói quen Canvas để render kiểm soát của bạn.

Có rất nhiều ví dụ hay ở ngoài đó nếu bạn google.

Để bắt đầu khởi tạo cái nhìn bề mặt:

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

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

Override onDraw và thêm thói quen vẽ của bạn. Bạn có thể xếp lớp chúng khi bạn đi.

public void onDraw(Canvas canvas) { 

     // Always Draw 
     super.onDraw(canvas); 

     drawBackground(canvas); 

     drawKnobIndentWell(canvas); 

     drawKnob(canvas); 

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

Một ví dụ về Callback và một chủ đề cập nhật:

/** 
* 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); 
      } 
     } 
    } 


} 

Nếu bạn quyết định đi tuyến đường này, bạn có thể tùy chỉnh kiểm soát của bạn từ XML sử dụng giá trị tùy chỉnh.

<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" 
     /> 

Khi bạn tạo điều khiển tùy chỉnh, bạn sẽ tham chiếu nó theo tên gói. Bạn tạo biến tùy chỉnh trong tệp tài nguyên trong/giá trị và sau đó tham chiếu chúng trong lớp học của bạn.

Xem thêm chi tiết ở đây:

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

Điều này có thể làm việc nhiều hơn sau đó bạn muốn làm, nhưng tôi nghĩ rằng bạn sẽ kết thúc với một điều khiển tìm kiếm chuyên nghiệp hơn và các hình ảnh động sẽ mượt mà hơn.

Ở mọi mức độ, trông giống như một dự án thú vị. Chúc may mắn.

+0

Đã thêm liên kết hiển thị cách sử dụng giá trị tùy chỉnh và tham chiếu một lớp chế độ xem tùy chỉnh. – mjstam

+0

Bạn không cần mã cập nhật tiến trình. Tôi đã lấy mã đó từ một dự án hiện có để cung cấp và ví dụ về một chủ đề cập nhật và cơ chế gọi lại. – mjstam

+2

Tôi không thể là mã thương mại và không thuộc về tôi. – mjstam

5

Bạn có thể đặt góc cố định và sử dụng postDelayed để xóa nó sau 2 giây.

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

Tôi đã thay đổi các lệnh gọi setFixedAngle() trong mã ví dụ. –

+2

Xin lỗi, tôi không thể hiểu hành vi mong muốn của núm. Bạn có thể chỉ định rõ ràng hơn không? –

+2

Câu trả lời rất hay –

Các vấn đề liên quan