Andoird 动画---属性动画(二)

1、ObjectAnimator

        在3.0系统之后,Android为我们提供了一种新的动画——Animator属性动画。在属性动画中,我们不仅可以像补间动画那样设置控件的透明度、缩放、平移或旋转的动画,还可以做到将这些动画联合起来播放、将一组动画按顺序播放、控制动画的播放速度,甚至可以对非View设置动画等等。

        简单的说就是改变动画的某一个属性,从而控制动画的某一个效果。

 ObjectAnimator animator = ObjectAnimator.ofFloat(
                view,
                "alpha",
                0.5f,
                1.0f);
animator.setDuration(3000);
animator.start();

上面代码中,ofFloat() 方法的第一个参数是动画作用的view对象第二个参数是属性名称第三个参数是一个不定长参数,指定属性的起始值和结束值;

当然也可以调用setDuration()方法指定的是动画执行的时长;最后调用start()方法,动画就开始执行了。

其中 第二个参数是属性名称 可以设置的值有

  • translationX 、translationY :针对X 轴或者Y 轴进行平移
  • rotation、rotationX、rotationY:view围绕支点进行2D 或者 3D 旋转
  • scaleX、scaleY:围绕X 支点 或者Y支点进行2D缩放
  • pivotX 、pivotY:控制View 的支点位置,围绕这个支点进行动画旋转,缩放。默认支点就是View对象的中心点。
  • x,y:View 对象在容器中的最终位置,相当于translationX 、translationY 的积分最终值。
  • alpha :透明度变化 1 (不透明) ,0 (透明)

可以看出来这些动画基本可以涵盖我们的需求了。

2、PropertyValuesHolder

  1. 类似视图动画的AnimationSet,可以实现多个属性动画的组合
  2. 在平移的过程中,同时改变X、Y轴的缩放,可以这样实现:
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX",300f);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX",1f,0,1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY",1f,0,1f);
ObjectAnimator.ofPropertyValuesHolder(view,pvh1,pvh2,pvh3).setDuration(1000).start();

3、ValueAnimator

  1. ObjectAnimator继承自ValueAnimator
  2. ValueAnimator本身不提供任何动画效果,提供动画过程的一个数值发生器:
ValueAnimator animator = ValueAnimator.ofFloat(0,100);
animator.setTarget(view);
animator.setDuration(1000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value = (float) animation.getAnimatedValue();
        //TODO use the value
    }

用来改变动画的过程中的其他逻辑或者效果。

4、动画事件的监听

ObjectAnimator anim = ObjectAnimator.ofFloat(view,"alpha",0.5f);
anim.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
 
    }
 
    @Override
    public void onAnimationEnd(Animator animation) {
 
    }
 
    @Override
    public void onAnimationCancel(Animator animation) {
 
    }
 
    @Override
    public void onAnimationRepeat(Animator animation) {
 
    }
});

大部分我们只关心End事件

anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
 
    }

5、AnimatorSet

  • AnimatorSet可以实现和PropertyValuesHolder一样的效果,不同的是Animator还可以实现更精确的顺序控制:
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0, 1f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0, 1f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1,animator2,animator3);
set.start();

还可以给动画设置插值器

set.setInterpolator(new BounceInterpolator());
  • AnimatorSet不仅仅通过playTogether(),还有其他方法控制多个效果的协同工作:playSequentially()、animSet.play().with()、before()、after() 

最后我们来做个小例子,群英传里提到的灵动菜单:

使用了两个知识点:ObjectAnimator &  AnimatorSet

