目录
????????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 version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity4">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button4"
android:text="播放"
android:layout_gravity="center"
android:layout_margin="20dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:id="@+id/tetx41"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="8dp"
android:text="冥王语录"
android:layout_marginLeft="20dp"
android:textColor="#999999"
android:textSize="16sp"/>
<ImageView
android:id="@+id/imageView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="30dp"
android:src="@drawable/up"/>
</LinearLayout>
<TextView
android:id="@+id/text42"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text=" 美,只不过是一瞬间的感觉,只有真实才是永恒的,而真实绝不会美
爱能创造一切,也能毁灭一切。当你用爱保护羊群不受狼的伤害,那么对于狼,这种爱心就等于毁灭,因为他们会因此而活活饿死。这个世界本就如此,不是狼死就是羊死,不是弱小的狼被饿死,就是弱小的羊被咬死。或许,这世界太过残酷,然而,却因此而美丽。"
android:textColor="#999999"
android:textSize="16sp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello world"
android:layout_margin="20dp"
android:layout_gravity="center"/>
</LinearLayout>
最后的Button没有设置点击事件,起到一个造型上的作用
本文参考:Android 动画-CSDN博客