Android中的属性动画

article/2025/8/21 21:14:11

1.属性动画简介

接下来我们学习Android动画中的第三种动画——属性动画(Property Animation)

Animation一般动画就是我们前面学的帧动画和补间动画Animator则是本节要讲的属性动画

1.1为什么要用属性动画

  • 补间动画功能比较单调,只有四种动画(透明度,旋转,倾斜和位移)

  • 补间动画针对的对象只是UI控件

  • 补间动画只是改变View的显示效果,不会去改变View的属性

eg:左边的按钮移到右边,但是此时的按钮其实还停留在左边,假如你去点右面的按钮,是不会触发按钮的点击事件的~

1.2属性动画是什么

  • Andoid 3.0引入,可以说是补间动画的增强版,不止可以实现四种动画效果,可以定义任何属性的变化;

  • 执行动画的对象不只是U控件。可以对任何对象执行动画(不管是否显示在屏幕上)

  • 属性动画通过对目标对象进行赋值来修改其属性,上面那个按钮问题就不存在了~

1.3属性动画常用API

见下图:

2.ValueAnimator简单使用

2.1使用流程

  1. 调用ValueAnimator的ofInt(),ofFloat()或ofObject()静态方法创建ValueAnimator实例

  2. 调用实例的setXxx方法设置动画持续时间,插值方式,重复次数等

  3. 调用实例的addUpdateListener添加AnimatorUpdateListener监听器,在该监听器中 可以获得ValueAnimator计算出来的值,你可以值应用到指定对象上

  4. 调用实例的start()方法开启动画! 另外我们可以看到ofInt和ofFloat都有个这样的参数:float/int... values代表可以多个值!

2.2实例:

布局文件:activity_main.xml,非常简单,四个按钮,一个ImageView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/ly_root"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn_one"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="动画1" /><Buttonandroid:id="@+id/btn_two"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="动画2" /><Buttonandroid:id="@+id/btn_three"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="动画3" /><Buttonandroid:id="@+id/btn_four"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="动画4" /><ImageViewandroid:id="@+id/img_babi"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:background="@mipmap/img_babi" /></LinearLayout>

接着到MainActivity.java, 首先需要一个修改View位置的方法,这里调用moveView()设置左边和上边的起始坐标以及宽高!

接着定义了四个动画,分别是:直线移动,缩放,旋转加透明,以及圆形旋转!

然后通过按钮触发对应的动画~

public class MainActivity extends AppCompatActivity {private Button btn_one;private Button btn_two;private Button btn_three;private Button btn_four;private ImageView iv_babi;private LinearLayout ly_root;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);iv_babi = findViewById(R.id.iv_babi);ly_root = findViewById(R.id.ly_root);btn_one = findViewById(R.id.btn_one);btn_two = findViewById(R.id.btn_two);btn_three = findViewById(R.id.btn_three);btn_four = findViewById(R.id.btn_four);btn_one.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//获取总布局的宽和高int width = ly_root.getWidth();int height = ly_root.getHeight();ValueAnimator va = ValueAnimator.ofInt(height,0,height/4,height/2,height/4*3,height);va.setDuration(3000l);va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {int x = width/2;int y = (int) va.getAnimatedValue();moveView(iv_babi,x,y);}});va.setInterpolator(new LinearInterpolator());va.start();}});btn_two.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {final float scale = 0.5f;AnimatorSet scaleSet = new AnimatorSet();ValueAnimator vaSmall =ValueAnimator.ofFloat(1.0f,scale);vaSmall.setDuration(500);ValueAnimator vaLarge = ValueAnimator.ofFloat(scale,1.0f);vaLarge.setDuration(500);vaSmall.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float scale = (float) valueAnimator.getAnimatedValue();iv_babi.setScaleX(scale);iv_babi.setScaleY(scale);}});vaLarge.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float scale = (float) valueAnimator.getAnimatedValue();iv_babi.setScaleX(scale);iv_babi.setScaleY(scale);}});scaleSet.play(vaLarge).after(vaSmall);scaleSet.start();}});btn_three.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {int width = ly_root.getWidth();int height = ly_root.getHeight();final int R = width/4;ValueAnimator va = ValueAnimator.ofFloat(0,(float) (2.0f*Math.PI));va.setDuration(1000);va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float t = (float) valueAnimator.getAnimatedValue();int x =(int) (R* Math.sin(t)+width/2);int y =(int) (R* Math.cos(t)+height/2);moveView(iv_babi,x,y);}});va.setInterpolator(new DecelerateInterpolator());va.start();}});btn_four.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {ValueAnimator va = ValueAnimator.ofInt(0,360);va.setDuration(1000l);va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {int rotate = (Integer) valueAnimator.getAnimatedValue();iv_babi.setRotation(rotate);float fractionValue = valueAnimator.getAnimatedFraction();iv_babi.setAlpha(fractionValue);}});va.setInterpolator(new DecelerateInterpolator());va.start();}});}private void moveView(View view,int rawX,int rawY){int left = rawX- view.getWidth()/2;int top = rawY - view.getHeight();int weight = left + view.getWidth();int height = top+ view.getHeight();view.layout(left,top,weight,height);}