package com.zx.matrix.objectanimator;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.BounceInterpolator;
import android.widget.ImageView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity implements View.OnClickListener {
    private int[] mRes = {R.id.imageView_a, R.id.imageView_b, R.id.imageView_c,
            R.id.imageView_d, R.id.imageView_e};
    private List<ImageView> mImageViews = new ArrayList<ImageView>();
    private boolean mFlag = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (int i = 0; i < mRes.length; i++) {
            ImageView imageView = (ImageView) findViewById(mRes[i]);
            imageView.setOnClickListener(MainActivity.this);
            mImageViews.add(imageView);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageView_a:
                if (mFlag) {
                    startAnim();
                } else {
                    closeAnim();
                }
                break;
            default:
                Toast.makeText(MainActivity.this, "" + v.getId(),
                        Toast.LENGTH_SHORT).show();
                break;
        }
    }

    private void  startAnim(){
        ObjectAnimator animator0 = ObjectAnimator.ofFloat(
                mImageViews.get(0),
                "alpha",
                1F,
                0.5F);

        ObjectAnimator animator1 = ObjectAnimator.ofFloat(
                mImageViews.get(1),
                "translationX",
                0F,
                200F);

        ObjectAnimator animator2 = ObjectAnimator.ofFloat(
                mImageViews.get(2),
                "translationX",
                0F,
                -200F);

        ObjectAnimator animator3 = ObjectAnimator.ofFloat(
                mImageViews.get(3),
                "translationY",
                0F,
                -200F);

        ObjectAnimator animator4 = ObjectAnimator.ofFloat(
                mImageViews.get(4),
                "translationY",
                0F,
                200F);
        AnimatorSet set = new AnimatorSet();
        set.setDuration(500);
        set.setInterpolator(new BounceInterpolator());
        set.playTogether(
                animator0,
                animator1,
                animator2,
                animator3,
                animator4);
        set.start();
        mFlag = false;

    }

    private void closeAnim(){
        ObjectAnimator animator0 = ObjectAnimator.ofFloat(
                mImageViews.get(0),
                "alpha",
                0.5f,
                1.0f);
        
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(
                mImageViews.get(1),
                "translationX",
                200f,
                0f);
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(
                mImageViews.get(2),
                "translationX",
                -200f,
                0f);
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(
                mImageViews.get(3),
                "translationY",
                -200f,
                0f);
        ObjectAnimator animator4 = ObjectAnimator.ofFloat(
                mImageViews.get(4),
                "translationY",
                200f,
                0f);
        AnimatorSet set = new AnimatorSet();
        set.setDuration(500);
        set.playTogether(animator0,animator1,animator2,animator3,animator4);
        set.setInterpolator(new BounceInterpolator());
        set.start();
        mFlag = true;
    }
}

效果如下:

 

回顾动画监听ValueAnimator  ,做一个小例子,下拉展开动画

布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:onClick="llClick"
        android:background="@android:color/holo_blue_bright"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/app_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:gravity="left"
            android:text="Click Me"
            android:textSize="30sp" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/hidden_view"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="@android:color/holo_orange_light"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:visibility="gone">

        <ImageView
            android:src="@mipmap/ic_launcher"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center" />

        <TextView
            android:id="@+id/tv_hidden"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:textSize="20sp"
            android:text="I am hidden" />
    </LinearLayout>
</LinearLayout>

MainActivity:

package com.zx.matrix.valueanimator;

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

public class MainActivity extends AppCompatActivity {

    private LinearLayout hiddenView;
    private float density;
    private int HiddenViewHeight;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        hiddenView = (LinearLayout) findViewById(R.id.hidden_view);

        density = getResources().getDisplayMetrics().density;
        HiddenViewHeight = (int)(density * 40 +0.5);
    }

    ValueAnimator createValueAnim(final View view ,int start,int end){
        ValueAnimator valueAnimator = ValueAnimator.ofInt(start,end);
        valueAnimator.setDuration(800);
        valueAnimator.setTarget(view);
        valueAnimator.setInterpolator(new BounceInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (Integer) animation.getAnimatedValue();
                ViewGroup.LayoutParams params = view.getLayoutParams();
                params.height = value;
                view.setLayoutParams(params);
            }
        });
        return  valueAnimator;
    }

    public void llClick(View v){
        if (hiddenView.getVisibility() == View.GONE){
            openAnim();
        }else {
            closeAnim();
        }
    }

    private void openAnim(){
        hiddenView.setVisibility(View.VISIBLE);
        ValueAnimator animator = createValueAnim(hiddenView,0,HiddenViewHeight);
        animator.start();
    }

    private void closeAnim(){
        ValueAnimator animator = createValueAnim(hiddenView,HiddenViewHeight,0);
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                hiddenView.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.start();
    }

}

可以看到,我们在让隐藏布局出现的时候,先设置 其可见,在隐藏的时候,在动画结束的时候,设置其Gone 掉。

实现效果:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值