最终静态效果
最终动态效果
Flash素材来自http://sc.chinaz.com/,自己通过一些工具提取成图片。
涉及的知识点
-
帧动画(Frame Animation)
这个Demo有两个帧动画,分别是自行车跳跃和自行车骑行中(轮胎滚动状态)时的帧动画。代码如下:
自行车跳跃:
自行车轮子滚动:
保存成xml存在drawable文件夹中,之后就可以当drawable对象一样设置到imageview中了
android:oneshot
设置动画是否只运行一次
android:drawable
设置当前帧的图片
android:duration
设置当前帧的播放时长,单位ms
调用方式:
package com.hellsam.drawableanimatordemo;
import android.animation.ValueAnimator;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private ImageView mIV;
private AnimationDrawable mAnimationDrawable;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIV = (ImageView) findViewById(R.id.iv_canvas);
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
mIV.setBackgroundResource(R.drawable.riding);
mAnimationDrawable = (AnimationDrawable) mIV.getBackground();
mAnimationDrawable.start();
}
});
}
});
}
}
-
属性动画(Property Animation)
这个demo中自行车左右移动是用属性动画实现的。代码如下:
mIV.animate().translationXBy(10000).setInterpolator(new LinearInterpolator()).setDuration(20000).start();
这里的10000只是为了大于屏幕宽度,使按下按钮后(未抬起)车子能一直移动超过一个屏幕宽度。
20000是根据车子的速度和10000设置的。
这里用线性差值器(LinearInterpolator)是小车匀速运动。
下面给出其余相关代码
MainActivity:
package com.hellsam.drawableanimatordemo;
import android.animation.ValueAnimator;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity implements ValueAnimator.AnimatorUpdateListener {
private ImageView mIV;
private AnimationDrawable mAnimationDrawable;
private Button mLeftBtn;
private Button mRightBtn;
private Button mJumpBtn;
private Handler mHandler = new Handler();
//是否正在往左运动,是否正在往右运动,是否正在跳跃
private boolean isRidingLeft = false, isRidingRight = false, isJumping = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIV = (ImageView) findViewById(R.id.iv_canvas);
mLeftBtn = (Button) findViewById(R.id.btn_left);
mRightBtn = (Button) findViewById(R.id.btn_right);
mJumpBtn = (Button) findViewById(R.id.btn_jump);
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
//先加载一下帧动画资源,避免第一次加载的时候的卡顿
mIV.setBackgroundResource(R.drawable.riding);
mAnimationDrawable = (AnimationDrawable) mIV.getBackground();
mIV.setBackgroundResource(R.drawable.jump);
mAnimationDrawable = (AnimationDrawable) mIV.getBackground();
mIV.setBackgroundResource(R.mipmap.riding_0);
}
});
}
});
mJumpBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
jump();
}
});
mRightBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!isJumping) {
ride();
}
isRidingRight = true;
isRidingLeft = false;
ride2Right();
break;
case MotionEvent.ACTION_UP:
if (!isRidingLeft) {
mIV.animate().cancel();
}
if (!isJumping && !isRidingLeft) {
mAnimationDrawable.stop();
}
isRidingRight = false;
break;
}
return false;
}
});
mLeftBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!isJumping) {
ride();
}
isRidingLeft = true;
isRidingRight = false;
ride2Left();
break;
case MotionEvent.ACTION_UP:
if (!isRidingRight) {
mIV.animate().cancel();
}
if (!isJumping && !isRidingRight) {
mAnimationDrawable.stop();
}
isRidingLeft = false;
break;
}
return false;
}
});
}
/**
* 判断车子是否在运动
* @return
*/
private boolean isRiding() {
return isRidingLeft || isRidingRight;
}
/**
* 播放骑行中(车轮滚动状态)的帧动画
*/
private void ride() {
mIV.setBackgroundResource(R.drawable.riding);
mAnimationDrawable = (AnimationDrawable) mIV.getBackground();
if (mAnimationDrawable != null && !mAnimationDrawable.isRunning()) {
mAnimationDrawable.start();
}
}
/**
* 播放跳跃的帧动画
*/
private void jump() {
mIV.setBackgroundResource(R.drawable.jump);
mAnimationDrawable = (AnimationDrawable) mIV.getBackground();
if (mAnimationDrawable != null && !mAnimationDrawable.isRunning()) {
mAnimationDrawable.stop();
mAnimationDrawable.start();
isJumping = true;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mAnimationDrawable.stop();
isJumping = false;
if (isRiding()) {
ride();
}
}
}, 21 * 50);
}
}
/**
* 往右运动
*/
private void ride2Right() {
mIV.animate().cancel();
mIV.animate().translationXBy(10000).setInterpolator(new LinearInterpolator()).setDuration(20000).start();
mIV.animate().setUpdateListener(MainActivity.this);
}
/**
* 往左运动
*/
private void ride2Left() {
mIV.animate().cancel();
mIV.animate().translationXBy(-10000).setInterpolator(new LinearInterpolator()).setDuration(20000).start();
mIV.animate().setUpdateListener(MainActivity.this);
}
/**
* 当自行车出了屏幕边界后,重新从另一面驶入
* @param animation
*/
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (mIV.getTranslationX() > getWindow().getDecorView().getWidth() - 34) {
mIV.setTranslationX(-mIV.getWidth() + 70);
ride2Right();
} else if (mIV.getTranslationX() < -mIV.getWidth() + 70) {
mIV.setTranslationX(getWindow().getDecorView().getWidth() - 34);
ride2Left();
}
}
}
activity_main.xml:
全部代码下载地址:
https://github.com/hellsam/DrawableAnimationDemo
欢迎留言交流,如有描述不当或错误的地方还请留言告知