好的,使用的流程非常简单,先创建ValueAnimator对象,调用ValueAnimator.ofInt/ofFloat 获得,然后设置动画持续时间,addUpdateListener添加AnimatorUpdateListener事件监听, 然后使用参数animationgetAnimatedValue()获得当前的值,然后我们可以拿着这个值 来修改View的一些属性,从而形成所谓的动画效果,接着设置setInterpolator动画渲染模式, 最后调用start()开始动画的播放

3.ObjectAnimator简单使用

比起ValueAnimator,ObjectAnimator显得更为易用,通过该类我们可以直接 对任意对象的任意属性进行动画操作!没错,是任意对象,而不单单只是View对象, 不断地对对象中的某个属性值进行赋值,然后根据对象属性值的改变再来决定如何展现 出来!比如为TextView设置如下动画: ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f); 这里就是不断改变alpha的值,从1f - 0f,然后对象根据属性值的变化来刷新界面显示,从而 展现出淡入淡出的效果,而在TextView类中并没有alpha这个属性,ObjectAnimator内部机制是: 寻找传输的属性名对应的get和set方法~,而非找这个属性值! 不信的话你可以到TextView的源码里找找是否有alpha这个属性! 好的,下面我们利用ObjectAnimator来实现四种补间动画的效果吧~

3.1实例

先看一下效果图:

 代码实现如下:

布局直接用的上面那个布局,加了个按钮,把ImageView换成了TextView,这里就不贴代码了, 直接上MainActivity.java部分的代码,其实都是大同小异的~

public class MainActivity3 extends AppCompatActivity implements View.OnClickListener {private Button button1;private Button button2;private Button button3;private Button button4;private Button button5;private LinearLayout ly_root;private TextView tv_show;private int height;private ObjectAnimator animator1;private ObjectAnimator animator2;private ObjectAnimator animator3;private ObjectAnimator animator4;private AnimatorSet animSet;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main3);bindViews();initAnimator();}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.button1:animator1.setDuration(3000l);animator1.start();break;case R.id.button2:animator2.setDuration(3000l);animator2.start();break;case R.id.button3:animator3.setDuration(3000l);animator3.start();break;case R.id.button4:animator4.setDuration(3000l);animator4.start();break;case R.id.button5://将前面的动画集合到一起~animSet = new AnimatorSet();animSet.play(animator4).with(animator3).with(animator2).after(animator1);animSet.setDuration(5000l);animSet.start();break;case R.id.tv_show:Toast.makeText(MainActivity3.this, "这也可以点???", Toast.LENGTH_SHORT).show();break;}}private void bindViews() {ly_root = (LinearLayout) findViewById(R.id.ly_root);button1 = (Button) findViewById(R.id.button1);button2 = (Button) findViewById(R.id.button2);button3 = (Button) findViewById(R.id.button3);button4 = (Button) findViewById(R.id.button4);button5 = (Button) findViewById(R.id.button5);tv_show = (TextView) findViewById(R.id.tv_show);height = ly_root.getHeight();button1.setOnClickListener(this);button2.setOnClickListener(this);button3.setOnClickListener(this);button4.setOnClickListener(this);button5.setOnClickListener(this);tv_show.setOnClickListener(this);}private void initAnimator(){animator1 = ObjectAnimator.ofFloat(tv_show, "alpha", 1f, 0f, 1f, 0f, 1f);animator2 = ObjectAnimator.ofFloat(tv_show, "rotation", 0f, 360f, 0f);animator3 = ObjectAnimator.ofFloat(tv_show, "scaleX", 2f, 4f, 1f, 0.5f, 1f);animator4 = ObjectAnimator.ofFloat(tv_show, "translationY", height / 8, -100, height / 2);}}

4.使用XML来编写动画

使用XML来编写动画,画的时间可能比Java代码长一点,但是重用起来就轻松很多! 对应的XML标签分别为:<animator><objectAnimator><set> 相关的属性解释如下:

  • android:ordering:指定动画的播放顺序:sequentially(顺序执行),together(同时执行)

  • android:duration:动画的持续时间

  • android:propertyName="x":这里的x,还记得上面的"alpha"吗?加载动画的那个对象里需要 定义getx和setx的方法,objectAnimator就是通过这里来修改对象里的值的!

  • android:valueFrom="1" :动画起始的初始值

  • android:valueTo="0" :动画结束的最终值

  • android:valueType="floatType":变化值的数据类型

