ApiDemo-AnimationSeeking

效果图
这里写图片描述
小球落下后还会弹起,而且用SeekBar可以控制小球在动画中的位置

先贴上这这个自定义view的所有代码

    public class MyAnimationView extends View implements ValueAnimator.AnimatorUpdateListener,Animator.AnimatorListener {

        private static final float BALL_SIZE = 100f;

        public final ArrayList<ShapeHolder> ballList = new ArrayList<>();

        ValueAnimator bounceAnim = null;
        ShapeHolder ball = null;


        public MyAnimationView(Context context) {
            this(context,null);
        }

        public MyAnimationView(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }

        public MyAnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            ball = addBall(200,0);
        }

        private ShapeHolder addBall(float x, float y) {
            OvalShape oval = new OvalShape();
            oval.resize(BALL_SIZE,BALL_SIZE);
            ShapeDrawable drawable = new ShapeDrawable(oval);
            ShapeHolder holder = new ShapeHolder(drawable);
            holder.setX(x);
            holder.setY(y);
            int red = (int) (100 + Math.random() * 155);
            int green = (int) (100 + Math.random() * 155);
            int blue = (int) (100 + Math.random() * 155);
            int color = 0xff000000 | red << 16 | green << 8 | blue;
            Paint paint = drawable.getPaint();
            int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
            RadialGradient gradient = new RadialGradient(37.5f,12.5f,50f,color,darkColor, Shader.TileMode.CLAMP);
            paint.setShader(gradient);
            holder.setPaint(paint);
            ballList.add(holder);
            return holder;

        }

        private void creatAnimation() {
            if (bounceAnim == null) {
                bounceAnim = ObjectAnimator.ofFloat(ball,"y",ball.getY(),getHeight() - BALL_SIZE).setDuration(1500);
                bounceAnim.setInterpolator(new BounceInterpolator());
                bounceAnim.addUpdateListener(this);
            }
        }

        public void startAnimation() {
            creatAnimation();
            bounceAnim.start();
        }

        public void seek(long seekTime) {
            creatAnimation();
            bounceAnim.setCurrentPlayTime(seekTime);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.translate(ball.getX(),ball.getY());
            ball.getShape().draw(canvas);

        }

        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            ballList.remove((((ObjectAnimator)animation).getTarget()));
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            invalidate();
            long playTime = bounceAnim.getCurrentPlayTime();
        }
    }

在代码中会使用到的javabean

/**
 * auhor: BaiLong
 * date: 2017/2/24
 * 一种数据结构,有形状和各种属性,可以用来定义
 *形状是如何绘制的
 */
public class ShapeHolder {

    private float x = 0 , y = 0;

    private ShapeDrawable shape;

    private int color;

    private RadialGradient gradient;//环形渲染

    private float alpha = 1.0f;

    private Paint paint;

    public ShapeHolder(ShapeDrawable s) {
        shape = s;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }

    public ShapeDrawable getShape() {
        return shape;
    }

    public void setShape(ShapeDrawable shape) {
        this.shape = shape;
    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
        shape.getPaint().setColor(color);
    }

    public RadialGradient getGradient() {
        return gradient;
    }

    public void setGradient(RadialGradient gradient) {
        this.gradient = gradient;
    }

    public Paint getPaint() {
        return paint;
    }

    public void setPaint(Paint paint) {
        this.paint = paint;
    }

    public float getAlpha() {
        return alpha;
    }

    public void setAlpha(float alpha) {
        this.alpha = alpha;
        shape.setAlpha((int) (alpha * 255f + 0.5f));
    }

    public float getWidth() {
        return shape.getShape().getWidth();
    }
    public void setWidth(float width) {
        Shape s = shape.getShape();
        s.resize(width, s.getHeight());
    }

    public float getHeight() {
        return shape.getShape().getHeight();
    }
    public void setHeight(float height) {
        Shape s = shape.getShape();
        s.resize(s.getWidth(), height);
    }

}

创建小球

 private ShapeHolder addBall(float x, float y) {
            OvalShape oval = new OvalShape();
            oval.resize(BALL_SIZE,BALL_SIZE);
            ShapeDrawable drawable = new ShapeDrawable(oval);
            ShapeHolder holder = new ShapeHolder(drawable);
            holder.setX(x);
            holder.setY(y);
            int red = (int) (100 + Math.random() * 155);
            int green = (int) (100 + Math.random() * 155);
            int blue = (int) (100 + Math.random() * 155);
            int color = 0xff000000 | red << 16 | green << 8 | blue;
            Paint paint = drawable.getPaint();
            int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
            RadialGradient gradient = new RadialGradient(37.5f,12.5f,50f,color,darkColor, Shader.TileMode.CLAMP);
            paint.setShader(gradient);
            holder.setPaint(paint);
            ballList.add(holder);
            return holder;

        }

在画图的时候用的是ShapeDrawable.draw(canvas)来画这个球,画笔就保存在ShapeDrawable中,而在Paint中又调用了一个方法paint.setShader(),这个方法的参数是RadialGradient ,主要就是用RadialGradient来实现渐变色,对于RadialGradient的用法还不会的,请大家自行百度,有大把的文章等待着你.

onDraw


        @Override
        protected void onDraw(Canvas canvas) {
            canvas.translate(ball.getX(),ball.getY());
            ball.getShape().draw(canvas);

        }

onDraw中的内容很简单,就是移动画布的位置,具体移动到那,在ShapeHolder中有保存,然后利用ShapeDrawable.draw(canvas)来绘制.

创建动画

        private void creatAnimation() {
            if (bounceAnim == null) {
                bounceAnim = ObjectAnimator.ofFloat(ball,"y",ball.getY(),getHeight() - BALL_SIZE).setDuration(1500);
                bounceAnim.setInterpolator(new BounceInterpolator());
                bounceAnim.addUpdateListener(this);
            }
        }

只是创建了一个简单的ObjectAnimator,第一个参数是Target,第二个参数是动画的类型,后面的参数就是具体怎么运动,而能实现小球落地之后还能弹起的效果,用的就是Interpolator,只用一句代码就可以实现bounceAnim.setInterpolator(new BounceInterpolator()),

Interpolator

AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速

AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速

AnticipateInterpolator 开始的时候向后然后向前甩

AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值

BounceInterpolator 动画结束的时候弹起

CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线

DecelerateInterpolator 在动画开始的地方快然后慢

LinearInterpolator 以常量速率改变

OvershootInterpolator 向前甩一定值后再回到原来位置

seek

public void seek(long seekTime) {
            creatAnimation();
            bounceAnim.setCurrentPlayTime(seekTime);
        }

能用SeekBar来控制小球处于动画中的什么位置,就是用这个方法实现的.具体的用法就很简单了.

最后再贴上上面效果图的代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   android:orientation="vertical"
    tools:context="com.sdzn.fuzhuxian.apidemo.animation.AnimationSeeking">
    <Button
        android:id="@+id/btn_run"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="run"
        />
    <SeekBar
        android:id="@+id/sb_seek"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"

        />
</LinearLayout>
private static final int DURATION = 1500;
    private SeekBar seekBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animation_seeking);

        LinearLayout container = (LinearLayout) findViewById(R.id.container);
        final MyAnimationView animView = new MyAnimationView(this);
        container.addView(animView);

        findViewById(R.id.btn_run).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animView.startAnimation();
            }
        });

        SeekBar sb = (SeekBar) findViewById(R.id.sb_seek);
        sb.setMax(DURATION);
        sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (animView.getHeight() != 0) {
                    animView.seek(progress);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

具体的做法就是把SeekBar.setMax(duration);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值