赞
踩
这个比较简单,作为一个单一动画的例子
多个动画叠加,作为一个进阶的例子
安卓动画分为三类:
这里我将用 View Animation作为例子来讲解如何实现
视图动画的作用对象是View,支持四种动画效果,分别是平移动画,缩放动画,旋转动画,透明度动画。譬如,我们可以对安卓组件设置其的移动,旋转,缩放,透明。
动画 | 调用 |
---|---|
平移动画 | translation |
缩放动画 | scale |
旋转 | rotate |
透明度动画 | Alpha |
每一个动画都可以由两种方式进行设置
首先在res文件夹下建立anim文件夹
然后在其中加入xml文件来编写动画文本
xml代码:
其中包括了4种动画的定义,这里大家可以任意选择使用某几种动画,并且设置其中的参数来达到自己想要的效果
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="0" android:toXDelta="20" android:fromYDelta="0" android:toYDelta="20" android:duration="4000"/> <scale android:fromXScale="1.0" android:toXScale="0.2" android:fromYScale="1.0" android:toYScale="0.2" android:pivotX="50%" android:pivotY="50%" android:duration="4000"/> <rotate android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%" android:duration="4000"/> <alpha android:fromAlpha="1.0" android:toAlpha="0.2" android:duration="4000"/> </set>
xml文件编写完毕之后,需要在java代码中调用一下才能使动画运行
Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.test);
raceCar.startAnimation(animation);
这里为了让大家看看清楚最基本的一个动画如何建立,我就直接截了Android studio上的图,这样可以方便大家能看清楚每一个参数是干什么的(其实自己打代码的话也是能看到的)
可以选择设置一个持续时间,调用.setDuration(long time)方法
然后调用.start()即可
相对来说JAVA代码设置会简单一些
这里再提供一个类的方法:
我这里用的是ObjectAnimator,因为这个进行动画集合的AnimatorSet比较好用,并且可以无限套娃
AnimatorSet()不仅可以使用playTogether()(同时播放动画),还可以让动画顺序播放,调用playSequentially():
同样的,还可以设置延时播放(不过这样不太好用,我用另外一种实现方式做出来了)
下面的第一个语句就是backX这个动画在backY之后1000毫秒后播放
backAnimatorSet.play(backX).after(backY).after(1000);
backAnimatorSet.play(backX).before(backY);
backAnimatorSet.play(backX).with(backY);
这里我要做在博文开始提到的3个动画
首先,让赛车的转向圆与赛道完美切合,我们可以先话一个圆,然后在圆上画赛道
这样子圆运动就比较好规划了,让赛车的起点在赛道左下角,然后圆心定在图片右下角,转90度即可
如果大家不知道如何确定圆心位置,Android Studio上有一个叫做GuidLine的东西,可以用来找到位置
然后就可以编写一个完美过弯的代码了
这里重点在于new RotateAnimation()里面的几个参数,前两个为从0°顺时针旋转到90°,后面两个为圆心的X,Y坐标,这里坐标是以动画主体(我的是一个图片)的左上角为原点的。
//编写动画
final Animation perfectTurning = new RotateAnimation(0,90,1100,488-432);
perfectTurning.setDuration(2000);
//编写按钮触发该动画
perfectBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
backAnimatorSet.start();
yuanli.setVisibility(View.INVISIBLE);
raceCar.startAnimation(perfectTurning);
desc.setText("正确的入弯时机\n正确的外内外走线\n正确的出弯时机");
}
});
这个跟上面的大同小异,只是不再是完美走线,而是一个半径更大的圆,所以我更改了pivotX的数值,其他保持不变,就完成了这个动画
为了更加清楚的解释赛车的动态,我还加了一个轮胎来解释这个动画
final Animation notEnough = new RotateAnimation(0,75,1600,488-432); notEnough.setDuration(1500); notEnoughBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { backAnimatorSet.start(); clickTime++; if (clickTime % 2 == 1) { raceCar.setVisibility(View.VISIBLE); yuanli.setVisibility(View.VISIBLE); raceCar.startAnimation(notEnough); desc.setText("车速过快,\n导致前轮胎摩擦力无法提供向心力\n而出现推头现象"); } if (clickTime % 2 == 0) { raceCar.setVisibility(View.INVISIBLE); yuanli.setVisibility(View.VISIBLE); tier.setVisibility(View.VISIBLE); tier.startAnimation(notEnough); tier.setVisibility(View.INVISIBLE); desc.setText("车速过快,\n导致前轮胎摩擦力无法提供向心力\n而出现推头现象"); } } });
这里写的每一个单一动画我都用了另外一个实现方式(ObjectAnimator)
这个相对来讲比较复杂,我的想的场景是这样的,赛车转向动作开始晚了一些(这里需要一个向前的动画),然后突然进行转弯(叠加一个向右的动画,此时的向前动画是还没停止的)。这里转弯不能只有平移,还要有旋转才能让这个转向更加逼真。由于这里是一个转向过度造成甩尾的情景,所以在平移结束后我的旋转动画实际上还没有结束(这里延时多设置了100毫秒)
首先先把上述几个动画写好:
goStraight = ObjectAnimator.ofFloat(raceCar,"translationY",-980);
goStraight.setDuration(1600);
turningX = ObjectAnimator.ofFloat(raceCar,"translationX",500);
turningX.setDuration(1200);
turningStep2 = ObjectAnimator.ofFloat(raceCar,"rotation",0,175);
turningStep2.setDuration(1300);
由于这种动画方式不会自动恢复动画物体位置,我自己只好手写了一个恢复位置动画(其实是一个持续时间为0的动画,也就是一瞬间完成),正好也用到了AnimationSet这个东西:
final ObjectAnimator backX = ObjectAnimator.ofFloat(raceCar,"translationX",0);
final ObjectAnimator backY = ObjectAnimator.ofFloat(raceCar,"translationY",0);
final ObjectAnimator backRotate = ObjectAnimator.ofFloat(raceCar,"rotation",0,0);
backAnimatorSet = new AnimatorSet();
backAnimatorSet.playTogether(backX,backY,backRotate);
backAnimatorSet.setDuration(0);
这几个动画执行的顺序是这样的:
本来可以使用上面讲到的after来执行,但是我觉得是在不太好控制
我这里又建了一个专门用来计时的线程,还有一个相应的Handler。
到了某个时间我就发message给Handler,然后在Handler中执行动画即可。
class MyTimer extends Thread{ @Override public void run() { time=0; while(true) { time+=10; try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { } if (time == 10 ){ Message message = handler.obtainMessage(); message.what=3; handler.sendMessage(message); } if (time == 700){ Message message = handler.obtainMessage(); message.what=1; handler.sendMessage(message); } if (time >=2000){ break; } } } }
上面的time是以毫秒为单位,每10ms过去time就更新一次
(严格山来说不是严格的10ms,因为执行这些其他的语句还要时间)
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (msg.what == 1){
turningX.start();
turningStep2.start();
}
else if (msg.what==3){
goStraight.start();
}
}
};
然后就是动画的执行了,我在一开始就执行了前进,然后在一定时间之后同时开始了转向动画的平移和旋转动画。由于前面设置的持续时间不一样,视觉上看起来就是车辆不再平移后还旋转了一小段。
最后开启一下Thread即可
tooMuchBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
backAnimatorSet.start();
time = 0;
MyTimer timer = new MyTimer();
timer.start();
yuanli.setVisibility(View.INVISIBLE);
desc.setText("入弯过晚->转向过快\n导致后轮胎摩擦力无法提供向心力\n从而出现甩尾现象");
}
});
工程文件:
AndroidAnimation
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。