4.1实例:

animator/property_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:ordering="together" ><objectAnimatorandroid:duration="3000"android:propertyName="translationX"android:valueFrom="-500"android:valueTo="0"android:valueType="floatType" ></objectAnimator><objectAnimatorandroid:duration="3000"android:propertyName="rotation"android:repeatCount="3"android:valueFrom="0"android:valueTo="360"android:valueType="floatType" ></objectAnimator></set>

加载我们的动画文件

public class MainActivity4 extends AppCompatActivity {private TextView tv_show;private Button btn_start;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main4);btn_start = findViewById(R.id.btn_start);tv_show = findViewById(R.id.tv_show);Animator animator = AnimatorInflater.loadAnimator(MainActivity4.this, R.animator.property_animator);animator.setTarget(tv_show);tv_show.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Toast.makeText(MainActivity4.this, "没想到吧,我也可以点~~~", Toast.LENGTH_SHORT).show();}});btn_start.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {animator.start();}});}
}


http://chatgpt.dhexx.cn/article/E8T4INLt.shtml

相关文章

android 动画库

1. Spruce(安卓动画库)&#xff08;是一个轻量级的动画库&#xff0c;可以帮助排版屏幕上的动画。使用有很多不同的动画库时&#xff0c;开发人员需要确保每个视图都能够在适当的时间活动。&#xff09; 2. Litho&#xff08;是一个非常强大的框架&#xff0c;以声明的方式构建…

android动画类型有哪几种,Android动画概念大揭秘

前言 说起Android里面的动画,我可能会立马想起平移、旋转、渐变、缩放等动画效果,但是对于他们的属性就记的不太清了,知道的都是皮毛而且很容易忘记,每次需要用到的时候总要去baidu或者google,完全无法做到灵活应用,信手拈来。所以抽时间重新温故了一下动画相关的知识,把…

Android 动画分类

前言 动画的使用 是 Android 开发中常用的知识可是动画的种类繁多、使用复杂&#xff0c;每当需要 采用自定义动画 实现 复杂的动画效果时&#xff0c;很多开发者就显得束手无策本文将献上一份Android动画的全面介绍攻略&#xff0c;包括动画的种类、使用、原理等&#xff0c;能…

Android动画

这篇博客主要总结一下自己在项目中对动画的一些使用。我写博客&#xff0c;其实更多的是总结自己在工作中用到的一些知识。比如某一段时间一个知识点相关的技术用的比较多&#xff0c;那我会总结一下。其实&#xff0c;对于Android动画的总结&#xff0c;这是几个月前就应该写完…

Android动画之帧动画

在Android开发时&#xff0c;为了实现一些动态的炫酷的效果&#xff0c;我们常用到帧动画&#xff0c;View动画&#xff08;补间动画&#xff09;和属性动画&#xff0c;今天就来总结下我在使用帧动画的实现方式。 1、什么是帧动画&#xff1f; 帧动画就是顺序播放一组预先定…

【Android】动画

概念 动画实际上就是在指定的时间段内持续的修改某个属性的值&#xff0c;使得该值在指定取值范围之内平滑的过渡 android中的动画分为&#xff1a;View动画、帧动画和属性动画 帧动画 Frame动画是一系列图片按照一定的顺序展示的过程&#xff0c;它的原理是在一定的时间段内切…

STM32 LWIP SNTP实现毫秒级的时间校准

