在 Android 中动画旋转图像
Animate rotation of an image in Android
我有一个齿轮图像,我想围绕一个固定点连续旋转。
早些时候,我通过将图像作为 ImageView 包含在我的 Android class 中并对其应用 RotateAnimation 来完成此操作。
@InjectView(R.id.gear00) ImageView gear00;
RotateAnimation ra07 = new RotateAnimation(0, 359, 129, 186);
ra07.setDuration(10000);
ra07.setRepeatCount(RotateAnimation.INFINITE);
ra07.setInterpolator(new LinearInterpolator());
gear00.setAnimation(ra07);
基本上,我将 ImageView 注入 class 并应用旋转动画。
但是,我再也没有使用 ImageView 的奢侈了。我必须使用 Bitmap 并在 canvas 上旋转它。
我怎样才能完成我之前在 onDraw() 方法中所做的事情,位图在 canvas 上连续围绕一个固定点旋转?
编辑1:
我尝试了下面提到的其中一个建议我的代码看起来有点像下面的
在 onCreate() 中:
Matrix matrix = new Matrix();
matrix.setRotate(10, 100, 200);
然后在onDraw()中(其中gear00Scaled是要在canvas上旋转的位图):
canvas.drawBitmap(gear00Scaled, matrix, new Paint());
我尝试的另一种方法涉及保存 canvas、旋转它,然后恢复它:
canvas.save();
canvas.rotate(10);
canvas.drawBitmap(gear00Scaled, 100, 200, null);
canvas.restore();
虽然两者似乎都不起作用!
创建一个XML class(假设:rotate.xml)并将其放置在res/anim文件夹中,然后在其中写入以下代码:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:toDegrees="360" />
然后在 java class 中,在 OnCreate
中执行以下操作:
final Animation a = AnimationUtils.loadAnimation(CustomActivity.this,
R.anim.rotate);
a.setDuration(3000);
gear00.startAnimation(a);
或
要使用位图来完成,希望以下代码序列对您有所帮助:
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());
如果你检查以下方法来自:
~frameworks\base\graphics\java\android\graphics\Bitmap.java
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter)
这将解释旋转和平移的作用。
我想在我的应用程序中旋转自定义图像作为进度对话框。您可以使用下面的代码来旋转图像:
RotateAnimation anim = new RotateAnimation(0.0f, 360.0f ,
Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(1000);
imageView.setAnimation(anim);
imageView.startAnimation(anim);
代码前两件事:
- 你根本就不会用imageview?因为你可以 link 它到 canvas 并使用位图,但它仍然是一个图像视图。
- 我认为您遇到的主要问题是另一个答案没有对其进行动画处理,并且您错过了对视图 invalidate() 并将其重新绘制为旋转的调用。
所以有两种方法:
第一个是图像视图,我个人认为它更容易、更好。下面是我的 activity class 中的一个方法,mLittleChef 是一个 ImageView。
public void doCanvas(){
//Create our resources
Bitmap bitmap = Bitmap.createBitmap(mLittleChef.getWidth(), mLittleChef.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
final Bitmap chefBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.dish_special);
//Link the canvas to our ImageView
mLittleChef.setImageBitmap(bitmap);
ValueAnimator animation= ValueAnimator.ofFloat(0, 359, 129, 186);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
//Clear the canvas
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.save();
canvas.rotate(value, canvas.getWidth()/2, canvas.getHeight()/2);
canvas.drawBitmap(chefBitmap, 0, 0, null);
canvas.restore();
mLittleChef.invalidate();
}
});
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(1000);
animation.start();
}
另一种方法是使用自定义 canvas class。我为 ExampleDrawView mLittleChefDraw 创建了自己的自定义视图 class,而不是 ImageView;在我的布局中。你可能需要稍微修改一下这个来得到你正在寻找的旋转方面的东西,我只是用 canvas 的中间作为轴心点做了一个 360 度的旋转。
public class ExampleDrawView extends View {
Bitmap bitmap;
Float mRotate= 0f;
Handler h;
//State variables
final int STATE_PAUSE = 2;
final int STATE_ROTATE = 3;
int STATE_CURRENT;
public ExampleDrawView(Context context, AttributeSet attrs) {
super(context, attrs);
h = new Handler();
bitmap= BitmapFactory.decodeResource(getResources(), R.drawable.dish_special);
STATE_CURRENT= STATE_PAUSE;
}
Runnable move = new Runnable() {
@Override
public void run() {
switch (STATE_CURRENT){
case STATE_ROTATE:
if (mRotate<360){
mRotate++;
invalidate();
}else{
STATE_CURRENT= STATE_PAUSE;
}
h.postDelayed(move, 20);
break;
}
}
};
public void startDrawing(){
if(STATE_CURRENT == STATE_PAUSE){
STATE_CURRENT= STATE_ROTATE;
mRotate=(float) 0;
h.postDelayed(move, 20);
}
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
//change your rotate point here, i just made it the middle of the canvas
canvas.rotate(mRotate,getWidth()/2,getHeight()/2);
canvas.drawBitmap(bitmap, 0, 0, null);
}
}
然后返回 activity 调用它来启动它:
public void doCanvasCustomView(){
mLittleChefDraw.startDrawing();
}
在你的 onCreate() 中做
Matrix matrix = new Matrix();
并且在onDraw
float angle = (float) (System.currentTimeMillis() % ROTATE_TIME_MILLIS)
/ ROTATE_TIME_MILLIS * 360;
matrix.reset();
matrix.postTranslate(-source.getWidth() / 2, -source.getHeight() / 2);
matrix.postRotate(angle);
matrix.postTranslate(centerX, centerY)
canvas.drawBitmap(source, matrix, null);
invalidate(); // Cause a re-draw
ROTATE_TIME_MILLIS是整圈时间,例如2000 是 2 秒。
我有一个齿轮图像,我想围绕一个固定点连续旋转。
早些时候,我通过将图像作为 ImageView 包含在我的 Android class 中并对其应用 RotateAnimation 来完成此操作。
@InjectView(R.id.gear00) ImageView gear00; RotateAnimation ra07 = new RotateAnimation(0, 359, 129, 186); ra07.setDuration(10000); ra07.setRepeatCount(RotateAnimation.INFINITE); ra07.setInterpolator(new LinearInterpolator()); gear00.setAnimation(ra07);
基本上,我将 ImageView 注入 class 并应用旋转动画。
但是,我再也没有使用 ImageView 的奢侈了。我必须使用 Bitmap 并在 canvas 上旋转它。
我怎样才能完成我之前在 onDraw() 方法中所做的事情,位图在 canvas 上连续围绕一个固定点旋转?
编辑1:
我尝试了下面提到的其中一个建议我的代码看起来有点像下面的
在 onCreate() 中:
Matrix matrix = new Matrix();
matrix.setRotate(10, 100, 200);
然后在onDraw()中(其中gear00Scaled是要在canvas上旋转的位图):
canvas.drawBitmap(gear00Scaled, matrix, new Paint());
我尝试的另一种方法涉及保存 canvas、旋转它,然后恢复它:
canvas.save();
canvas.rotate(10);
canvas.drawBitmap(gear00Scaled, 100, 200, null);
canvas.restore();
虽然两者似乎都不起作用!
创建一个XML class(假设:rotate.xml)并将其放置在res/anim文件夹中,然后在其中写入以下代码:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:toDegrees="360" />
然后在 java class 中,在 OnCreate
中执行以下操作:
final Animation a = AnimationUtils.loadAnimation(CustomActivity.this,
R.anim.rotate);
a.setDuration(3000);
gear00.startAnimation(a);
或
要使用位图来完成,希望以下代码序列对您有所帮助:
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());
如果你检查以下方法来自:
~frameworks\base\graphics\java\android\graphics\Bitmap.java
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter)
这将解释旋转和平移的作用。
我想在我的应用程序中旋转自定义图像作为进度对话框。您可以使用下面的代码来旋转图像:
RotateAnimation anim = new RotateAnimation(0.0f, 360.0f ,
Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(1000);
imageView.setAnimation(anim);
imageView.startAnimation(anim);
代码前两件事:
- 你根本就不会用imageview?因为你可以 link 它到 canvas 并使用位图,但它仍然是一个图像视图。
- 我认为您遇到的主要问题是另一个答案没有对其进行动画处理,并且您错过了对视图 invalidate() 并将其重新绘制为旋转的调用。
所以有两种方法: 第一个是图像视图,我个人认为它更容易、更好。下面是我的 activity class 中的一个方法,mLittleChef 是一个 ImageView。
public void doCanvas(){
//Create our resources
Bitmap bitmap = Bitmap.createBitmap(mLittleChef.getWidth(), mLittleChef.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
final Bitmap chefBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.dish_special);
//Link the canvas to our ImageView
mLittleChef.setImageBitmap(bitmap);
ValueAnimator animation= ValueAnimator.ofFloat(0, 359, 129, 186);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
//Clear the canvas
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.save();
canvas.rotate(value, canvas.getWidth()/2, canvas.getHeight()/2);
canvas.drawBitmap(chefBitmap, 0, 0, null);
canvas.restore();
mLittleChef.invalidate();
}
});
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(1000);
animation.start();
}
另一种方法是使用自定义 canvas class。我为 ExampleDrawView mLittleChefDraw 创建了自己的自定义视图 class,而不是 ImageView;在我的布局中。你可能需要稍微修改一下这个来得到你正在寻找的旋转方面的东西,我只是用 canvas 的中间作为轴心点做了一个 360 度的旋转。
public class ExampleDrawView extends View {
Bitmap bitmap;
Float mRotate= 0f;
Handler h;
//State variables
final int STATE_PAUSE = 2;
final int STATE_ROTATE = 3;
int STATE_CURRENT;
public ExampleDrawView(Context context, AttributeSet attrs) {
super(context, attrs);
h = new Handler();
bitmap= BitmapFactory.decodeResource(getResources(), R.drawable.dish_special);
STATE_CURRENT= STATE_PAUSE;
}
Runnable move = new Runnable() {
@Override
public void run() {
switch (STATE_CURRENT){
case STATE_ROTATE:
if (mRotate<360){
mRotate++;
invalidate();
}else{
STATE_CURRENT= STATE_PAUSE;
}
h.postDelayed(move, 20);
break;
}
}
};
public void startDrawing(){
if(STATE_CURRENT == STATE_PAUSE){
STATE_CURRENT= STATE_ROTATE;
mRotate=(float) 0;
h.postDelayed(move, 20);
}
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
//change your rotate point here, i just made it the middle of the canvas
canvas.rotate(mRotate,getWidth()/2,getHeight()/2);
canvas.drawBitmap(bitmap, 0, 0, null);
}
}
然后返回 activity 调用它来启动它:
public void doCanvasCustomView(){
mLittleChefDraw.startDrawing();
}
在你的 onCreate() 中做
Matrix matrix = new Matrix();
并且在onDraw
float angle = (float) (System.currentTimeMillis() % ROTATE_TIME_MILLIS)
/ ROTATE_TIME_MILLIS * 360;
matrix.reset();
matrix.postTranslate(-source.getWidth() / 2, -source.getHeight() / 2);
matrix.postRotate(angle);
matrix.postTranslate(centerX, centerY)
canvas.drawBitmap(source, matrix, null);
invalidate(); // Cause a re-draw
ROTATE_TIME_MILLIS是整圈时间,例如2000 是 2 秒。