您的位置:首页 > 移动开发 > Android开发

android 艺术开发探索之动画(animation)

2016-08-17 15:37 405 查看
名称类型子类标签效果
平移动画view动画TranslateAnimation< translate >移动view
缩放动画view动画ScaleAnimation< scale >放大或缩小view
旋转动画view动画RotateAnimation< RotateAnimation>旋转view
透明度动画view动画AlphaAnimation< AlphaAnimation>改变view的透明度
帧动画view动画AnimationDrawable< animation-list >顺序播放一组预先定义好的的图片
layoutAnimation动画view动画AnimationDrawable< layoutAnimation>作用于viewgroup,子元素出厂时都具有此效果
属性动画属性动画
<?xml version="1.0" encoding="utf-8"?>
<!-- set对应得是动画集合,对应类是AnimationSet,-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1"
android:fillAfter="true"
android:shareInterpolator="true">
<!-- 表示集合中的动画是否和集合共享一个插值器,duration是指持续时间,fillAfter动画结束后view是否停留在结束位置-->
<!-- 表示透明度动画-->
<alpha
android:fromAlpha="1"
android:toAlpha="0"></alpha>
<!-- 表示缩放动画,默认缩放轴点为view中心,左右方向同时缩放,若设右边界,view只会向左边进行缩放-->
<scale
android:fromXScale="1"
android:toXScale="0"
android:fromYScale="1"
android:toYScale="0"
android:pivotY="1"
android:pivotX="1"
>
</scale>
<!-- 表示在水平和垂直方法平移动画-->
<translate
android:fromXDelta="1"
android:fromYDelta="1"
android:toXDelta="0"
android:toYDelta="0">
</translate>
<!-- 表示旋转动画,默认view的中心为旋转轴-->
<rotate
android:fromDegrees="10"
android:pivotX="1"
android:pivotY="1"
android:toDegrees="30">

</rotate>
</set>


加载动画

Animation animation= AnimationUtils.loadAnimation(this,R.anim.demo);
m.startAnimation(animation);


帧动画xml,帧动画的xml要写的drawable下面,animation-list才能识别

<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true"
>
<item android:drawable="@drawable/icon1" android:duration="150"></item>
<item android:drawable="@drawable/icon2" android:duration="150"></item>
<item android:drawable="@drawable/icon3" android:duration="150"></item>
<item android:drawable="@drawable/icon4" android:duration="150"></item>
<item android:drawable="@drawable/icon5" android:duration="150"></item>
<item android:drawable="@drawable/icon6" android:duration="150"></item>
</animation-list>


m.setBackgroundResource(R.drawable.demo1);
AnimationDrawable drawable=(AnimationDrawable)m.getBackground();
drawable.start();


LayoutAnimation作用于Viewgroup,当其子元素出场时也具有这种效果,一般用于listview这种带列表的控件。

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/demo1">
<!--假如demo1动画周期为1000ms,那么0.5表示每个item出场都需延时500ms,
第一个是500ms,第二个就是1000ms,animationOrder为子元素的动画顺序,比如随机出场和逆向出场,
对于listview,只需给其加上android:layoutAnimation这个属性就好-->
</layoutAnimation>


Activity的切换效果主要方法:

//此方法只能在startactivity和finish()之后被调用才有效。
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);


Fragment切换效果主要方法:

//这里动画必须是View动画
FragmentTransaction transaction= getChildFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.enter_anim,R.anim.exit_anim);


属性动画ObjectAnimator , ValueAnimator, AnimatorSet

属性动画是API11加入的属性,可对任何对象做动画,动画默认的时间间隔是300ms,默认帧率10ms/帧,达到的效果是在一个时间间隔内

完成对象从一个属性值到另一个属性值的改变。兼容库nineoldandroids,网址:http://nineoldandroid.com,属性动画要求对象

的该属性有get/set方法

ObjectAnimator例子,它是ValueAnimator的子类

ObjectAnimator.ofFloat(myObject,"translationY",-myObject.getHeight).start();


ValueAnimator例子

ValueAnimator colorAnimator=ObjectAnimator.ofInt
(this,"backgroundColor",/*RED*/0XFFFF8080,/*RED*/0XFF8080FF);
colorAnimator.setDuration(3000);
colorAnimator.setEvaluator(new ArgbEvaluator());
colorAnimator.setRepeatCount(ValueAnimator.INFINITE);
colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
colorAnimator.start();


####AnimatorSet例子

AnimatorSet set=new AnimatorSet();
set.playTogether(
ObjectAnimator.ofInt(myView,"rotationX",0,360),
ObjectAnimator.ofInt(myView,"rotationY",0,180)
);
set.setDuration(5*1000).start();


属性动画通过XML定义,需要定义在res/animator目录下

<set
android:ordering="sequentially"
xmlns:android="http://schemas.android.com/apk/res/android"><!-- 播放方式,按顺序还是一起播放-->
<objectAnimator>

</objectAnimator>
<animator>

</animator><!--ValueAnimator-->
</set><!--AnimatorSet-->


插值器和估值器

