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

1.Android View 动画框架

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

2.Android属性动画分析

     ObjectAnimator使用可以用下面这个例子
<pre name="code" class="java">ObjectAnimator animator = ObjectAnimator.ofFloat(
   view,
   “translationX",
   300);
animator.setDuration(300);
animator.start();<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">    </span>
 

    通过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的优点是放大不是真,不需要为不同分辨率设计多套图标

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

  • 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

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="200dp"
    android:width="200dp"
    android:viewportHeight="100"
    android:viewportWidth="100">
    <group
        android:name="sun"
        android:pivotX="60"
        android:pivotY="50"
        android:rotation="0">
        <path
            android:name="path_sun"
            android:fillColor="@android:color/holo_blue_light"
            android:pathData="
              M 50,50
              a 10,10 0 1,0 20 0
              a 10,10 0 1,0 -20 0"/>
        <group
            android:name="earth"
            android:pivotX="75"
            android:pivotY="50"
            android:rotation="0">
            <path
                android:name="path_earth"
                android:fillColor="@android:color/holo_orange_dark"
                android:pathData="
                  M 70,50
                  a 5,5 0 1,0 10,0
                  a 5,5 0 1,0 -10,0"/>
            <group>
                <path
                    android:fillColor="@android:color/holo_green_dark"
                    android:pathData="
                     M 90,50
                     m -5 0
                     a 4,4 0 1,0 8 0
                     a 4,4 0 1,0 -8 0"/>
            </group>
        </group>
    </group>
</vector><span style="font-size: 16.4268px; font-family: Arial, Helvetica, sans-serif;">	</span>
<pre name="code" class="html" style="font-size: 16.4268px;">这个VectorDrawble分别代表了太阳系系统和地月系统,并且使用pivotX和pivotY方法来指定他们绕着哪个转,接着是动画实现,这里就给出太阳的动画实现,<pre name="code" class="html"><objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="4000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360"
    />
——————————————————————————————————————————————————————————————————————————
最后我们还要使用AnimatedVectorDrawable来粘合SVG静态图形和动画
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vearth">
    <target
        android:animation="@anim/anim_sun"
        android:name="sun"/>
    <target
        android:animation="@anim/anim_earth"
        android:name="earth"/>
</animated-vector> 
 
 

    我们只需使用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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值