Android的图形与图像处理之四 补间动画(Tween)

本文详细介绍了Android中补间动画的概念、使用方法及自定义动画的开发流程,通过实例展示了如何利用补间动画实现透明度、缩放、旋转、位移效果,并进一步探讨了自定义动画的实现,特别强调了使用Animation类和补间动画在Android应用中的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Tween与Interpolator
Android使用的Animation代表抽象的动画类,它包括如下子类:
AlphaAnimation
透明度
ScaleAnimation
缩放
TranslateAnimation
位移
RotateAnimation
旋转
为控制动画期间补入帧数量,需要借组于Interpolator
Interpolator是一个接口,有一个必须实现的方法:float getInterpolation(float input),有如下几个实现类:
LinearInterpolator
均匀速度改变
AccelerateInterpolator
逐渐加速
AccelerateDecelerateInterpolator
中间加速
CycleInterpolator
动画循环播放特定次数,变化曲线按正弦曲线改变
DecelerateInterpolator
开始的地方改变速度快,让后开始减速
定义补间动画<set.../>元素支持一个android:interpolator属性,该属性的属性值可以指定为Android默认支持的Interceptor。
@android:anim/linear_interpolator
...
在程序中通过AnimationUtils得到代表补间动画的Animation之后,接下来就调用View的startAnimation(Animation anim)方法开始对该View执行动画了

实际上一般都会采用动画资源文件来定义补间动画
示例代码:
anim.xml
<? xml version = "1.0" encoding = "utf-8" ?>
< set xmlns:android = "http://schemas.android.com/apk/res/android"
   
android:interpolator = "@android:anim/linear_interpolator"
   
>
   
< scale android:fromXScale = "1.0"
       
android:toXScale = "0.01"
       
android:fromYScale = "1.0"
       
android:toYScale = "0.01"
       
android:pivotX = "50%"
       
android:pivotY = "50%"
       
android:fillAfter = "true"
       
android:duration = "3000" />
   
< alpha android:fromAlpha = "1"
       
android:toAlpha = "0.05"
       
android:duration = "3000" />
   
< rotate android:fromDegrees = "0"
       
android:toDegrees = "1800"
       
android:pivotX = "50%"
       
android:pivotY = "50%"
       
android:duration = "3000" />
</ set >
reverse.xml
<? xml version = "1.0" encoding = "utf-8" ?>
< set android:interpolator = "@android:anim/linear_interpolator"
    
xmlns:android = "http://schemas.android.com/apk/res/android"
    
android:startOffset = "3000" >
    
< scale android:fromXScale = "0.01"
        
android:toXScale = "1"
        
android:fromYScale = "0.01"
        
android:toYScale = "1"
         android:pivotX = "50%"
        
android:pivotY = "50%"
        
android:fillAfter = "true"
        
android:duration = "3000" />
    
< alpha android:fromAlpha = "0.05"
        
android:toAlpha = "1"
        
android:duration = "3000" />
    
< rotate android:fromDegrees = "1800"
        
android:toDegrees = "0"
        
android:pivotX = "50%"
        
android:pivotY = "50%"
        
android:duration = "3000" />
</ set >
main.java
public class TweenAnim extends ActionBarActivity {

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super .onCreate(savedInstanceState);
        setContentView(R.layout.
main );
       
final ImageView flower = (ImageView) findViewById(R.id. flower );
       
final Animation anim = AnimationUtils.loadAnimation( this , R.anim. anim );
        anim.setFillAfter(
true );
       
final Animation reverse = AnimationUtils.loadAnimation( this , R.anim. reverse );
        reverse.setFillAfter(
true );
        Button bn = (Button) findViewById(R.id.
bn );
       
final Handler handler = new Handler()
        {
       
@Override
       
public void handleMessage(Message msg)
        {
       
if (msg. what == 0x123)
        {
        flower.startAnimation(reverse);
        }
        }
        };
        bn.setOnClickListener(
new OnClickListener()
        {
       
@Override
       
public void onClick(View arg0)
        {
        flower.startAnimation(anim);
       
new Timer().schedule( new TimerTask()
        {
       
@Override
       
public void run()
        {
        handler.sendEmptyMessage(0x123);
        }
        },3500);
        }
        });
    }
}
另一个示例
(蝴蝶飞行时的效果是逐帧动画;蝴蝶飞行时位置改变是补间动画)
butterfly.xml
<? xml version = "1.0" encoding = "utf-8" ?>
< animation-list xmlns:android = "http://schemas.android.com/apk/res/android"
android:oneshot = "false" >
< item android:drawable = "@drawable/butterfly_f01" android:duration = "120" />
< item android:drawable = "@drawable/butterfly_f02" android:duration = "120" />
< item android:drawable = "@drawable/butterfly_f03" android:duration = "120" />
< item android:drawable = "@drawable/butterfly_f04" android:duration = "120" />
< item android:drawable = "@drawable/butterfly_f05" android:duration = "120" />
< item android:drawable = "@drawable/butterfly_f06" android:duration = "120" />
  
</ animation-list >
main.xml
< RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
   
xmlns:tools = "http://schemas.android.com/tools"
   
android:layout_width = "match_parent"
   
android:layout_height = "match_parent"
   