自定义插值器需要实现Interpolator或者TimeInterpolator,自定义估值算法需要实现TypeEvaluator.另外如果要对其他类型(非

int、float、Color)做动画,那么必须要自定义类型估值算法,可参考http://www.weidu8.net/wx/140849

属性动画的监听器

ValueAnimator.AnimatorUpdateListener

public void onAnimationUpdate(ValueAnimator animation);

监听动画的整个过程,每播放一帧就会被调用一次

Animator.AnimatorListener

public void onAnimationStart(Animator animation) ;
public void onAnimationEnd(Animator animation);
public void onAnimationCancel(Animator animation);
public void onAnimationRepeat(Animator animation);


属性动画的要求

1、object必须提供setXX/getXX属性的方法,当没有初始值的时候需要调get方法获取,否则程序cash。

2、object提供的setXX所做的改变必须能够通过某种方法反应出来,否则动画无效果。

想要满足上面两条件的话,有3种方法,如下:

1,给你的对象加上get和set方法,如果你有权限的话

2,用一个类来包装原始对象,间接为其提供get和set方法

3,采用ValueAnimator,监听动画的过程,自己实现属性的改变

如下:

package site.zhangyun.appliction;
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import com.efrobot.library.RobotManager;
import com.efrobot.library.RobotState;
import com.efrobot.library.task.ControlManager;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

Button mBtLight, mBtLightPutout;
RobotManager mRobotManager;
ObjectAnimator mObjectAnimator;
ValueAnimator valueAnimator;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InitViews();
}
void InitViews() {
mBtLight = (Button) findViewById(R.id.lightchange);
mBtLight.setOnClickListener(this);
mBtLightPutout = (Button) findViewById(R.id.light_putout);
mBtLightPutout.setOnClickListener(this);
mRobotManager = RobotManager.getInstance(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.lightchange:
//坑一:android系统里面吧动画设置给关闭了导致播放不了动画,找了一下午的bug,555....
//实现呼吸灯的效果
mObjectAnimator = ObjectAnimator.ofInt(new myTest(mRobotManager, this), "lightBeltBrightness", 0, 255);
mObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int currentValue = (Integer) animation.getAnimatedValue();
Log.d("当前灯带亮度", currentValue + "");
}
});
mObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);//死循环
mObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);//先从熄灭到亮,再从亮到熄灭
mObjectAnimator.setInterpolator(new LinearInterpolator());//线性变换一次递增
mObjectAnimator.setDuration(1000 * 10);//动画执行时间为10秒
mObjectAnimator.start();
//ValueAnimator实现允许变化从0到255
performAnimator(ControlManager.getInstance(mRobotManager), 0, 255);
break;
case R.id.light_putout:
ControlManager.getInstance(mRobotManager).setLightBeltBrightness(0);
if (mObjectAnimator != null) {
mObjectAnimator.cancel();
}
break;
}
}
void performAnimator(final ControlManager controlManager, final int start, final int end) {
valueAnimator = ValueAnimator.ofInt(0, 255);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private IntEvaluator mEvaluator = new IntEvaluator();//整形估值器,匀速
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//获取当前动画的进度值
int currentValue = (Integer) animation.getAnimatedValue();
//获取当前的进度占整个动画过程的比例
float fraction = animation.getAnimatedFraction();
//设置灯带的亮度
controlManager.setLightBeltBrightness(mEvaluator.evaluate(fraction, start, end));
//呼吸灯是抛物线,0-255-0,自己算吧y=(-51/5)*t2+102t
}
});
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.setDuration(1000 * 10).start();
}
//ControlManager里面只有set木有get于是乎就得自己实现啦
class myTest extends ControlManager {
ControlManager mControlManager;
RobotState mRobotState;

myTest(RobotManager robotManager, Context context) {
super(robotManager);
mControlManager = ControlManager.getInstance(mRobotManager);
mRobotState = RobotState.getInstance(context);
}

public int getLightBeltBrightness() {
return mRobotState.getLightBeltBrightness();
}

public void setLightBeltBrightness(int lightBeltBrightness) {
mControlManager.setLightBeltBrightness(lightBeltBrightness);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//这里要是不调用的话,就会内存泄漏
//当动画为无限循环动画的时候,动画持有view,view持有activity,那么activity无法释放,内存泄漏
if (mObjectAnimator != null) {
mObjectAnimator.cancel();
}
if (valueAnimator != null) {
valueAnimator.cancel();
}
}
}


使用动画的注意事项

1、当图片的数量过多较大时极易容易出现OOM,开发中应尽量避免。

2、无限循环属性动画容易造成内存泄漏,需要在activity退出时及时停止,view动画不存在此问题。

3、view动画是对view的影像做动画,并不是真的改变状态,有时出现动画完成后view无法隐藏问题,可以先调用view.clearAnimation()。

4、进行动画时尽可能使用dp,px会导致在不同设备有不同效果

5、从3.0开始,属性动画的单击事件触发位置为移动后的位置,但view动画任然在原位置。

6,开启硬件加速可以提高动画流畅性

7,动画在3.0以下有兼容问题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android