Android群英传学习笔记——动画机制

1.Android View 动画框架

      Animation框架定义了透明度、旋转、缩放和位移几种常见的动画,而且控制的是整个View,实现原理是每次绘制试图时View所在的ViewGroup中的drawChild函数获取该View的Animation 的 Transformation值,然后调用canvas.concat(transformToApply.getMatrix());通过矩阵运算完成动画帧。如果动画没完成,就继续调用invalidate()函数,启动下次绘制来驱动动画,从而完成整个动画的绘制。以下是几个简单的视图动画使用

2.Android属性动画分析

     ObjectAnimator使用可以用下面这个例子

ObjectAnimator animator = ObjectAnimator.ofFloat(
   view,
   “translationX",
   300);
animator.setDuration(300);
animator.start();    
 
  

    通过ObjectAnimator的静态工厂方法,创建一个ObjectAnimator对象。第一个参数为需要操纵的View,第二个参数为需要操纵的属性,最后一个参数是设置变化的参数

    常用的属性动画值有                                           

  • translationX和translationY:这两个属性作为一种增量来控制着View对象从它布局容器的左上角坐标偏移的位置
  • rotation、rotationX和rotationY:这三个属性控制View对象围绕支点进行2D和3D旋转
  • scaleX 和 scaleY: 这个两个属性控制着View对象围绕它的支点进行2D缩放
  • pivotX 和 pivotY:这两个属性控制着View对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,该支点的位置就是View对象的中心点
  • x 和 y: 这两个属性是View对象在它的容器中的最终位置,是由最初的左上角坐标和translationX、translationY值得累计和
  • alpha:表示View对象的透明度,1为不透明,0代表完全透明 

    如果我们想要实现多种动画方法,我们可以先使用PropertyValuesHolder来创建多个实例,再使用ObjectAnimator.ofPropertyValuesHolder()给相应的View装载动画。我们也可以使用AnimatorSet的playTogether方法来实现多个动画。另外我们可以用ValueAnimator来达到调用者控制动画的实现过程。

     关于动画事件的监听。我们可以使用AnimatorListener(),但当我们只需要对部分事件进行监听就只用需要AnimatorListenerAdapter()来实现个别需要监听的时间.最后属性动画也可以向View一样写在XML文件中。

3.Android布局动画

    所谓布局动画是指作用在ViewGroup上,给ViewGroup增加View时添加添加一个动画过度效果。最简单的就是在XML文件中使用android:animateLayoutChanges="true"来打开,当然我们也可以用LayoutAnimationController类来自定义一个子View的过渡效果

4.插值器

    插值器可以定义动画变换速率。就如同跑步的速度,只要这个速度在规定时间时到达终点,那么就是可行的,插值器就是控制这个跑步速度的加速度,虽然中间的速度不一样,但会保证最后一定会在规定时间内到达终点

5.自定义动画

    创建自定义动画只需要使用applyTransformation(float time,Transformation t)第一个参数为插值器的时间因子,取值范围0-1,第二个参数就是矩阵的封装类,也可以称他为要变换的效果。至于用Canera类实现动画,就是设置三个坐标轴的旋转角度,并且使用preTranslate()方法可以改变旋转时的默认旋转中心

6.Android 5.X SVG矢量动画机制

    SVG矢量图比起Bitmap的优点是放大不是真,不需要为不同分辨率设计多套图标

    使用标签创建SVG,就像用指令的方式来控制一只画笔,因此标签所支持的指令有以下几种

  • M = moveto(M X,Y) :将画笔移动到指定的坐标位置,但未发生绘制
  • L = lineto(L X,Y) : 画直线到指定的坐标位置
  • H = horizontal lineto(H x): 画水平线到指定的X坐标位置
  • V = vertical lineto(V Y): 画垂直线到指定的Y坐标位置
  • A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y): 弧线
  • Z = closepath(): 关闭路径

     使用指令时,需要注意坐标轴以(0,0)位中心,X轴水平向右,Y轴水平向下。指令大小写均可,大写绝对定位,小写相对定位。指令和数据间的空格可以省略,同一指令出现多次可以只用一个 .

直接使用一个太阳-地球-月亮的简易模型来阐述我们该如何使用SVG矢量动画机制,首先我们需要创建一个静态的SVG图形,即静态的VectorDrawable



    
        
        
            
            
                
            
        
    
	
这个VectorDrawble分别代表了太阳系系统和地月系统,并且使用pivotX和pivotY方法来指定他们绕着哪个转,接着是动画实现,这里就给出太阳的动画实现,
——————————————————————————————————————————————————————————————————————————
最后我们还要使用AnimatedVectorDrawable来粘合SVG静态图形和动画


    
    
 
 
  
 
  

    我们只需使用android:src来使用相应的AnimatedVectorDrawable来进行显示即可

7.Android 动画特效

     现在要实现一个下拉展开动画,我们需要隐藏的View的高度不断发生变化,所以我们需要使用ValueAnimator来模拟这个过程,布局就是一个显示的Text,一个隐藏Text,故略,主要程序如下

package com.example.linzhengle.anima;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private LinearLayout mHiddenView;
    private float mDensity;
    private int mHiddenViewMeasuredHeight;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHiddenView = (LinearLayout) findViewById(R.id.hide_view);
        //获取像素密度
        mDensity = getResources().getDisplayMetrics().density;
        //获取布局的高度
        mHiddenViewMeasuredHeight = (int)(mDensity * 40 + 0.5);
    }
    public void llClick(View view){
        if (mHiddenView.getVisibility() == View.GONE)
            animateOpen(mHiddenView);
        else
            animateClose(mHiddenView);

    }

    public void animateOpen(final View view){
        view.setVisibility(View.VISIBLE);
        ValueAnimator animator = createDropAnimator(view,0,mHiddenViewMeasuredHeight);
        animator.start();
    }
    public void animateClose(final  View view){
        int origHeight = view.getHeight();
        ValueAnimator animator = createDropAnimator(view,origHeight,0);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                view.setVisibility(View.GONE);
            }
        });
        animator.start();
    }
    private ValueAnimator createDropAnimator(final View view, int start, int end){
        ValueAnimator animator = ValueAnimator.ofInt(start,end);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (Integer) animation.getAnimatedValue();
                ViewGroup.LayoutParams layoutParams =
                        view.getLayoutParams();
                layoutParams.height = value;
                view.setLayoutParams(layoutParams);
            }
        });
        return animator;
    }
}

你可能感兴趣的:(Android)