Android动画(四)——属性动画ValueAnimator的妙用

目录

介绍

效果图

 代码实现

xml文件


介绍

        ValueAnimator是ObjectAnimator的父类,它继承自Animator。ValueAnimaotor同样提供了ofInt、ofFloat、ofObject等静态方法,传入的参数是动画过程的开始值、中间值、结束值来构造动画对象。可以将ValueAnimator看着一个值变化器,即在给定的时间内将一个目标值从给定的开始值变化到给定的结束值。

        上一篇中我们提到,在使用ValueAnimator时通常需要添加一个动画更新的监听器,在监听器中能够获取到执行过程中的每一个动画值。

privatevoidstartValueAnimator() {
    ValueAnimatorvalueAnimator= ValueAnimator.ofFloat(0, 1);
    valueAnimator.setDuration(300);
    valueAnimator.start();
    valueAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {
        @OverridepublicvoidonAnimationUpdate(ValueAnimator animation) {
            // 动画更新过程中的动画值,可以根据动画值的变化来关联对象的属性,实现属性动画floatvalue= (float) animation.getAnimatedValue();
            Log.d("ValueAnimator", "动画值:" + value);
        }
    });
}复制代码

        ValueAnimator的使用一般会结合更新监听器AnimatorUpdateListener,大多数时候是在自定义控件时使用。

        我们可以利用ValueAnimator自定义控件实现动画打开关闭效果。

效果图

 代码实现

package com.example.animationstudy;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.ActionBar;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity4 extends AppCompatActivity implements View.OnClickListener {

    Button button;
    ImageView imageView;
    TextView textView;

    boolean isClose = true;

    ValueAnimator animator1;
    ValueAnimator animator2;

    LinearLayout.LayoutParams params;
//LinearLayout.LayoutParams 是 Android 中用于定义 LinearLayout(线性布局)中子视图的布局参数的类。它继承自 ViewGroup.MarginLayoutParams 类,因此包含了 Margin 相关的属性。
    //
    //LinearLayout 是一种常用的布局容器,可以水平或垂直排列子视图。而 LinearLayout.LayoutParams 则是用于描述子视图在 LinearLayout 中的布局行为,例如子视图在父布局中的位置、大小、权重等。

    int hight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);

        button = (Button) findViewById(R.id.button4);
        imageView = (ImageView) findViewById(R.id.imageView4);
        textView = (TextView) findViewById(R.id.text42);
        button.setOnClickListener(this);
        imageView.setOnClickListener(this);

        textView.post(new Runnable() {
            @Override
            public void run() {
                hight = textView.getMeasuredHeight();
                init();
            }
        });
//注意,在调用 getMeasuredHeight() 方法前,TextView 控件必须已经完成布局和测量,否则获取到的高度值可能是 0,因此在此之前需要确保 TextView 控件已经被添加到父容器中并已经完成了布局和测量。
//这个方法可以确保 TextView 控件完成了布局,因为它是通过 post 方法将一个 Runnable 对象发送到主线程的消息队列中,并在主线程空闲时执行。在主线程中执行的代码会在 UI 线程的消息循环中得到处理,因此可以保证在布局完成后才执行。
    }

    public void init(){
        animator1 = isClose ? ValueAnimator.ofFloat(0,180) : ValueAnimator.ofFloat(180,0);
        animator1.setDuration(500);
        animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator valueAnimator) {
                float value = (float) animator1.getAnimatedValue();
                imageView.setRotation(value);
            }
        });
        animator1.start();

        params = (LinearLayout.LayoutParams) textView.getLayoutParams();
        animator2 = isClose ? ValueAnimator.ofInt(hight,0) : ValueAnimator.ofInt(0,hight);
        animator2.setDuration(500);
        animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator valueAnimator) {
                int value = (int) valueAnimator.getAnimatedValue();
                Log.d("TextView4", "onAnimationUpdate: " + value);
                params.height = value;
                textView.setLayoutParams(params);
            }
        });
        animator2.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isClose = !isClose;
            }
        });
        animator2.start();
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.button4){
            init();
        }
        if (view.getId() == R.id.imageView4){
            init();
        }
    }
}

xml文件




    

最后的Button没有设置点击事件,起到一个造型上的作用

上一篇:Android动画(三)——属性动画-CSDN博客

本文参考:Android 动画-CSDN博客

你可能感兴趣的:(android)