I have a Custom Class extending Drawable as seen below which is meant to draw an Arc. From my MainActivity controlling the Drawable, I am redrawing it based on some input values that I translate to the appropriate "angle" for the shape. E.g.
This is the initial state of the drawable:
This is the second state of the drawable:
Red arrow indicates the motion i am trying to achieve
I am trying to "animate" the change from state 1 to state 2 with a sweeping motion. Any ideas on how to do that? Should I redraw the shape a number of times gradually transitioning between state one and two?
My Drawable Code:
public class CircleLoadingBar extends Drawable implements Drawable.Callback{
private Paint paint;
private Canvas canvas;
private float angle;
private RectF outterCircle;
private float padding=30;
public void invalidateDrawable(Drawable drawable){
final Callback callback = getCallback();
if (callback != null) {
callback.invalidateDrawable(this);
}
}
public void scheduleDrawable(Drawable drawable, Runnable runnable, long l){
invalidateDrawable(drawable);
}
public void unscheduleDrawable(Drawable drawable,Runnable runnable){
//empty
}
public CircleLoadingBar(){
this(0);
}
public CircleLoadingBar( int angle){
this.angle=angle;
this.canvas=new Canvas();
paint=new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(padding);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStyle(Paint.Style.STROKE);
outterCircle = new RectF();
}
public void setAngle(float angle){
this.angle=angle;
}
#Override
public void draw(Canvas canvas){
canvas.save();
Rect bounds = getBounds();
outterCircle.set(bounds.left+padding,bounds.top+padding,bounds.right-padding,bounds.bottom-padding);
int[] colors = {Color.RED, Color.GREEN, Color.RED};
float[] positions = {0,0.2f,1.3f};
SweepGradient gradient3 = new SweepGradient(innerCircle.centerX(), innerCircle.centerY(),colors,positions);
paint.setShader(gradient3);
canvas.drawArc(outterCircle,90,angle,true,paint);
}
#Override
public void setAlpha(int alpha) {
// Has no effect
}
#Override
public void setColorFilter(ColorFilter cf) {
// Has no effect
}
#Override
public int getOpacity() {
// Not Implemented
return 0;
}
}
My MainActivity Code:
public class MainActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate();
setContentView(R.layout.main);
textView= (TextView) findViewById(R.id.textview);
circleLoadingBar= new CircleLoadingBar(10);
textView.setBackgroundDrawable(circleLoadingBar);
}
public void stateUpdate(float angle) {
circleLoadingBar.setAngle(angle);
textView.invalidate();
}
}
After a lot of searching around, I found the answer.
Summary:
I needed my Custom Drawable class to implement Drawable.Callback and Runnable interfaces (see code below).
CustomDrawable.class
public class CustomDrawable extends Drawable implements Drawable.Callback, Runnable{
private Paint paint;
private Canvas canvas;
private int angle;
private RectF circle;
private float cx,cy;
private float mHeight,mWidth=100;
private float mRadius=20;
private Drawable.Callback cb;
private boolean running=false;
public void invalidateDrawable(Drawable drawable){
super.invalidateSelf(); //This was done for my specific example. I wouldn't use it otherwise
}
public void scheduleDrawable(Drawable drawable, Runnable runnable, long l){
invalidateDrawable(drawable);
}
public void unscheduleDrawable(Drawable drawable,Runnable runnable){
super.unscheduleSelf(runnable);
}
public CircleLoadingBar(){
this(0);
}
public CircleLoadingBar(int angle){
this.angle=angle;
paint=new Paint();
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStyle(Paint.Style.STROKE);
circle= new RectF();
}
#Override
public void draw(Canvas canvas){
canvas.save();
Rect bounds = getBounds();
circle.set(bounds);
canvas.drawArc(circle, 90, angle, true, paint);
}
public void nextFrame(){
unscheduleSelf(this);
scheduleSelf(this, SystemClock.uptimeMillis() + 250);
}
public void stop(){
running=false;
unscheduleSelf(this);
}
public void start(){
if(!running){
running=true;
nextFrame();
}
}
public void run(){
angle++;
invalidate();
nextFrame();
}
#Override
public void setAlpha(int alpha) {
// Has no effect
}
#Override
public void setColorFilter(ColorFilter cf) {
// Has no effect
}
#Override
public int getOpacity() {
// Not Implemented
return 0;
}
}
Now that your Drawable implements both, you can just "run" it as a separate thread, initiated and controlled by your activity via start and stop functions.
Related
My task is Drawing a Circle Diagram.
I have 4 arcs.
On each arc, I have 2 values to make View Animate.
this image
will show you more detail.
Can Anyone Suggest me the Animation should I use for each value?
And how can I make it Animate by Specific Angle?
Edit: I upload .gif file for more detail.
You can make a custom View and a custom animation. Override the applyTransformation() Method in the custom Animation to apply the transformation.
public class ArcView extends View {
private final Paint mPaint;
private final RectF mRect;
private float arcAngle;
public ArcView(Context context, AttributeSet attrs) {
super(context, attrs);
// Set Angle to 0 initially or whatever you want
arcAngle = 0;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4);
mPaint.setColor(Color.WHITE);
mRect = new RectF(2, 2, 78, 78);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(mRect, 90, arcAngle, false, mPaint);
}
public float getArcAngle() {
return arcAngle;
}
public void setArcAngle(float arcAngle) {
this.arcAngle = arcAngle;
}
}
And here is how your animation Class looks like
public class ArcAngleAnimation extends Animation {
private ArcView arcView;
private float oldAngle;
private float newAngle;
public ArcAngleAnimation(ArcView arcView, int newAngle) {
this.oldAngle = arcView.getArcAngle();
this.newAngle = newAngle;
this.arcView = arcView;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime);
arcView.setArcAngle(angle);
arcView.requestLayout();
}
public void setNewAngle(int newAngle){
this.newAngle = newAngle;
}
public void setOldAngle(float oldAngle) {
this.oldAngle = oldAngle;
}
}
Now all you need to do is apply animation and run it in your activity or fragment
ArcView view = (ArcView) findViewById(R.id.arc_view);
ArcAngleAnimation arcAnimation;
arcAnimation = new ArcAngleAnimation(view, 30);
arcAnimation.setFillAfter(true);
arcAnimation.setDuration(200);
view.startAnimation(arcAnimation);
The following code it's an activity class with a custom view class. This code is the only working example of canvas for me.
I just need to recall in loop the onDraw function (like animationframe in javascript canvas2d).
I can always use timers to make a call but maybe there is some low level nice way for that. I'm a newbie in Android development.
Question update: I use class name instead of instance name. No need for static for sure.
Current status : crash on activate activity.
public class CanvasNativeSurface extends AppCompatActivity {
private GoogleApiClient client;
private myview myView;
private Handler mHandler;
class myview extends View
{
private void init() {
}
public myview(Context context) {
super(context);
init();
}
int x=80;
int y=180;
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
x=80;
y = y + 1;
int radius=40;
Paint paint=new Paint();
// Use Color.parseColor to define HTML colors
paint.setColor(Color.parseColor("#CD5C5C"));
canvas.drawCircle(x,y, radius, paint);
}
public void move()
{
y= y+30;// 30 is value for testing
// change it to whatever you want.
invalidate();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewGroup view1;
view1 = (ViewGroup) findViewById( R.id.activity_canvas_native_surface );
/// setContentView(R.layout.activity_canvas_native_surface );
setContentView(new myview(this));
mHandler = new Handler();
mHandler.postDelayed(mRunnable, 1000);
}
private Runnable mRunnable = new Runnable() {
#Override
public void run() {
myView.move();
mHandler.postDelayed(this, 1000);
}
};
y = y + 1; Must push object to the bottom. Circle has no movement.
Catch in log:
Attempt to invoke virtual method 'void....CanvasNativeSurface$myview.move()' on a null object reference
Also Android Studio on mouseover it says: myView never assingned
MyView.jav // separate file
public class MyView extends View
{
private int x=80,y=180,radius=40;
private Paint paint;
public MyView(Context context) {
super(context);
init();
}
public void init() {
paint=new Paint();
paint.setColor(Color.parseColor("#CD5C5C"));
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawCircle(x,y, radius, paint);
}
public void move()
{
y= y+30;// 30 is value for testing
// change it to whatever you want.
invalidate();
}
}
And in your activity you can do something like
private MyView myView;
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(myView);
mHandler = new Handler();
mHandler.postDelayed(mRunnable, 1000);
}
private Runnable mRunnable = new Runnable() {
#Override
public void run() {
myView.move();
mHandler.postDelayed(this, 1000);
}
};
Finally don't forget to
mHandler.removeCallbacksAndMessages(mRunnable);
When you want to stop.
As i said earlier you don't need setWillNotDraw(false); and your constructor is called only once.
You probably need a timer mechanism to move the circle every second or something. I hope you got the idea and you can make changes accordingly.
If you are looking for animation
public class MyView extends View
{
private int x=80,y=180,radius=40;
private Paint paint;
public MyView(Context context) {
super(context);
init();
}
public void init() {
paint=new Paint();
paint.setColor(Color.parseColor("#CD5C5C"));
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawCircle(x,y, radius, paint);
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setStateOnObject(){
// 900 is the end value
ObjectAnimator animateBottom = ObjectAnimator.ofFloat(this,"y",y,900);
animateBottom.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
postInvalidate();
}
});
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(animateBottom);
animatorSet.setDuration(5000).start();
}
}
And instead of handler you would do
myView.setStateOnObject();
I'm creating a custom view in which I have a rectangle RectF object that have a specific height. I would like to increase the bottom Y point coordinate to a specific value with a progressive animation.
I've tried the following. I've created a method setBatteryState() that is called on a onclicked method in the activity that holds the custom view:
public class BatteryView extends View {
public int mCanvasWidth;
public int mCanvasHeight;
public RectF mBatteryHead;
public RectF mBatteryBody;
public RectF mBatteryBodyVolume;
public Canvas mCanvas;
public BatteryView(Context context) {
super(context);
}
public BatteryView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void init()
{
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
this.mCanvas = canvas;
float batteryHeadDistanceFromLeft = mCanvasWidth / 3;
float batteryHeadWidth = mCanvasWidth / 3;
float batteryBodyDistanceFromTop = mCanvasHeight / 5;
float batteryHeadHeight = mCanvasHeight / 5;
mBatteryHead = new RectF(batteryHeadDistanceFromLeft,0,2*batteryHeadWidth,batteryHeadHeight+5);
Paint batteryHeadPaint = new Paint();
batteryHeadPaint.setColor(ContextCompat.getColor(getContext(), R.color.batifyColor));
canvas.drawRect(mBatteryHead,batteryHeadPaint);
mBatteryBody = new RectF(0,(int)batteryBodyDistanceFromTop,mCanvasWidth,mCanvasHeight);
Paint batteryBodyPaint = new Paint();
batteryBodyPaint.setStyle(Paint.Style.STROKE);
batteryBodyPaint.setColor(ContextCompat.getColor(getContext(), R.color.batifyColor));
batteryBodyPaint.setStrokeWidth(10);
canvas.drawRect(mBatteryBody,batteryBodyPaint);
mBatteryBodyVolume = new RectF(12,(int)batteryBodyDistanceFromTop + 10,mCanvasWidth-12,mCanvasHeight/2);
Paint volumeBodyPaint = new Paint();
volumeBodyPaint.setColor(ContextCompat.getColor(getContext(), R.color.batifyColor));
canvas.drawRect(mBatteryBodyVolume,volumeBodyPaint);
}
public void setStateOnBattery(){
ObjectAnimator animateBottom = ObjectAnimator.ofFloat(mBatteryBodyVolume, "bottom", mBatteryBodyVolume.bottom, mCanvasHeight);
animateBottom.setDuration(1000).start();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
mCanvasWidth = MeasureSpec.getSize(widthMeasureSpec);
mCanvasHeight = MeasureSpec.getSize(heightMeasureSpec);
}}
ObjectAnimator should translate the rect mBatteryBodyVolume to the size of the canvas but nothing change...
Any Idea ?
Thanks in advance !
Use an asynchronous task with 2 major functions, draw and update. Every time update is called, increase the height variable by a constant. Then, in draw, draw your rectangle with height as a param. If you need code, just ask. :D
UPDATE
Create a 'runner' async task:
public class Runner extends Thread {
public volatile boolean running = true;
private Environment env;
public Runner(Environment E) {
env = E;
}
#Override
public void run() {
long lastTime = System.currentTimeMillis();
while(running) {
long now = System.currentTimeMillis();
long elapsed = now - lastTime;
env.update(elapsed);
env.draw();
lastTime = now;
}
}
public void shutdown() {
running = false;
}
}
In Environment, Do the following:
public void draw() {
Canvas canvas = holder.lockCanvas();
if (canvas != null) {
canvas.drawRect(x-w, y-h, x+w, y+h, myPaint);
holder.unlockCanvasAndPost(canvas);
}
}
and the update method:
public void update(float elapsedTime) {
h+=myKonstant*elpasedTime;
}
Hope I Helped :D
Background
I've been searching in plenty of places to find out how to animate a drawable without animating the view and without using the built in drawables.
The reason is that I will need to prepare a customized animation within the drawable, and I might have different requirements for it later.
For now, I'm making a basic animated drawable that just spins a given bitmap inside it.
I've set it on an imageView, but I wish to be able to use it on any kind of view, even customized views that have overridden the onDraw function.
The problem
I can't find out how to show the drawable without being cut, no matter what the size of the view is. Here's what I see:
The code
Here's the code:
private class CircularAnimatedDrawable extends Drawable implements Animatable {
private static final Interpolator ANGLE_INTERPOLATOR = new LinearInterpolator();
private static final int ANGLE_ANIMATOR_DURATION = 2000;
private final RectF fBounds = new RectF();
private float angle = 0;
private ObjectAnimator mObjectAnimatorAngle;
private final Paint mPaint;
private boolean mRunning;
private final Bitmap mBitmap;
public CircularAnimatedDrawable(final Bitmap bitmap) {
this.mBitmap = bitmap;
mPaint = new Paint();
setupAnimations();
}
public float getAngle() {
return this.angle;
}
public void setAngle(final float angle) {
this.angle = angle;
invalidateSelf();
}
#Override
public Callback getCallback() {
return mCallback;
}
#Override
public void draw(final Canvas canvas) {
canvas.save();
canvas.rotate(angle);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
canvas.restore();
}
#Override
public void setAlpha(final int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(final ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
#Override
protected void onBoundsChange(final Rect bounds) {
super.onBoundsChange(bounds);
fBounds.left = bounds.left;
fBounds.right = bounds.right;
fBounds.top = bounds.top;
fBounds.bottom = bounds.bottom;
}
private void setupAnimations() {
mObjectAnimatorAngle = ObjectAnimator.ofFloat(this, "angle", 360f);
mObjectAnimatorAngle.setInterpolator(ANGLE_INTERPOLATOR);
mObjectAnimatorAngle.setDuration(ANGLE_ANIMATOR_DURATION);
mObjectAnimatorAngle.setRepeatMode(ValueAnimator.RESTART);
mObjectAnimatorAngle.setRepeatCount(ValueAnimator.INFINITE);
}
#Override
public void start() {
if (isRunning())
return;
mRunning = true;
mObjectAnimatorAngle.start();
invalidateSelf();
}
#Override
public void stop() {
if (!isRunning())
return;
mRunning = false;
mObjectAnimatorAngle.cancel();
invalidateSelf();
}
#Override
public boolean isRunning() {
return mRunning;
}
}
and the usage :
final ImageView imageView = (ImageView) findViewById(R.id.imageView);
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.spinner_76_inner_holo);
final CircularAnimatedDrawable circularAnimatedDrawable = new CircularAnimatedDrawable(bitmap);
circularAnimatedDrawable.setCallback(imageView);
circularAnimatedDrawable.start();
imageView.setImageDrawable(circularAnimatedDrawable);
The question
How can I set it to make the drawable fit the view?
Should I use the bitmap size? the fBounds? both? Or maybe something else?
try this modified version of your Drawable:
class CircularAnimatedDrawable extends Drawable implements Animatable, TimeAnimator.TimeListener {
private static final float TURNS_PER_SECOND = 0.5f;
private Bitmap mBitmap;
private boolean mRunning;
private TimeAnimator mTimeAnimator = new TimeAnimator();
private Paint mPaint = new Paint();
private Matrix mMatrix = new Matrix();
public CircularAnimatedDrawable(final Bitmap bitmap) {
mBitmap = bitmap;
mTimeAnimator.setTimeListener(this);
}
#Override
public void draw(final Canvas canvas) {
canvas.drawBitmap(mBitmap, mMatrix, mPaint);
}
#Override
protected void onBoundsChange(Rect bounds) {
Log.d(TAG, "onBoundsChange " + bounds);
mMatrix.setRectToRect(new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight()),
new RectF(bounds),
Matrix.ScaleToFit.CENTER);
}
#Override
public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
Rect b = getBounds();
mMatrix.postRotate(360 * TURNS_PER_SECOND * deltaTime / 1000, b.centerX(), b.centerY());
invalidateSelf();
}
#Override
public void setAlpha(final int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(final ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
#Override
public void start() {
if (isRunning())
return;
mRunning = true;
mTimeAnimator.start();
invalidateSelf();
}
#Override
public void stop() {
if (!isRunning())
return;
mRunning = false;
mTimeAnimator.cancel();
invalidateSelf();
}
#Override
public boolean isRunning() {
return mRunning;
}
}
EDIT: version without Animator stuff (uses [un]scheduleSelf), NOTE it uses View's Drawable.Callback mechanism so it usually cannot be started directly from onCreate where View doesn't have attached Handler yet
class CircularAnimatedDrawable extends Drawable implements Animatable, Runnable {
private static final float TURNS_PER_SECOND = 0.5f;
private static final long DELAY = 50;
private Bitmap mBitmap;
private long mLastTime;
private boolean mRunning;
private Paint mPaint = new Paint();
private Matrix mMatrix = new Matrix();
public CircularAnimatedDrawable(final Bitmap bitmap) {
mBitmap = bitmap;
}
#Override
public void draw(final Canvas canvas) {
canvas.drawBitmap(mBitmap, mMatrix, mPaint);
}
#Override
protected void onBoundsChange(Rect bounds) {
Log.d(TAG, "onBoundsChange " + bounds);
mMatrix.setRectToRect(new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight()),
new RectF(bounds),
Matrix.ScaleToFit.CENTER);
}
#Override
public void setAlpha(final int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(final ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
#Override
public void start() {
if (isRunning())
return;
mRunning = true;
mLastTime = SystemClock.uptimeMillis();
scheduleSelf(this, 0);
invalidateSelf();
}
#Override
public void stop() {
if (!isRunning())
return;
mRunning = false;
unscheduleSelf(this);
invalidateSelf();
}
#Override
public boolean isRunning() {
return mRunning;
}
#Override
public void run() {
long now = SystemClock.uptimeMillis();
Rect b = getBounds();
long deltaTime = now - mLastTime;
mLastTime = now;
mMatrix.postRotate(360 * TURNS_PER_SECOND * deltaTime / 1000, b.centerX(), b.centerY());
scheduleSelf(this, now + DELAY);
invalidateSelf();
}
}
ok, the fix is:
#Override
public void draw(final Canvas canvas) {
canvas.save();
canvas.rotate(angle, fBounds.width() / 2 + fBounds.left, fBounds.height() / 2 + fBounds.top);
canvas.translate(fBounds.left, fBounds.top);
canvas.drawBitmap(mBitmap, null, new Rect(0, 0, (int) fBounds.width(), (int) fBounds.height()), mPaint);
canvas.restore();
}
#Override
public int getIntrinsicHeight() {
return mBitmap.getHeight();
}
#Override
public int getIntrinsicWidth() {
return mBitmap.getWidth();
}
It works fine. I hope it will be enough for the future changes.
EDIT: here's an optimization to the above, including all changes:
class CircularAnimatedDrawable extends Drawable implements Animatable {
private static final Interpolator ANGLE_INTERPOLATOR = new LinearInterpolator();
private static final int ANGLE_ANIMATOR_DURATION = 2000;
private float angle = 0;
private ObjectAnimator mObjectAnimatorAngle;
private final Paint mPaint;
private boolean mRunning;
private final Bitmap mBitmap;
private final Matrix mMatrix = new Matrix();
public CircularAnimatedDrawable(final Bitmap bitmap) {
this.mBitmap = bitmap;
mPaint = new Paint();
mPaint.setAntiAlias(true);
setupAnimations();
}
#SuppressWarnings("unused")
public float getAngle() {
return this.angle;
}
#SuppressWarnings("unused")
public void setAngle(final float angle) {
this.angle = angle;
invalidateSelf();
}
#Override
public void draw(final Canvas canvas) {
final Rect b = getBounds();
canvas.save();
canvas.rotate(angle, b.centerX(), b.centerY());
canvas.drawBitmap(mBitmap, mMatrix, mPaint);
canvas.restore();
}
#Override
public void setAlpha(final int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(final ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
#Override
protected void onBoundsChange(final Rect bounds) {
super.onBoundsChange(bounds);
mMatrix.setRectToRect(new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight()), new RectF(bounds),
Matrix.ScaleToFit.CENTER);
}
#Override
public int getIntrinsicHeight() {
return mBitmap.getHeight();
}
#Override
public int getIntrinsicWidth() {
return mBitmap.getWidth();
}
private void setupAnimations() {
mObjectAnimatorAngle = ObjectAnimator.ofFloat(this, "angle", 360f);
mObjectAnimatorAngle.setInterpolator(ANGLE_INTERPOLATOR);
mObjectAnimatorAngle.setDuration(ANGLE_ANIMATOR_DURATION);
mObjectAnimatorAngle.setRepeatMode(ValueAnimator.RESTART);
mObjectAnimatorAngle.setRepeatCount(ValueAnimator.INFINITE);
}
#Override
public void start() {
if (isRunning())
return;
mRunning = true;
mObjectAnimatorAngle.start();
invalidateSelf();
}
#Override
public void stop() {
if (!isRunning())
return;
mRunning = false;
mObjectAnimatorAngle.cancel();
invalidateSelf();
}
#Override
public boolean isRunning() {
return mRunning;
}
}
I want to have a seek bar that I can show range of acceptable values like below. I know the method of setting a custom drawable to seek bar. My question is how I can build this kind of drawable with partial green part in xml.Thanks in advanced.
use this Drawable, call it with SeekBar.setProgressDrawable()
public class PartialDrawable extends Drawable {
private float mStart;
private float mEnd;
private Paint mPaint;
public PartialDrawable(float start, float end) {
mStart = start;
mEnd = end;
mPaint = new Paint();
}
#Override
public void draw(Canvas canvas) {
Rect b = getBounds();
mPaint.setColor(0xff888888);
canvas.drawRect(b,mPaint);
mPaint.setColor(0xff00aa00);
canvas.drawRect(b.width() * mStart, b.top, b.width() * mEnd, b.bottom, mPaint);
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
I don't think that the standard SeekBar provides a minimum and a maximum "acceptable" values.
What you can do is to simply add a background, using the method
mySeekBar.setProgressDrawable(Drawable d);
And build an image with grey and green that will be stretched.