How To Pause Canvas From Rotating For 2 Secs At Specific Angles?
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?"