Animation动画详解(七)--ObjectAnimator基本使用_html/css_WEB-ITnose
前言:
假如生活欺骗了你,
不要悲伤,不要心急!
忧郁的日子里须要镇静:
相信吧,快乐的日子终将会来临!
心儿永远向往着未来;
现在却常是忧郁。
一切都是瞬息,一切都将会过去;
而那过去了的,就会成为亲切的怀恋。
—–普希金
相关文章:
1、《Animation 动画详解(一)——alpha、scale、translate、rotate、set的xml属性及用法》
2、《Animation动画详解(二)——Interpolator插值器》
3、《Animation动画详解(三)—— 代码生成alpha、scale、translate、rotate、set及插值器动画》
4、《Animation动画详解(四)——ValueAnimator基本使用》
5、《Animation动画详解(五)——ValueAnimator高级进阶(一)》
6、《Animation动画详解(六)——ValueAnimator高级进阶(二)》
7、《Animation动画详解(七)——ObjectAnimator基本使用》
一、概述
1、引入
上几篇给大家讲了ValueAnimator,但ValueAnimator有个缺点,就是只能对数值对动画计算。我们要想对哪个控件操作,需要监听动画过程,在监听中对控件操作。这样使用起来相比补间动画而言就相对比较麻烦。为了能让动画直接与对应控件相关联,以使我们从监听动画过程中解放出来,谷歌的开发人员在ValueAnimator的基础上,又派生了一个类ObjectAnimator;
由于ObjectAnimator是派生自ValueAnimator的,所以ValueAnimator中所能使用的方法,在ObjectAnimator中都可以正常使用。
但ObjectAnimator也重写了几个方法,比如ofInt(),ofFloat()等。我们先看看利用ObjectAnimator重写的ofFloat方法如何实现一个动画:(改变透明度)
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1);animator.setDuration(2000);animator.start();
我们这里还是直接使用上一篇的框架代码;(当点击start anim时执行动画)从上面的代码中可以看到构造ObjectAnimator的方法非常简单:
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);animator.setDuration(2000);animator.start();
从代码中可以看到,我们只需要改变ofFloat()的第二个参数的值就可以实现对应的动画;
那么问题来了,我们怎么知道第二个参数的值是啥呢?
2、setter函数
我们再回来看构造改变rotation值的ObjectAnimator的方法ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);
//1、透明度:alphapublic void setAlpha(float alpha)//2、旋转度数:rotation、rotationX、rotationYpublic void setRotation(float rotation)public void setRotationX(float rotationX)public void setRotationY(float rotationY)//3、平移:translationX、translationYpublic void setTranslationX(float translationX) public void setTranslationY(float translationY)//缩放:scaleX、scaleYpublic void setScaleX(float scaleX)public void setScaleY(float scaleY)
在开始逐个看这些函数的使用方法前,我们先做一个总结:
1、要使用ObjectAnimator来构造对画,要操作的控件中,必须存在对应的属性的set方法
2、setter 方法的命名必须以骆驼拼写法命名,即set后每个单词首字母大写,其余字母小写,即类似于setPropertyName所对应的属性为propertyName
下面我们就来看一下上面中各个方法的使用方法及作用。
有关alpha的用法,上面已经讲过了,下面我们来看看其它的
(1)、setRotationX、setRotationY与setRotation
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationX",0,270,0);animator.setDuration(2000);animator.start();
效果图如下:
从效果图中明显看出,textview的旋转方法是围绕X轴旋转的,我们设定为从0度旋转到270度再返回0度。
然后再来看看setRotationY的使用方法与效果:
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationY",0,180,0);animator.setDuration(2000);animator.start();
效果图如下:
从效果图中明显可以看出围绕Y轴旋转的。
我们再来看看setRotation的用法与效果:
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,270,0);animator.setDuration(2000);animator.start();
我们上面说了,setRotation是围绕Z轴旋转的,可能有些同学不理解什么是Z轴,我们来看一张图:
从这张图中,绿色框部分表示手机屏幕,很明显可以看出Z轴就是从屏幕左上角原点向外伸出的一条轴。这样,我们也就可以理解围绕Z轴旋转,为什么是这样子转了。
(2)、setTranslationX与setTranslationY
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationX", 0, 200, -200,0);animator.setDuration(2000);animator.start();
所以,我们上面在构造动画时,指定的移动距离是(0, 200, -200,0),所以控件会从自身所有位置向右移动200像素,然后再移动到距离原点-200的位置,最后回到原点;
然后我们来看看setTranslateY的用法:
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationY", 0, 200, -100,0);animator.setDuration(2000);animator.start();
同样,移动位置的坐标也都是以当前控件所在位置为中心点的。所以对应的移动位置从原点移动向下移动200像素,然后再移动到向下到距原点200像素的位置,最后再回到(0,0)从效果图中很明显可以看出来。
从上面可以看出:每次移动距离的计算都是以原点为中心的;比如初始动画为ObjectAnimator.ofFloat(tv, “translationY”, 0, 200, -100,0)表示首先从0移动到正方向200的位置,然后再移动到负方向100的位置,最后移动到原点。
(3)、setScaleX与setScaleY
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleX", 0, 3, 1);animator.setDuration(2000);animator.start();
在效果图中,从0倍放大到3倍,然后再还原到1倍的原始状态。
然后再来看看setScaleY的用法
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);animator.setDuration(2000);animator.start();
源码在文章底部给出
好了,到这里有关View中自带的set函数讲完了,我们来看看ObjectAnimator是如何实现控件动画效果的。3、ObjectAnimator动画原理
我们先来看张图:在这张图中,将ValueAnimator的动画流程与ObjectAnimator的动画流程做了个对比。
可以看到ObjectAnimator的动画流程中,也是首先通过加速器产生当前进度的百分比,然后再经过Evaluator生成对应百分比所对应的数字值。这两步与ValueAnimator是完全一样的,唯一不同的是最后一步,在ValueAnimator中,我们要通过添加监听器来监听当前数字值。而在ObjectAnimator中,则是先根据属性值拼装成对应的set函数的名字,比如这里的scaleY的拼装方法就是将属性的第一个字母强制大写后,与set拼接,所以就是setScaleY。然后通过反射找到对应控件的setScaleY(float scaleY)函数,将当前数字值做为setScaleY(float scale)的参数将其传入。
这里在找到控件的set函数以后,是通过反射来调用这个函数的,有关反射的使用大家可以参考《夯实JAVA基本之二 —— 反射(1):基本类周边信息获取》
这就是ObjectAnimator的流程,最后一步总结起来就是调用对应属性的set方法,将动画当前数字值做为参数传进去。
根据上面的流程,这里有几个注意事项:
(1)、拼接set函数的方法:上面我们也说了是首先是强制将属性的第一个字母大写,然后与set拼接,就是对应的set函数的名字。注意,只是强制将属性的第一个字母大写,后面的部分是保持不变的。反过来,如果我们的函数名命名为setScalePointX(float ),那我们在写属性时可以写成”scalePointX”或者写成“ScalePointX”都是可以的,即第一个字母大小写可以随意,但后面的部分必须与set方法后的大小写保持一致。
(2)、如何确定函数的参数类型:上面我们知道了如何找到对应的函数名,那对应的参数方法的参数类型如何确定呢?我们在讲ValueAnimator的时候说过,动画过程中产生的数字值与构造时传入的值类型是一样的。由于ObjectAnimator与ValueAnimator在插值器和Evaluator这两步是完全一样的,而当前动画数值的产生是在Evaluator这一步产生的,所以ObjectAnimator的动画中产生的数值类型也是与构造时的类型一样的。那么问题来了,像我们的构造方法。
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
那问题来了,如果没有类似setScaleY(float xxx)的函数,我们只实现了一个setScaleY(int xxx)的函数怎么办?这里虽然函数名一样,但参数类型是不一样的,那么系统就会报一个错误:
意思就是对应函数的指定参数类型没有找到。
(3)、调用set函数以后怎么办?从ObjectAnimator的流程可以看到,ObjectAnimator只负责把动画过程中的数值传到对应属性的set函数中就结束了,注意传给set函数以后就结束了!set函数就相当我们在ValueAnimator中添加的监听的作用,set函数中的对控件的操作还是需要我们自己来写的。
那我们来看看View中的setScaleY是怎么实现的吧:
/** * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of * the view's unscaled width. A value of 1 means that no scaling is applied. * * @param scaleY The scaling factor. * @see #getPivotX() * @see #getPivotY() * * @attr ref android.R.styleable#View_scaleY */public void setScaleY(float scaleY) { ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mScaleY != scaleY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); info.mScaleY = scaleY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); }}
所以在重绘时,控件就会根据最新的控件参数来绘制了,所以我们就看到当前控件被缩放了。
(4)、set函数调用频率是多少:由于我们知道动画在进行时,每隔十几毫秒会刷新一次,所以我们的set函数也会每隔十几毫秒会被调用一次。
讲了这么多,就是为了强调一点:ObjectAnimator只负责把当前运动动画的数值传给set函数。至于set函数里面怎么来做,是我们自己的事了。
好了,在知道了ObjectAnimator的原理以后,下面就来看看如何自定义一个ObjectAnimator的属性吧。
二、自定义ObjectAnimator属性
上面我们已经看了使用View自带的set函数所对应属性的方法,而且理解了ObjectAnimator的动画实现原理,下面我们来自定义一个属性来看看实现效果吧。我们在开始之前再来捋一下ObjectAnimator的动画设置流程:ObjectAnimator需要指定操作的控件对象,在开始动画时,到控件类中去寻找设置属性所对应的set函数,然后把动画中间值做为参数传给这个set函数并执行它。
所以,我们说了,控件类中必须所要设置属性所要对应的set函数。所以为了自由控制控件的实现,我们这里自定义一个控件。大家知道在这个自定义控件中,肯定存在一个set函数与我们自定义的属性相对应。
我们先来看看这段要实现的效果:
这个效果图与我们上篇自定义控件实现的效果差不多,这个控件中存在一个圆形,也是在动画时先将这个圆形放大,然后再将圆形还原。
1、保存圆形信息类——Point
为了,保存圆形的信息,我们先定义一个类:(Point.java)public class Point { private int mRadius; public Point(int radius){ mRadius = radius; } public int getRadius() { return mRadius; } public void setRadius(int radius) { mRadius = radius; }}
2、自定义控件——MyPointView
然后我们自定义一个控件MyPointView,完整代码如下:public class MyPointView extends View { private Point mPoint = new Point(100); public MyPointView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { if (mPoint != null){ Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(300,300,mPoint.getRadius(),paint); } super.onDraw(canvas); } void setPointRadius(int radius){ mPoint.setRadius(radius); invalidate(); }}
void setPointRadius(int radius){ mPoint.setRadius(radius); invalidate();}
第二点,在setPointRadius中,先将当前动画传过来的值保存到mPoint中,做为当前圆形的半径。然后强制界面刷新
在界面刷新后,就开始执行onDraw()函数:
@Overrideprotected void onDraw(Canvas canvas) { if (mPoint != null){ Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(300,300,mPoint.getRadius(),paint); } super.onDraw(canvas);}
3、使用MyPointView
首先,在MyActivity的布局中添加MyPointView的使用(main.xml):<?xml version="1.0" encoding="utf-8"?><relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:padding="10dp" android:text="start anim"></button> <button android:id="@+id/btn_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentright="true" android:padding="10dp" android:text="cancel anim"></button> <textview android:id="@+id/tv" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:gravity="center" android:padding="10dp" android:background="#ffff00" android:text="Hello qijian"></textview> <com.example.blogobjectanimator1.mypointview android:id="@+id/pointview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tv"></com.example.blogobjectanimator1.mypointview></relativelayout>
然后看看在MyActivity中,点击start anim后的处理方法:
public class MyActivity extends Activity { private Button btnStart; private MyPointView mPointView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnStart = (Button) findViewById(R.id.btn); mPointView = (MyPointView)findViewById(R.id.pointview); btnStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doPointViewAnimation(); } }); } …………}
private void doPointViewAnimation(){ ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius", 0, 300, 100); animator.setDuration(2000); animator.start();}
所以在动画开始以后,ObjectAnimator就会实时地把动画中产生的值做为参数传给MyPointView类中的setPointRadius(int radius)函数,然后调用setPointRadius(int radius)。由于我们在setPointRadius(int radius)中实时地设置圆形的半径值然后强制重绘当前界面,所以可以看到圆形的半径会随着动画的进行而改变。
源码在文章底部给出
三、常用函数
有关常用函数这一节其实没有太多讲的必要。因为ObjectAnimator的函数都是从ValueAnimator中继承而来的,所以用法和效果与ValueAnimator是完全一样的。我们这里只讲解一下Evaluator的用法,其它的也就不再讲了。1、使用ArgbEvaluator
我们搜一下TextView所有的函数发现,TextView有一个set函数能够改变背景色:public void setBackgroundColor(int color);
public class ArgbEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { int startInt = (Integer) startValue; int startA = (startInt >> 24); int startR = (startInt >> 16) & 0xff; int startG = (startInt >> 8) & 0xff; int startB = startInt & 0xff; int endInt = (Integer) endValue; int endA = (endInt >> 24); int endR = (endInt >> 16) & 0xff; int endG = (endInt >> 8) & 0xff; int endB = endInt & 0xff; return (int)((startA + (int)(fraction * (endA - startA))) 有关它具体实现的原理,前面篇章中我们已经讲过了,这里主要说一点,ArgbEvaluator的返回值是Integer类型,所以我们要使用ArgbEvaluator的话,构造ObjectAnimator时必须使用ofInt() <br>下面我们来看看使用ArgbEvaluator的代码: <br> <pre name="code" class="sycode">ObjectAnimator animator = ObjectAnimator.ofInt(tv, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);animator.setDuration(8000);animator.setEvaluator(new ArgbEvaluator());animator.start();
源码在文章底部给出
2、其它函数
下面把其它所涉及到的函数的列表列在下面,大家可以参考ValueAnimator的使用方法来使用。有关自定义插值器和Evaluator的部分,可以参考 《Animation动画详解(五)——高级进阶(一)》(1)、常用函数
/** * 设置动画时长,单位是毫秒 */ValueAnimator setDuration(long duration)/** * 获取ValueAnimator在运动时,当前运动点的值 */Object getAnimatedValue();/** * 开始动画 */void start()/** * 设置循环次数,设置为INFINITE表示无限循环 */void setRepeatCount(int value)/** * 设置循环模式 * value取值有RESTART,REVERSE, */void setRepeatMode(int value)/** * 取消动画 */void cancel()
(2)、监听器相关
/** * 监听器一:监听动画变化时的实时值 */public static interface AnimatorUpdateListener { void onAnimationUpdate(ValueAnimator animation);}//添加方法为:public void addUpdateListener(AnimatorUpdateListener listener)/** * 监听器二:监听动画变化时四个状态 */public static interface AnimatorListener { void onAnimationStart(Animator animation); void onAnimationEnd(Animator animation); void onAnimationCancel(Animator animation); void onAnimationRepeat(Animator animation);}//添加方法为:public void addListener(AnimatorListener listener)
(3)、插值器与Evaluator
/** * 设置插值器 */public void setInterpolator(TimeInterpolator value)/** * 设置Evaluator */public void setEvaluator(TypeEvaluator value)
如果本文有帮到你,记得加关注哦
源码下载地址:
csdn:
github:
请大家尊重原创者版权,转载请标明出处,谢谢

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
