Android进阶--属性动画Property Animation详解(一)_html/css_WEB-ITnose
引言
前一篇文章Android入门——补间动画和帧动画应用小结总结了补间动画和帧动画及一些相关类的应用,基本可以掌握简单的缩放、旋转、透明度变化、平移的动画效果,但是需要实现更复杂的动画效果时,比如说希望View的切换动画、Layout的切换动画、3D旋转动画等等,这些View Animation都无法做到。此时Property Animation应运而生,这篇主要总结下属性动画的相关知识点。
一、Property Animation属性动画概述属性动画,在我最先接触到Android 1.5时还没有这个动画系统,直到Android 3.0中才引进的(在3.0之前的系统中,可通过NineOldAndroids项目使用Property Animation)。官方文档是这样介绍他的:该属性动画系统是一个强大的框架,几乎可以为任何对象设置动画效果,可以定义随时间而改变任何对象属性的动画,无论它是否已经绘制到屏幕。在指定的时间长度值,改变的是对象的实际属性的(一个字段中的对象)值。简而言之,Property Animation就是,由动画的执行类(Animator系)来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态地改变对象的属性从而形成的一种动画效果。。
二、Property Animation动画过程接下来引用下官方文档的例子说明下(Ps:Google的官方文档已经说得很好了,可以说是最好的学习教材,当然你得耐心看英文)。
第一个例子是以持续时间为40ms且匀速变化的动画,其中每10ms刷新一帧(目的是通过10个像素水平移动),请注意把x看作这个对象的实际属性的话,这个x也是随着动画的进行一直在改变的。
第二个可以看到,这是非线性变化的动画(通过改变属性值的方法,即设置不同的interpolation,在下图中运动速度先逐渐增大再逐渐减小),也是在40ms的时间移动了40个像素,x这个属性也是随着动画的进行不断在改变的。
1、属性动画的监听器
属性动画的基类Animator里封装了两个内部监听接口:Animator.AnimatorListener『onAnimationCancel(Animator animation)、onAnimationEnd(Animator animation)、onAnimationRepeat(Animator animation)、
、onAnimationStart(Animator animation)』 和
Animator.AnimatorPauseListener『 onAnimationPause(Animator animation)、onAnimationResume(Animator animation)』 。
void addListener(Animator.AnimatorListener listener) | 添加监听(在整个生命周期内through the life of an animation, such as start, repeat, and end.) |
void addPauseListener(Animator.AnimatorPauseListener listener) | 在暂停时监听 |
void removeAllListeners() | 取消所有监听 |
void removeListener(Animator.AnimatorListener listener) | 取消指定监听 |
void removePauseListener(Animator.AnimatorPauseListener listener) | 取消指定暂停监听 |
首先还是看下官方的Property Animation几个重要组件之间的关系图
比如在图2中,使用的TimeInterpolator的是AccelerateDecelerateInterpolator ,而TypeEvaluator是IntEvaluator,而ValueAnimator是属性动画的核心类封装了前两者。
ValueAnimator | 包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等 |
TimeInterpolator | 定义动画interpolation的方式 |
TypeEvaluator, | 一个接口, 根据开始、结束值与TimeIniterpolator计算得到的值计算出属性值。 |
ObjectAnimator | 继承自ValueAnimator,也是一个动画执行类 |
AnimatorSet | 用于控制一组动画的执行:线性,同时,每个动画的先后执行等。 |
AnimatorInflater | 用户加载属性动画的xml文件 |
当想要start属性动画之前,系统会先建立一个ValueAnimator并为属性指定开始值和结束值,接着调用start()运行动画,在整个动画运行时期,ValueAnimator基于已经运行的时间和整个动画的持续时间的比计算出一个时间系数(范围是0——1,其中0代表0%,1代表已完成100%),然后TimeInterpolator计算出插值系数(fraction ),最后TypeAnimator通过开始时间、结束时间以及插值系数计算出当时的属性值。
例如:
上面例子t=10ms时ValueAnimator根据运行的时间和整个动画的持续时间的比计算出时间系数为0.25(10/40),然后TimeInterpolator计算出插值系数约为0.15,
//上例使用的是AccelerateDecelerateInterpolator,其中input为时间系数public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}
最后TypeAnimator通过这个因子计算出在10ms时的属性值为6pix。
//插值系数fraction,开始值startValue,结束值endValuepublic Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat);}
1、使用ObjectAnimator 运行属性动画
ObjectAnimator运行属性动画要求动画所作用的对象object,必须提供该对应属性的get和set方法,因为属性动画根据你传递的该属性的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,确切来说是随着时间的推移,所传递的值越来越接近最终值。简而言之,你对object的属性xxx做动画,如果想让动画生效,要同时满足两个条件。
当对于属性值,若值传递一个的时,默认为当前对象该属性的值为开始(通过getPropName反射获取,所以这个第二个参数即属性字段必须是实际存在的),然后设置的值为终点。若传递两个,则一个为开始、一个为结束,这些ofXxx系都是返回ObjectAnimator的
static ObjectAnimator ofFloat(Object target, String propertyName, float... values)//其他重载形式省
translationX,translationY | View相对于原始位置的偏移量 |
rotation,rotationX,rotationY | 旋转,rotation用于2D旋转角度,3D中用到后两个 |
scaleX,scaleY: | 缩放比 |
x,y | View的最终坐标,是View的left,top位置加上translationX,translationY |
alpha | 透明度 |
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <ImageView android:id="@+id/id_ball" android:layout_width="400dp" android:layout_height="400dp" android:layout_centerInParent="true" android:src="@mipmap/bcg" android:scaleType="centerCrop" android:onClick="runPropertyAnim" /></RelativeLayout>
package com.crazymo.anim;import android.animation.ObjectAnimator;import android.app.Activity;import android.os.Bundle;import android.view.View;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void runPropertyAnim(View v){ ObjectAnimator .ofFloat(v, "rotationY", 0.0F, -360.0F)//rotationY为v的实际属性字段,如果任意传递字段值程序有可能无效果甚至crash,本例中是ImageView的实际属性 .setDuration(5000) .start(); }}
2、使用ValueAnimator运行属性动画
ValueAnimator本身不作用于任何对象,即直接使用它没有任何动画效果。它可以对一个属性值做动画,然后通过可以监听其动画过程,在动画过程中修改我们的对象的属性值,这样也就相当于我们的对象做了动画,当然,也不要求操作的对象的属性一定要有getter和setter方法,你可以自己根据当前动画的计算值,来操作任何属性。
package com.crazymo.anim;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.view.WindowManager;import android.view.animation.AccelerateInterpolator;import android.widget.ImageView;public class MainActivity extends Activity { private float mScreenHeight; private ImageView mImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); mImage= (ImageView) findViewById(R.id.img_ball); WindowManager wm = (WindowManager)getApplicationContext() .getSystemService(Context.WINDOW_SERVICE); //int width = wm.getDefaultDisplay().getWidth(); mScreenHeight = wm.getDefaultDisplay().getHeight(); } /** * @param view 作用的目标对象 */ public void verticalRun( View view) { ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight - mImage.getHeight()); animator.setTarget(mImage);//设置应用到的目标对象 animator.setInterpolator(new AccelerateInterpolator());//设置加速器 animator.setDuration(2000).start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mImage.setTranslationY((Float) animation.getAnimatedValue()); } }); }}
3、AnimatorSet的应用
AnimatorSet() | 构造方法 |
void cancel() | 取消动画集 |
AnimatorSet.Builder play(Animator anim) | 产生Builder对象,用于设置播放动画的规则(约束) |
void playSequentially(Animator… items)及重载形式 | 依次执行动画效果 |
void playTogether(Animator… items)及重载形式 | 同时执行动画 |
void setTarget(Object target) | 设置应用的目标对象 |
void start() | 启动动画集 |
public void runAnimSets(View view) { ObjectAnimator animScaleX = ObjectAnimator.ofFloat(mImage, "scaleX", 2.0f, 0.5f); ObjectAnimator animScaleY = ObjectAnimator.ofFloat(mImage, "scaleY", 2.0f, 0.5f); ObjectAnimator animAlpha=ObjectAnimator.ofFloat(mImage,"alpha",1.0f,0.0f); AnimatorSet animSet = new AnimatorSet(); animSet.setDuration(4000); animSet.setInterpolator(new LinearInterpolator()); //三个动画同时执行 animSet.playTogether(animScaleX, animScaleY,animAlpha); animSet.start(); }
动画开始时先扩大两倍然后再缩小同时透明度减小为0
1、首先在res下建立animator文件夹,然后建立对应的xml文件,根节点为set嵌套objectAnimator(其中orderring属性值:同时执行together,依次执行sequentially)或者直接为objectAnimator。
<?xml version="1.0" encoding="utf-8"?><objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="0.5" android:valueType="floatType" ></objectAnimator>
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together" > <objectAnimator android:duration="3000" android:propertyName="scaleX" android:valueFrom="1" android:valueTo="0.5" > </objectAnimator> <objectAnimator android:duration="0000" android:propertyName="scaleY" android:valueFrom="1" android:valueTo="0.5" > </objectAnimator> <objectAnimator android:duration="3000" android:propertyName="alpha" android:valueFrom="1.0" android:valueTo="0"> </objectAnimator></set>
2、然后使用AnimatorInflater加载动画的资源文件
// 加载动画 Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_scalealpha);
3、给目标View设置旋转、缩放、反转等的中心点或者轴,(默认中心缩放,和中间对称线为反转线),然后手动触发View重绘
mImage.setPivotX(0);mImage.setPivotY(0);//触发重绘mImage.invalidate();//mImage.postInvalidate();
4、给Animator设置target并start动画,Over。
anim.setTarget(mImage);anim.start();
完整的方法
public void runXmlAnimSet(View v){ Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_scalealpha); mImage.setPivotX(0); mImage.setPivotY(0); //显示的调用invalidate mImage.invalidate(); mImage.postInvalidate(); anim.setTarget(mImage); anim.start(); }
Property Animation它更改的是对象的实际属性,本质就是系统根据特定的算法不断地动态改变对象的实际属性从而形成一种动画效果,而在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变,比如说无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用于View,还可以应用于任何对象。

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Le cache de mise à jour de la page Web du compte officiel, cette chose est simple et simple, et elle est suffisamment compliquée pour en boire un pot. Vous avez travaillé dur pour mettre à jour l'article officiel du compte, mais l'utilisateur a toujours ouvert l'ancienne version. Dans cet article, jetons un coup d'œil aux rebondissements derrière cela et comment résoudre ce problème gracieusement. Après l'avoir lu, vous pouvez facilement faire face à divers problèmes de mise en cache, permettant à vos utilisateurs de toujours ressentir le contenu le plus frais. Parlons d'abord des bases. Pour le dire franchement, afin d'améliorer la vitesse d'accès, le navigateur ou le serveur stocke des ressources statiques (telles que des images, CSS, JS) ou du contenu de la page. La prochaine fois que vous y accédez, vous pouvez le récupérer directement à partir du cache sans avoir à le télécharger à nouveau, et il est naturellement rapide. Mais cette chose est aussi une épée à double tranchant. La nouvelle version est en ligne,

L'article discute de l'utilisation des attributs de validation de formulaire HTML5 comme les limites requises, motifs, min, max et longueurs pour valider la saisie de l'utilisateur directement dans le navigateur.

Cet article démontre un ajout de bordure PNG efficace aux pages Web à l'aide de CSS. Il soutient que CSS offre des performances supérieures par rapport à JavaScript ou à des bibliothèques, détaillant comment ajuster la largeur, le style et la couleur des bordures pour un effet subtil ou proéminent

L'article examine les meilleures pratiques pour assurer la compatibilité des navigateurs de HTML5, en se concentrant sur la détection des fonctionnalités, l'amélioration progressive et les méthodes de test.

L'article traite du HTML & lt; Datalist & GT; élément, qui améliore les formulaires en fournissant des suggestions de saisie semi-automatique, en améliorant l'expérience utilisateur et en réduisant les erreurs. COMMANDE COMPRES: 159

L'article traite du HTML & lt; Progress & GT; élément, son but, son style et ses différences par rapport au & lt; mètre & gt; élément. L'objectif principal est de l'utiliser & lt; Progress & gt; pour l'achèvement des tâches et & lt; mètre & gt; pour stati

Cet article explique le html5 & lt; time & gt; élément de représentation sémantique de date / heure. Il souligne l'importance de l'attribut DateTime pour la lisibilité à la machine (format ISO 8601) à côté du texte lisible par l'homme, stimulant AccessIbilit

L'article traite du HTML & lt; mètre & gt; élément, utilisé pour afficher des valeurs scalaires ou fractionnaires dans une plage, et ses applications courantes dans le développement Web. Il différencie & lt; mètre & gt; De & lt; Progress & gt; et ex
