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

名称类型子类标签效果
平移动画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以下有兼容问题

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值