android:paddingBottom = "@dimen/activity_vertical_margin"
   
android:paddingLeft = "@dimen/activity_horizontal_margin"
   
android:paddingRight = "@dimen/activity_horizontal_margin"
   
android:paddingTop = "@dimen/activity_vertical_margin"
   
tools:context = "com.example.butterfly.Butterfly" >

   
< ImageView
       
android:id = "@+id/butterfly"
       
android:layout_width = "wrap_content"
       
android:layout_height = "wrap_content"
android:background = "@anim/butterfly" />

</ RelativeLayout >
main.java
public class Butterfly extends ActionBarActivity {

private float curX = 0;
private float curY = 0;
float nextX = 0;
float nextY = 0;
   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super .onCreate(savedInstanceState);
        setContentView(R.layout.
main );
       
final ImageView imageView = (ImageView)
        findViewById(R.id.
butterfly );
       
final Handler handler = new Handler(){
       
@Override
       
public void handleMessage(Message msg)
        {
       
if (msg. what == 0x123)
        {
       
if ( nextX > 480)
        {
       
curX = nextX = 0;
        }
       
else
        {
       
nextX += 8;
        }
       
nextY = curY + ( float ) (Math.random() * 10 -5);
        TranslateAnimation anim =
new TranslateAnimation( curX , nextX , curY , nextY );
       
curX = nextX ;
       
curY = nextY ;
        anim.setDuration(200);
        imageView.startAnimation(anim);
        }
        }
        };
       
final AnimationDrawable butterfly = (AnimationDrawable)
        imageView.getBackground();
        imageView.setOnClickListener(
new OnClickListener()
        {
       
@Override
       
public void onClick(View v)
        {
        butterfly.start();
       
new Timer().schedule( new TimerTask()
        {
       
@Override
       
public void run()
        {
        handler.sendEmptyMessage(0x123);
        }
        },0,200);
        }
        });
    }
}

自定义补间动画
Android提供了Animation作为补间动画抽象基类,而且有AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation四个实现类(补间动画的四种形式:透明度改变、旋转、缩放、位移),实际项目中可能还需要一些更复杂的动画,如让图片在“三维”空间内进行旋转动画等,这就需要开发者自己开发补间动画了
自定义补间动画并不难,需要继承Animation,关键是要重写该抽象基类的 applyTransformation(float interpolatedTime, Transformation t)
interpolatedTime
代表动画的进行时间比(由0变化到1)
Transformation
代表了补间动画在不同时刻对图形或组件的变形程度
Transformation代表了对图片或试图的变形,该对象里封装了一个Matrix对象,对它所包装的Matrix进行位移、倾斜、旋转等变形;
为了控制图片或View进行三维空间的变换,还需借助于Android提供的Camera,此Camera并非摄像头,只是一个空间变换工具,作用类似于Matrix,但功能更强大
Camera提供如下常用方法
getMatrix(Matrix matrix)
将Camera所做的变换应用到指定matrix上
rotateX(float deg)
沿X轴旋转
rotateY(float deg)
沿Y轴旋转
rotateZ(float deg)
沿Z轴旋转
translate(float x, float y, float z)
把目标组件在三维空间里进行变换
applyToCanvas(Canvas canvas)
把Camera所做的变换应用到Canvas上
当Camera控制图片或View沿X、Y或Z轴旋转时,被旋转的图片或View将呈现三维透视效果
示例代码
main.xml
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
>

< ListView
       
android:id = "@+id/list"
       
android:layout_width = "wrap_content"
       
android:layout_height = "wrap_content"
       
android:entries = "@array/bookArray" />
    </LinearLayout>
MyAnimation.java
public class MyAnimation extends Animation{
private float centerX ;
private float centerY ;
private int duration ;
private Camera camera = new Camera();
public MyAnimation( float x, float y, int duration)
{
this . centerX = x;
this . centerY = y;
this . duration = duration;
}
@Override
public void initialize( int width, int height
,
int parentWidth, int parentHeight)
{
super .initialize(width,height, parentWidth, parentHeight);
setDuration(
duration );
setFillAfter(
true );
setInterpolator(
new LinearInterpolator());
}
@Override
protected void applyTransformation( float interpolatedTime, Transformation t)
{
camera .save();
camera .translate(100.0f - 100.0f*interpolatedTime
, 150.0f * interpolatedTime - 150
, 80.0f - 80.0f*interpolatedTime);
camera .rotateY(360*(interpolatedTime));
camera .rotateX((360*interpolatedTime));
Matrix matrix = t.getMatrix();
camera .getMatrix(matrix);
matrix.preTranslate(-
centerX , - centerY );
matrix.postTranslate(
centerX , centerY );
camera .restore();
}
}
main.java
public class ListViewTween extends ActionBarActivity {

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super .onCreate(savedInstanceState);
        setContentView(R.layout.
main );
        ListView list = (ListView) findViewById(R.id.
list );
        WindowManager windowManager = (WindowManager)
        getSystemService(
WINDOW_SERVICE );
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics metrice =
new DisplayMetrics();
        display.getMetrics(metrice);
        list.setAnimation(
new MyAnimation(metrice. xdpi / 2
        ,metrice.
ydpi   /2,3500 ));
       
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值