【问题标题】:Android: Animate Custom Drawable programmaticallyAndroid:以编程方式为自定义 Drawable 设置动画
【发布时间】:2015-04-30 14:52:39
【问题描述】:

我有一个扩展 Drawable 的自定义类,如下所示,用于绘制弧线。从我控制 Drawable 的 MainActivity 中,我根据一些输入值重新绘制它,这些输入值我转换为形状的适当“角度”。例如

这是可绘制对象的初始状态:

这是可绘制对象的第二个状态:红色箭头表示我想要实现的动作

我正在尝试通过扫动来“动画化”从状态 1 到状态 2 的变化。关于如何做到这一点的任何想法?我是否应该在状态一和状态二之间逐渐过渡多次重绘形状?

我的可绘制代码:

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

我的 MainActivity 代码:

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

【问题讨论】:

    标签: android android-animation android-drawable


    【解决方案1】:

    经过大量搜索,我找到了答案。

    总结: 我需要我的 Custom Drawable 类来实现 Drawable.Callback 和 Runnable 接口(参见下面的代码)。

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

    现在您的 Drawable 实现了这两者,您可以将其作为单独的线程“运行”,由您的活动通过启动和停止功能启动和控制。

    【讨论】:

    • angle++ 这意味着如果 UI 线程延迟,drawable 就会落后。通常最好考虑帧之间经过的时间,而不是假设总是 60 fps。
    猜你喜欢
    • 2015-09-17
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    相关资源
    最近更新 更多