Skip to content Skip to sidebar Skip to footer

How To Pause Canvas From Rotating For 2 Secs At Specific Angles?

I made a rotating knob ,but I want to stop the knob at specific angles for 2 seconds. I want to stop it on 260f and -20f. Can anyone suggest how to do it ? This is the code from a

Solution 1:

You may set a fixed angle and use postDelayed to clear it after 2 seconds.

publicclassRotatoryKnobViewextendsImageView {

    privatefloatangle= -20f;
    privatefloat theta_old=0f;

    private RotaryKnobListener listener;

    private Float fixedAngle;
    privatefloat settleAngle;

    privateRunnableunsetFixedAngle=newRunnable() {
        @Overridepublicvoidrun() {
            angle = settleAngle;
            fixedAngle = null;
            invalidate();
        }
    };

    publicinterfaceRotaryKnobListener {
        publicvoidonKnobChanged(float arg);
    }

    publicvoidsetKnobListener(RotaryKnobListener l )
    {
        listener = l;
    }

    publicRotatoryKnobView(Context context) {
        super(context);
        initialize();
    }

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

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

    privatefloatgetTheta(float x, float y)
    {
        floatsx= x - (getWidth() / 2.0f);
        floatsy= y - (getHeight() / 2.0f);

        floatlength= (float)Math.sqrt( sx*sx + sy*sy);
        floatnx= sx / length;
        floatny= sy / length;
        floattheta= (float)Math.atan2( ny, nx );

        finalfloatrad2deg= (float)(180.0/Math.PI);
        floatthetaDeg= theta*rad2deg;

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

    publicvoidinitialize()
    {
        this.setImageResource(R.drawable.rotoron);
        setOnTouchListener(newOnTouchListener()
        {
            @OverridepublicbooleanonTouch(View v, MotionEvent event) {
                floatx= event.getX(0);
                floaty= event.getY(0);
                floattheta= getTheta(x,y);

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

    privatevoidnotifyListener(float arg)
    {
        if (null!=listener)
            listener.onKnobChanged(arg);
    }

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

    protectedvoidonDraw(Canvas c)
    {
        if(fixedAngle==null) {
            if (angle > 270) {
                setFixedAngle(270, -15);
            } elseif (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);
    }
}

`

Solution 2:

I think the ultimate answer here is to implement your own class by extending SurfaceView and then overriding onDraw( Canvas canvas )

You can then use the Canvas routines to render your control.

There are a lot of good examples out there if you google.

To get started initialize the surface view:

// So things actually rendersetDrawingCacheEnabled(true);
    setWillNotDraw(false);
    setZOrderOnTop(true);

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

Override onDraw and add your rendering routines. You can layer them as you go.

public void onDraw(Canvas canvas) {

      // Always Draw
      super.onDraw(canvas);

      drawBackground(canvas);

      drawKnobIndentWell(canvas);

      drawKnob(canvas);

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

An example of a Callback and an update thread:

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

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

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


    /**
     * When the surface is created start the drawing thread.
     * @paramholder
     */@OverridepublicvoidsurfaceCreated(SurfaceHolder holder) {
        if (!done) {
            threadIndeterminant = newThread(runnableUpdater = newRunnableProgressUpdater());
            threadIndeterminant.start();
        }
    }

    @OverridepublicvoidsurfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    /**
     * When the surface is destroyed stop the drawing thread.
     * @paramholder
     */@OverridepublicvoidsurfaceDestroyed(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.
 */classRunnableProgressUpdaterimplementsRunnable {

    boolean surfaceExists = true;
    boolean needRedraw = false;

    publicvoiddone() {
        surfaceExists = false;
    }

    publicvoidneedRedraw() {
        needRedraw = true;
    }


    @Overridepublicvoidrun() {

        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;
            } elseif (needRedraw) {
                canvasDrawAndPost();
                needRedraw = false;
            }


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


        // One final updatecanvasDrawAndPost();

    }

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

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


}

If you decide to go this route you can customize your control from XML using custom values.

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

When you create a custom control you reference it by its package name. You create custom variable in a resource file under /values and then reference them in your class.

More details here:

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

This may be more work then you want to do, but I think you will end up with a more professional looking control and the animations will be smoother.

At any rate, looks like a fun project. Good Luck.

Post a Comment for "How To Pause Canvas From Rotating For 2 Secs At Specific Angles?"