アニメーションアニメーションの詳細解説(5) ~ValueAnimatorの高度な進化(1)_html/css_WEB-ITnose
はじめに: 現実的であることによってのみ、私たちは多くのことを積み上げることができます。未来は、夢に向かって努力する人だけが持っています。
前回の記事では ValueAnimator のほとんどの機能の使い方を紹介しましたが、それでも簡単な使い方を今回はアクセラレータ、アニメーター、キーフレームについての知識を見ていきます。
1. インターポレーター
インターポレーター、アクセラレーターとも呼ばれます。インターポレーターの知識については、「アニメーションの詳細な説明 (2) - インターポレーター」で詳しく説明しています。まずこの記事をご覧ください。それぞれのアクセル。ここでインターポレーターとは何かについて話しましょう。 ofInt(0,400) を通じてアニメーション範囲値を 0 ~ 400 に定義し、アニメーションのリアルタイムの変化を監視する AnimatorUpdateListener を追加することがわかります。そこで問題は、0 ~ 400 の値がどのように変化するかということです。自転車に乗るときのように、速い人もいれば遅い人もいますが、この値は一定の速度で変化しますか?その場合、最初に加速してから減速したい場合はどうすればよいですか?
これがインターポレーターの目的です!補間器は、アニメーション間隔の値の計算方法を制御するために使用されます。たとえば、LinearInterpolator 補間器は一定の速度で間隔ポイントの値を返しますが、DecelerateInterpolator は最初の変化が速く、後の変化が遅いことを意味します。他の関数の適用方法を見てみましょう。 ValueAnimator の interpolator をカスタマイズして確認してください。interpolator とは何かを確認してください。
1. インターポレーターを使用する
BounceInterpolator を例として使用して、その効果を見てみましょう。 ValueAnimator を使用して実装される方法を見てください。レイアウトは前の記事と同じなので、ここでは詳しく説明しません。コードは次のとおりです。ValueAnimator animator = ValueAnimator.ofInt(0,600);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight()); }});animator.setDuration(1000);animator.setInterpolator(new BounceInterpolator());animator.start();
レンダリングからわかるように、インターポレーターの意味は次のとおりです。実際には物理式の加速度パラメータに相当するため、加速器とも呼ばれます。
ソースコードは記事の下部にあります
アクセラレータの使用方法を学んだ後、アクセラレータをカスタマイズする方法を見てみましょう
2. カスタムアクセラレータ
概要
このセクションでは、始めます。私はアクセラレーターを作成しています。アクセラレーターを作成する前に、他の人のアクセラレーターがどのように作成されているかを見てみましょう。
まず LinearInterpolator を見てみましょう:public class LinearInterpolator implements Interpolator { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; }}public interface Interpolator extends TimeInterpolator {}
次に、TimeInterpolator インターフェイスの関数を見てみましょう:
/** * A time interpolator defines the rate of change of an animation. This allows animations * to have non-linear motion, such as acceleration and deceleration. */public interface TimeInterpolator { /** * Maps a value representing the elapsed fraction of an animation to a value that represents * the interpolated fraction. This interpolated value is then multiplied by the change in * value of an animation to derive the animated value at the current elapsed animation time. * * @param input A value between 0 and 1.0 indicating our current point * in the animation where 0 represents the start and 1.0 represents * the end * @return The interpolation value. This value can be more than 1.0 for * interpolators which overshoot their targets, or less than 0 for * interpolators that undershoot their targets. */ float getInterpolation(float input);}
パラメータ入力: 入力パラメータはfloat型で、現在のアニメーションの進行状況を表します。0の場合はアニメーションが開始されたばかりです。 0.5 の場合はアニメーションの途中を意味します。
戻り値: 表示したい現在の実際の進行状況を示します。値は 1 より大きいか 0 より小さいことができます。1 より大きい場合はターゲット値を超えていることを意味し、0 より小さい場合は開始位置より小さいことを意味します。 入力パラメータの場合、現在のアニメーションの進行状況を表し、一定の速度で増加します。アニメーションの進行状況とは何ですか? アニメーションの進行状況は、時間の経過とともに、入力パラメーターとは何の関係もありません。 setDuration() を通じてアニメーションの継続時間を指定します。これは、曲を再生するときと同じです。 0から1まで同じです。
戻り値はアニメーションの進行状況を数値で表し、対応する数値範囲は ofInt() と ofFloat() で指定されます。
まず次のコードを見てみましょう:
ValueAnimator anim = ValueAnimator.ofInt(100, 400); anim.setDuration(1000); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); Log.d("TAG", "cuurent value is " + currentValue); } }); anim.start();
現在の値はどのように取得されるのか。どうですか?以下の計算式を参照してください: (これは現在の理解です。実際の状況は後で詳しく説明します)
現在値 = 100 + (400 - 100) * 進捗状況を表示します
このうち、100 と 400 は値ですofInt(100,400) に設定します。この式は比較的理解しやすいはずです。これは文章題を行うのと同じです。
Xiao Ming は 100 の位置から開始し、400 の位置まで実行します。20% に達すると、合計距離のうち、シャオミンは何点で優れていますか?
現在の値 = 100 + (400 -100) * 0.2;
非常に単純なアプリケーションの質問ですが、これが ofInt() の AnimatorUpdateListener の現在の値の由来です。ここから、進行状況の表示が現在の値の位置を示していることがわかります。ただし、getInterpolation() の戻り値を指定することで現在表示されている値の進行状況を指定できるため、時間が経過しても値を任意の場所に置くことができます。
繰り返しますが、入力パラメータは設定した値とは何の関係もありません。時間が増加するにつれて、入力パラメータは現在のアニメーションの進行状況を表します。戻り値はアニメーションの現在の進行状況を数値で表します。上記のことから、LinearInterpolator が TimeInterpolator を書き換える方法を見てみましょう。上記、LinearInterpolator getInterpolation 関数では、入力値が直接返されます。つまり、現在のアニメーションの進行状況がアニメーションの数値的な進行状況として使用されます。これは、現在のアニメーションの数値的な進行状況がアニメーションの進行状況と一致していることも意味します。アニメーションの進行時間。たとえば、現在のアニメーションの進行状況が 0 の場合、アニメーションの進行状況の数値も 0.5 の場合、アニメーションが終了するときのアニメーションの進行状況の数値も 0.5 になります。 、アニメーションの進行状況が 1 になり、アニメーションの数値的な進行状況も 1 になります。
例を使用して補間器をカスタマイズする方法を説明しましょう。
2. 例
上記の説明からわかるように、補間器をカスタマイズするには、TimeInterpolator インターフェイスを実装するだけで済みます。
public class LinearInterpolator implements Interpolator { ………… public float getInterpolation(float input) { return input; }}
その後、補間器を使用します:
ValueAnimator animator = ValueAnimator.ofInt(0,600);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight()); }});animator.setDuration(1000);animator.setInterpolator(new MyInterploator());animator.start();
从效果图中可见,我们将数值进度倒序返回——即随着动画进度的推进,动画的数值进度从结束位置进行到起始位置;
到这里,想必大家应该已经理解了getInterpolation(float input)函数中input参数与返回值的关系,在重写插值器时,需要强有力的数学知识做基础,一般而言,都是通过数学公式来计算插值器的变化趋势的,大家可以再分析分析其它几个插值器的写法;可以把它他们总结成公式,放到公式画图软件里,看看对应的数学图在(0,1)之间的走向,这个走向就是插值器在数值变化时的样子。
源码在文章底部给出
二、Evaluator
1、概述
我们先不讲什么是Evaluator,我们先来看一张图:这幅图讲述了从定义动画的数字区间到通过AnimatorUpdateListener中得到当前动画所对应数值的整个过程。下面我们对这四个步骤具体讲解一下:
(1)、ofInt(0,400)表示指定动画的数字区间,是从0运动到400;
(2)、加速器:上面我们讲了,在动画开始后,通过加速器会返回当前动画进度所对应的数字进度,但这个数字进度是百分制的,以小数表示,如0.2
(3)、Evaluator:我们知道我们通过监听器拿到的是当前动画所对应的具体数值,而不是百分制的进度。那么就必须有一个地方会根据当前的数字进度,将其转化为对应的数值,这个地方就是Evaluator;Evaluator就是将从加速器返回的数字进度转成对应的数字值。所以上部分中,我们讲到的公式:
当前的值 = 100 + (400 - 100)* 显示进度
(4)、监听器:我们通过在AnimatorUpdateListener监听器使用animation.getAnimatedValue()函数拿到Evaluator中返回的数字值。
讲了这么多, Evaluator其实就是一个转换器,他能把小数进度转换成对应的数值位置
2、各种Evaluator
首先,加速器返回的小数值,表示的是当前动画的数值进度。无论是利用ofFloat()还是利用ofInt()定义的动画都是适用的。因为无论是什么动画,它的进度必然都是在0到1之间的。0表示没开始,1表示数值运动的结束,对于任何动画都是适用的。但Evaluator则不一样,我们知道Evaluator是根据加速器返回的小数进度转换成当前数值进度所对应的值。这问题就来了,如果我们使用ofInt()来定义动画,动画中的值应该都是Int类型,如果我用ofFloat()来定义动画,那么动画中的值也都是Float类型。所以如果我用ofInt()来定义动画,所对应的Evaluator在返回值时,必然要返回Int类型的值。同样,我们如果用ofFloat来定义动画,那么Evaluator在返回值时也必然返回的是Float类型的值。
所以每种定义方式所对应的Evaluator必然是它专用的;Evaluator专用的原因在于动画数值类型不一样,在通过Evaluator返回时会报强转错误;所以只有在动画数值类型一样时,所对应的Evaluator才能通用。所以ofInt()对应的Evaluator类名叫IntEvaluator,而ofFloat()对应的Evaluator类名叫FloatEvaluator;
在设置Evaluator时,是通过animator.setEvaluator()来设置的,比如:
ValueAnimator animator = ValueAnimator.ofInt(0,600);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight()); }});animator.setDuration(1000);animator.setEvaluator(new IntEvaluator());animator.setInterpolator(new BounceInterpolator());animator.start();
上面,我们已经弄清楚Evaluator定义和使用方法,下面我们就来看看IntEvaluator内部是怎么实现的吧:
/** * This evaluator can be used to perform type interpolation between <code>int</code> values. */public class IntEvaluator implements TypeEvaluator<Integer> { /** * This function returns the result of linearly interpolating the start and end values, with * <code>fraction</code> representing the proportion between the start and end values. The * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>, * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>, * and <code>t</code> is <code>fraction</code>. * * @param fraction The fraction from the starting to the ending values * @param startValue The start value; should be of type <code>int</code> or * <code>Integer</code> * @param endValue The end value; should be of type <code>int</code> or <code>Integer</code> * @return A linear interpolation between the start and end values, given the * <code>fraction</code> parameter. */ public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(startInt + fraction * (endValue - startInt)); }}
其中fraction就是加速器中的返回值,表示当前动画的数值进度,百分制的小数表示。
startValue和endValue分别对应ofInt(int start,int end)中的start和end的数值;
比如我们假设当我们定义的动画ofInt(100,400)进行到数值进度20%的时候,那么此时在evaluate函数中,fraction的值就是0.2,startValue的值是100,endValue的值是400;理解上应该没什么难度。
下面我们就来看看evaluate(float fraction, Integer startValue, Integer endValue) 是如何根据进度小数值来计算出具体数字的:
return (int)(startInt + fraction * (endValue - startInt));
当前的值 = 100 + (400 - 100)* 显示进度
在我们看懂了IntEvalutor以后,下面我们尝试自己写一个Evalutor
3、自定义Evalutor
(1)、简单实现MyEvalutor
前面我们看了IntEvalutor的代码,我们仿照IntEvalutor的实现方法,我们自定义一个MyEvalutor:首先是实现TypeEvaluator接口:
public class MyEvaluator implements TypeEvaluator<Integer> { @Override public Integer evaluate(float fraction, Integer startValue, Integer endValue) { return null; }}
在实现TypeEvaluator,我们给它指定它的返回是Integer类型,这样我们就可以在ofInt()中使用这个Evaluator了。再说一遍原因:只有定义动画时的数值类型与Evalutor的返回值类型一样时,才能使用这个Evalutor;很显然ofInt()定义的数值类型是Integer而我们定义的MyEvaluator,它的返回值类型也是Integer;所以我们定义的MyEvaluator可以给ofInt()来用。同理,如果我们把实现的TypeEvaluator填充为为Float类型,那么这个Evalutor也就只能给FloatEvalutor用了。
屁话了那么多,现在转入正题,我们来简单实现evaluate函数,代码如下:
public class MyEvaluator implements TypeEvaluator<Integer> { @Override public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(200+startInt + fraction * (endValue - startInt)); }}
我们看看MyEvaluator的使用:
ValueAnimator animator = ValueAnimator.ofInt(0,400);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight()); }});animator.setDuration(1000);animator.setEvaluator(new MyEvaluator());animator.start();
然后再看看我们设置了MyEvaluator以后的效果:
很明显,textview的动画位置都向下移动了200个点;
再重新看一下下面的这个流程图:
在加速器中,我们可以通过自定义加速器的返回的数值进度来改变返回数值的位置。比如上面我们实现的倒序动画
在Evaluator中,我们又可以通过改变进度值所对应的具体数字来改变数值的位置。
所以,结论来了:
我们可以通过重写加速器改变数值进度来改变数值位置,也可以通过改变Evaluator中进度所对应的数值来改变数值位置。
源码在文章底部给出
下面我们就只通过重写Evaluator来实现数值的倒序输出;(2)、实现倒序输出实例
我们自定义一个ReverseEvaluator:public class ReverseEvaluator implements TypeEvaluator<Integer> { @Override public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int) (endValue - fraction * (endValue - startInt)); }}
使用方法:
ValueAnimator animator = ValueAnimator.ofInt(0,400);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight()); }});animator.setDuration(1000);animator.setEvaluator(new ReverseEvaluator());animator.start();
源码在文章底部给出
4、关于ArgbEvalutor
1、使用ArgbEvalutor
我们上面讲了IntEvaluator和FloatEvalutor,还说了Evalutor一般来讲不能通用,会报强转错误,也就是说,只有在数值类型相同的情况下,Evalutor才能共用。其实除了IntEvaluator和FloatEvalutor,在android.animation包下,还有另外一个Evalutor叫ArgbEvalutor。
ArgbEvalutor是用来做颜色值过渡转换的。可能是谷歌的开发人员觉得大家对颜色值变换可能并不知道要怎么做,所以特地给我们提供了这么一个过渡Evalutor;
我们先来简单看一下ArgbEvalutor的源码:(这里先不做具体讲解原理,最后会讲原理,这里先会用)
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))) << 24) | (int)((startR + (int)(fraction * (endR - startR))) << 16) | (int)((startG + (int)(fraction * (endG - startG))) << 8) | (int)((startB + (int)(fraction * (endB - startB)))); }}
下面我们就使用一下ArgbEvaluator,并看看效果:
ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff);animator.setEvaluator(new ArgbEvaluator());animator.setDuration(3000);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); tv.setBackgroundColor(curValue); }});animator.start();
在监听中,我们根据当前传回来的颜色值,将其设置为textview的背景色
我们来看一下效果:
源码在文章底部给出
到这里,我们就已经知道ArgbEvalutor的使用方法和效果了,下面我们再来回头看看ArgbEvalutor的实现方法2、ArgbEvalutor的实现原理
先重新看源码:/** * This evaluator can be used to perform type interpolation between integer * values that represent ARGB colors. */public class ArgbEvaluator implements TypeEvaluator { /** * This function returns the calculated in-between value for a color * given integers that represent the start and end values in the four * bytes of the 32-bit int. Each channel is separately linearly interpolated * and the resulting calculated values are recombined into the return value. * * @param fraction The fraction from the starting to the ending values * @param startValue A 32-bit int value representing colors in the * separate bytes of the parameter * @param endValue A 32-bit int value representing colors in the * separate bytes of the parameter * @return A value that is calculated to be the linearly interpolated * result, derived by separating the start and end values into separate * color channels and interpolating each one separately, recombining the * resulting values in the same way. */ 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))) << 24) | (int)((startR + (int)(fraction * (endR - startR))) << 16) | (int)((startG + (int)(fraction * (endG - startG))) << 8) | (int)((startB + (int)(fraction * (endB - startB)))); }}
这段代码分为三部分,第一部分根据startValue求出其中A,R,G,B中各个色彩的初始值;第二部分根据endValue求出其中A,R,G,B中各个色彩的结束值,最后是根据当前动画的百分比进度求出对应的数值
我们先来看第一部分:根据startValue求出其中A,R,G,B中各个色彩的初始值
int startInt = (Integer) startValue;int startA = (startInt >> 24);int startR = (startInt >> 16) & 0xff;int startG = (startInt >> 8) & 0xff;int startB = startInt & 0xff;
所以我们的初始值是0xffffff00,那么求出来的startA = 0xff,startR = oxff,startG = 0xff,startB = 0x00;
关于通过位移和与运算如何得到指定位的值的问题,我就不再讲了,大家如果不理解,可以搜一下相关运算符使用方法的文章。
同样,我们看看第二部分根据endValue求出其中A,R,G,B中各个色彩的结束值:
int endInt = (Integer) endValue;int endA = (endInt >> 24);int endR = (endInt >> 16) & 0xff;int endG = (endInt >> 8) & 0xff;int endB = endInt & 0xff;
最后一部分到了,就是如何根据进度来求得变化的值,我们先看看下面这句是什么意思:
startA + (int)(fraction * (endA - startA)))
同理
startR + (int)(fraction * (endR - startR)表示当前进度下的红色值
startG + (int)(fraction * (endG - startG))表示当前进度下的绿色值
startB + (int)(fraction * (endB - startB))表示当前进度下的蓝色值
然后通过位移和或运算将当前进度下的A,R,G,B组合起来就是当前的颜色值了。
好了,到这里,有关加速器和Evaluator的知识就讲完了,对于ValueAnimator还有一些知识没来得及讲,这篇文章已经很长了,就另开一篇来讲解吧
如果本文有帮到你,记得加关注哦
源码下载地址:
请大家尊重原创者版权,转载请标明出处: 谢谢

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











HTMLは、簡単に学習しやすく、結果をすばやく見ることができるため、初心者に適しています。 1)HTMLの学習曲線はスムーズで簡単に開始できます。 2)基本タグをマスターして、Webページの作成を開始します。 3)柔軟性が高く、CSSおよびJavaScriptと組み合わせて使用できます。 4)豊富な学習リソースと最新のツールは、学習プロセスをサポートしています。

