2015-11-17 4 views
22

मैंने घूर्णन घुंडी बनाया, लेकिन मैं 2 सेकंड के लिए विशिष्ट कोणों पर घुंडी को रोकना चाहता हूं। मैं इसे 260 एफ और -20 एफ पर रोकना चाहता हूं।विशिष्ट कोणों पर 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 (कैनवास कैनवास) द्वारा अपने स्वयं के वर्ग को लागू

फिर आप कैनवास दिनचर्या का उपयोग कर सकते अपने नियंत्रण रेंडर करने के लिए है।

यदि आप Google हैं तो वहां बहुत अच्छे उदाहरण हैं।

आरंभ करने के लिए सतह दृश्य प्रारंभ:

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


} 

आप इस मार्ग आप कस्टम मानों का उपयोग कर एक्सएमएल से अपने नियंत्रण अनुकूलित कर सकते हैं जाने के लिए निर्णय लेते हैं।

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

जब आप कस्टम नियंत्रण बनाते हैं तो आप इसे अपने पैकेज नाम से संदर्भित करते हैं। आप संसाधन फ़ाइल में कस्टम मान को/मानों के अंतर्गत बनाते हैं और फिर को अपनी कक्षा में संदर्भित करते हैं।

अधिक यहाँ विवरण:

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

यह और अधिक काम हो सकता है तो आप क्या करना चाहते हैं, लेकिन मुझे लगता है कि आप एक और अधिक पेशेवर लग रही नियंत्रण के साथ खत्म हो जाएगा और एनिमेशन चिकनी हो जाएगा।

किसी भी दर पर, एक मजेदार परियोजना की तरह दिखता है। शुभ लाभ।

+0

कस्टम लिंक का उपयोग करने और कस्टम व्यू क्लास को संदर्भित करने के तरीके को दिखाते हुए एक लिंक जोड़ा गया। – mjstam

+0

आपको प्रगति अद्यतनकर्ता कोड की आवश्यकता नहीं है। मैंने उस थ्रेड को एक मौजूदा प्रोजेक्ट से अद्यतन थ्रेड और कॉलबैक तंत्र प्रदान करने और उदाहरण के लिए खींच लिया। – mjstam

+2

मैं वाणिज्यिक कोड नहीं कर सकता और यह मेरा नहीं है। – mjstam

5

आप एक निश्चित कोण सेट कर सकते हैं और दो सेकंड के बाद इसे साफ़ करने के लिए पोस्ट का उपयोग कर सकते हैं।

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

बहुत अच्छा जवाब –

संबंधित मुद्दे