1、首先配置LWIP支持SNTP 然后在opt.h中增加一个timeout->LWIP_SNTP 防止出现类似 Assertion "sys_timeout: timeout ! NULL, pool MEMP_SYS_TIMEOUT is empty" failed at line 190 in ../Middlewares/Third_Party/LwIP/src/core/timeouts.c 这样的错误。 /*…

NTP/SNTP协议介绍和校时服务器搭建

文|Seraph 本文主要简单介绍用于校时的NTP/SNTP协议 同时&#xff0c;以windows 2008 R2为例&#xff0c;搭建NTP/SNTP服务器 NTP可参考文献RFC1305&#xff0c;SNTP可参考文献RFC1796 1. 应用场景 一般应用&#xff0c;连上公网即可通过NTP/SNTP协议进行校时&#xff0c;例如…

linux sntp 代码,C语言window(linux)平台的SNTP实现

C语言实现window(linux)平台的SNTP&#xff0c;本程序功能主要是实现电脑(或者设备)时间同步。摘录部分代码&#xff1a; unsigned char liVnMode; /* LeapSecond(2bits:0), VersionNumber(3bits: 3), Mode(3bits: Client3, Server4) */ unsigned char stratum; /* 时间层级 (0…

学习日记——ESP8266SNTP

SNTP基本知识 1、定义 SNTP是简单网络时间协议&#xff0c;而NTP网络时间协议就是网络计算机上同步计算时间的协议&#xff0c;具有高度的精确性&#xff0c;实际上也用不到这么高精度的算法。所以就在NTP上简化了以下变成SNTP&#xff0c;SNTP协议主要被用来同步因特网上计算…

WiFi开发|ESP8266模组SDK开发之SNTP协议

ESP8266模组SDK开发之SNTP协议 1. NTP和SNTP NTP 是网络时间协议&#xff08;Network Time Protocol&#xff09;&#xff0c;是用来同步网络设备&#xff08;如计算机、手机&#xff09;的时间的协议 SNTP由NTP改编而来&#xff08;简单网络时间协议&#xff0c;Simple Net…

ESP8266学习笔记(11)——SNTP接口使用

一、SNTP简介 简单网络时间协议&#xff08;Simple Network Time Protocol&#xff09;&#xff0c;由 NTP 改编而来&#xff0c;主要用来同步因特网中的计算机时钟 二、SNTP接口 SNTP 接口位于 ESP8266_NONOS_SDK/include/sntp.h。 三、初始化SNTP 设置三个时间服务器…

ESP32 SNTP配置

SNTP&#xff0c;Simple Network Time Protocol&#xff08;简单网络时间协议&#xff09;&#xff0c;用来同步时钟。 百度百科&#xff1a;SNTP SNTP协议采用客户端/服务器的工作方式&#xff0c;可以采用单播&#xff08;点对点&#xff09;或者广播&#xff08;一点对多点&…

通过sntp同步系统时间

通过sntp同步系统时间 小型物联网设备&#xff0c;很少有接口提供给用户进行数据交互&#xff0c;那么我们设备的系统时间只能够通过获取网络时间后&#xff0c;再更新到本地。那么&#xff0c;就少不了使用sntp协议。 ntp协议&#xff1a;NTP(Network Time Protocol&#xff…

2012系统sntp服务器,如何设置SNTP服务器,实现同步PLC时钟

在过程/生产自动化系统构架和运行时&#xff0c;有时需要实现对时间的精确控制&#xff0c;即系统中所有子系统(包括设备等)的时间必须保持同步。 作为自动化系统组成部分的 以Windows 7操作系统为例&#xff0c;将PC机配置为SNTP服务器端的操作步骤&#xff1a; [注意]操作前前…

ESP32学习笔记(41)——SNTP接口使用

一、SNTP简介 简单网络时间协议&#xff08;Simple Network Time Protocol&#xff09;&#xff0c;由 NTP 改编而来&#xff0c;主要用来同步因特网中的计算机时钟。 SNTP 协议是用来同步本地的时间到 unix 时间戳。通常嵌入式设备上电&#xff0c;连接 AP(access point)&…

物联网专题27:SNTP

什么是SNTP&#xff08;Simple Network Time Protocol&#xff09;&#xff1f;简单时钟控制协议&#xff0c;主要用来同步因特网中的计算机时钟。 SNTP&#xff0c;使用的默认端口号是 UDP123。 ESP8266中&#xff0c;SNTP相关的API&#xff1a; 1 设置SNTP服务器&#xff08…

ESP8266-----SNTP获取网络时间

目录 前言 user_init IP定时的回调函数 初始化SNTP SNTP定时回调函数 前言 介绍了8266如何获取网络时间 user_init 首先将8266设置为sta模式 void ICACHE_FLASH_ATTR user_init(void) {uart_init(115200,115200); // 初始化串口波特率os_delay_us(10000); // 等待串口…

微软 sntp服务器地址,电脑sntp服务器地址

电脑sntp服务器地址 内容精选 换一换 当创建文件系统后&#xff0c;您需要使用云服务器来挂载该文件系统&#xff0c;以实现多个云服务器共享使用文件系统的目的。本章节以Windows 2012版本操作系统为例进行NFS文件系统挂载&#xff0c;其他版本请参考以下主要步骤根据实际界面…

ESP32 SNTP设置

SNTP&#xff0c;Simple Network Time Protocol&#xff08;简单网络时间协议&#xff09;&#xff0c;用来同步时钟。 百度百科&#xff1a;[SNTP](https://baike.baidu.com/item/sntp/4749147?fraladdin) SNTP协议采用客户端/服务器的工作方式&#xff0c;可以采用单播&…