HTMLはWeb構造を定義し、CSSはスタイルとレイアウトを担当し、JavaScriptは動的な相互作用を提供します。 3人はWeb開発で職務を遂行し、共同でカラフルなWebサイトを構築します。

webdevelopmentReliesOnhtml、css、andjavascript:1)htmlStructuresContent、2)cssStylesit、および3)Javascriptaddsinteractivity、形成、

Anexampleapalofastartingtaginhtmlis、それはaperginsaparagraph.startingtagsaresentionentientiontheyinitiateelements、definetheirtypes、およびarecrucialforurturingwebpagesandcontingthomedomを構築します。

GiteEpages静的Webサイトの展開が失敗しました:404エラーのトラブルシューティングと解像度Giteeを使用する

Y軸位置Webアノテーション機能の適応アルゴリズムこの記事では、単語文書と同様の注釈関数、特に注釈間の間隔を扱う方法を実装する方法を探ります...

HTML、CSS、およびJavaScriptは、Web開発の3つの柱です。 1。HTMLは、Webページ構造を定義し、などなどのタグを使用します。2。CSSは、色、フォントサイズなどのセレクターと属性を使用してWebページスタイルを制御します。

画像をクリックした後、散乱と周囲の画像を拡大する効果を実現するには、多くのWebデザインがインタラクティブな効果を実現する必要があります。特定の画像をクリックして周囲を作成してください...
