真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Android動(dòng)畫教程之屬性動(dòng)畫詳解

簡介

成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),鷹手營子企業(yè)網(wǎng)站建設(shè),鷹手營子品牌網(wǎng)站建設(shè),網(wǎng)站定制,鷹手營子網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,鷹手營子網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

Android 開發(fā)中,總是需要一些動(dòng)畫來優(yōu)化用戶的交互體驗(yàn),提高用戶滿意度。因此,Google 為我們提供了一些用于處理動(dòng)畫效果的動(dòng)畫框架。Android 的動(dòng)畫框架分為兩類:

  • 傳統(tǒng)動(dòng)畫(Animation):通過系統(tǒng)不斷調(diào)用onDraw方法重繪界面,來達(dá)到動(dòng)畫的效果。
  • 屬性動(dòng)畫(Animator):通過操縱一個(gè)屬性的get/set方法,真實(shí)地改變目標(biāo)的某些屬性。

傳統(tǒng)動(dòng)畫框架的局限性

既然有了傳統(tǒng)動(dòng)畫框架,Google 為什么還要?jiǎng)?chuàng)造一個(gè)屬性動(dòng)畫框架呢?

我們下面舉個(gè)例子來說明一下傳統(tǒng)動(dòng)畫的局限性。

在布局中加入一個(gè) ImageView 和一個(gè) Button,點(diǎn)擊 ImageView 后彈出一個(gè) Toast,點(diǎn)擊 Button 后使 ImageView 展現(xiàn)一個(gè)向右平移的動(dòng)畫效果。

下面是使用傳統(tǒng)動(dòng)畫實(shí)現(xiàn)的代碼:

TranslateAnimation animation = new TranslateAnimation(0,200,0,0); // 平移動(dòng)畫x軸移動(dòng)200,y軸不動(dòng)
animation.setDuration(1000); // 動(dòng)畫時(shí)長
animation.setFillAfter(true); // 使動(dòng)畫結(jié)束后停留在結(jié)束的位置
mIvPicture.startAnimation(animation);

運(yùn)行后,ImageView 確實(shí)進(jìn)行了我們預(yù)期的平移的效果。可是當(dāng)我們嘗試點(diǎn)擊 ImageView 當(dāng)前的位置時(shí),卻沒有 Toast 彈出。我們再嘗試去點(diǎn)擊 ImageView 開始動(dòng)畫前的位置,卻成功彈出了 Toast。

這就是傳統(tǒng)動(dòng)畫很大的局限性:

  • 它僅僅是重繪了控件,改變了其顯示的位置。但真正事件響應(yīng)的位置,卻并沒有發(fā)生改變。因此傳統(tǒng)動(dòng)畫不適合做具有交互的動(dòng)畫效果。僅僅能做一些顯示的動(dòng)畫效果。
  • 傳統(tǒng)動(dòng)畫是不斷通過 onDraw() 方法重繪界面,必然會(huì)十分耗費(fèi)GPU資源。
  • 傳統(tǒng)動(dòng)畫所支持的動(dòng)畫類型少,僅有旋轉(zhuǎn)、縮放、位移、透明度這四種動(dòng)畫效果。雖然通過組合可以實(shí)現(xiàn)豐富的效果,但相比直接通過改變屬性來實(shí)現(xiàn)的屬性動(dòng)畫來說,還是有很大的局限性的。

因此,Google 為我們提供了一套全新的屬性動(dòng)畫框架,來讓我們實(shí)現(xiàn)更豐富的動(dòng)畫效果。

ObjectAnimator

ObjectAnimator 是屬性動(dòng)畫中,最簡單也最常用的一個(gè)對象。

實(shí)現(xiàn) Animation 框架的功能

平移

前文提到的使 ImageVIew 向右平移 200 像素的動(dòng)畫效果,使用屬性動(dòng)畫只需要很簡單的幾句代碼即可實(shí)現(xiàn):

ObjectAnimator.ofFloat(mIvPicture,"translationX",0F,200F)
 .setDuration(1000)
 .start();

我們來分析一下這一句代碼。我們調(diào)用了ofFloat代碼,并傳入三個(gè)參數(shù)。

​ 第一個(gè)參數(shù)是動(dòng)畫需要操縱的目標(biāo),在這里是我們的 ImageView。

​ 第二個(gè)參數(shù)是所需要操縱的目標(biāo)所具備的屬性名稱。

​ 第三個(gè)參數(shù)是這個(gè)動(dòng)畫變化的取值范圍。

最后設(shè)置一下它的動(dòng)畫的屬性,便可以 start 了。

這次我們再次點(diǎn)擊 ImageView 目前的位置,成功地彈出了 Toast。這證實(shí)了屬性動(dòng)畫是通過改變物體的屬性來達(dá)到動(dòng)畫效果的理論。

當(dāng)我們需要改變 y 坐標(biāo)時(shí),只需要把 "translationX" 變?yōu)?"translationY" 即可。

其實(shí) ,只要Google對一個(gè)對象的某個(gè)屬性提供了get和set方法,我們就可以使用這個(gè)屬性來實(shí)現(xiàn)動(dòng)畫效果。

其實(shí)我們還能用 X Y 兩個(gè)屬性實(shí)現(xiàn)之前的動(dòng)畫效果,那么對象屬性中 X 的 Y 與 translationX translationY 有什么區(qū)別呢?

translationX translationY指的是物體的偏移量,而X Y則表示它最終到達(dá)的絕對位置。

旋轉(zhuǎn)

旋轉(zhuǎn)屬性使用的是 "rotation" 屬性,后面的變換范圍的單位是角度。

比如想讓 ImageView 旋轉(zhuǎn)90度,只需要

ObjectAnimator.ofFloat(mIvPicture,"rotation",0F,90F)
 .setDuration(1000)
 .start();

其他

其實(shí)屬性動(dòng)畫能操縱的屬性,只要具有 set、get 方法,都可以進(jìn)行操縱。如 scaleX、scaleY 等等...

插值器

Android 為我們內(nèi)置了插值器,使我們的動(dòng)畫更為自然。比如可以讓我們的平移動(dòng)畫像物體的重力加速度由快到慢的 Accelerate 等等

Android中內(nèi)置了七種插值器,分別是

  • Accelerate
  • Decelerate
  • Accelerate/Decelerate
  • Anticipate
  • Overshoot
  • Anticipate/Overshoot
  • Bounce

要應(yīng)用插值器,可以調(diào)用 ObjectAnimator 的 setInterpolator 方法, new 出對應(yīng)的插值器作為參數(shù)(xxxInterpolator)。比如下面這段代碼:

animator.setInterpolator(new AccelerateInterpolator());

通過插值器,我們可以讓動(dòng)畫的效果更佳自然。

多種屬性動(dòng)畫同時(shí)作用

當(dāng)我們把幾種動(dòng)畫按順序?qū)懴聲r(shí),運(yùn)行程序,會(huì)發(fā)現(xiàn)效果是三種屬性動(dòng)畫的疊加。由此可以發(fā)現(xiàn),屬性動(dòng)畫在調(diào)用 start 方法后,實(shí)際上是一個(gè)異步的過程。因此我們就可以看到三個(gè)屬性動(dòng)畫同時(shí)作用的效果。通過這樣的方法,其實(shí)就可以實(shí)現(xiàn)多種屬性動(dòng)畫同時(shí)作用的效果:

ObjectAnimator.ofFloat(mIvPicture,"translationX",0F,200F).setDuration(1000).start();
ObjectAnimator.ofFloat(mIvPicture,"rotationX",0F,360F).setDuration(1000).start();
ObjectAnimator.ofFloat(mIvPicture,"translationY",0F,200F).setDuration(1000).start();

其實(shí) Google 為我們提供了更好的方法,來實(shí)現(xiàn)這樣的效果。

我們可以使用 PropertyValuesHolder 來實(shí)現(xiàn)。其構(gòu)造函數(shù)僅僅比 ObjectAnimator 少了一個(gè)作用對象參數(shù)。之后通過ObjectAnimator 的 ofPropertyValuesHolder 方法,傳入作用對象以及要同時(shí)作用的 PropertyValuesHolder 即可執(zhí)行。可以看到下面的代碼示例:

PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX",0F,200F);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("rotationX",0F,360F);
PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("translationY",0F,200F);
ObjectAnimator.ofPropertyValuesHolder(mIvPicture,p1,p2,p3).setDuration(1000).start();

運(yùn)行后可以發(fā)現(xiàn),與之前的效果是相同的。

那既然兩種方法效果一樣,這樣相比之前有什么好處么?

  • 其實(shí) Google 在 PropertyValuesHolder 內(nèi)部進(jìn)行了一些優(yōu)化,使得我們使用多個(gè)屬性動(dòng)畫時(shí)更加有效率,節(jié)省系統(tǒng)資源。

AnimatorSet 屬性集合

playTogether 方法

我們其實(shí)還可以通過 AnimatorSet,來實(shí)現(xiàn)同樣的效果。這里我們調(diào)用了 set 的 playTogether 方法,使得這些方法同時(shí)執(zhí)行:

AnimatorSet set = new AnimatorSet();
ObjectAnimator animator1 = ObjectAnimator.ofFloat(mIvPicture, "translationX", 0F, 200F);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(mIvPicture, "rotationX", 0F, 360F);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(mIvPicture, "translationY", 0F, 200F);
set.playTogether(animator1,animator2,animator3);
set.setDuration(1000);
set.start();

playSequentially方法

除了 playTogether 方法外,AnimatorSet 還提供了 playSequentially 方法,它可以使得動(dòng)畫按順序執(zhí)行。具體順序取決于調(diào)用時(shí)的參數(shù)順序。

AnimatorSet set = new AnimatorSet();
ObjectAnimator animator1 = ObjectAnimator.ofFloat(mIvPicture, "translationX", 0F, 200F);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(mIvPicture, "rotationX", 0F, 360F);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(mIvPicture, "translationY", 0F, 200F);
set.playSequentially(animator1,animator2,animator3);
set.setDuration(1000);
set.start();

play 與 with、after 方法

我們除了可以用上述方法來讓動(dòng)畫按順序執(zhí)行外,也可以通過 AnimatorSet 的 play、with、after、before 等方法相組合來控制動(dòng)畫播放關(guān)系。

例如如下的代碼就可以實(shí)現(xiàn)先平移,再旋轉(zhuǎn)的效果

set.play(animator1).with(animator3);
set.play(animator2).after(animator1);

動(dòng)畫監(jiān)聽事件

通過下面的代碼,我們可以實(shí)現(xiàn)按鈕按下后漸隱的效果。

mBtnPress.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
  ObjectAnimator animator = ObjectAnimator.ofFloat(mBtnPress,"alpha",1F,0F);
  animator.setDuration(1000);
  animator.start();
 }
});

但如果我們想要在動(dòng)畫播放完成后再執(zhí)行一些操作的話,又該如何實(shí)現(xiàn)呢?

  • 我們可以使用 ObjectAnimator 的 addListener方法,傳入一個(gè)AnimatorListener,為動(dòng)畫設(shè)置監(jiān)聽事件。

AnimatorListener

一個(gè)AnimatorListener,需要實(shí)現(xiàn)四個(gè)方法,分別是:

  • onAnimationStart
  • onAnimationEnd
  • onAnimationCancel
  • onAnimationRepeat

它們的回調(diào)時(shí)機(jī)我們根據(jù)字面意思便可以理解。大部分時(shí)候,我們需要實(shí)現(xiàn)的是onAnimationEnd方法。

animator.addListener(new AnimatorListener() {
 @Override
 public void onAnimationStart(Animator animation) {
 }
 @Override
 public void onAnimationEnd(Animator animation) {
  Toast.makeText(MainActivity.this,"Animation End",Toast.LENGTH_SHORT).show();
 }
 @Override
 public void onAnimationCancel(Animator animation) {
 }
 @Override
 public void onAnimationRepeat(Animator animation) {
 }
});

AnimatorListenerAdapter

如果每次監(jiān)聽都需要實(shí)現(xiàn)這么多方法,未免太麻煩了一點(diǎn)。因此 Android 為我們提供了另一種方法來添加動(dòng)畫的監(jiān)聽事件:在添加 AnimatorListener 的時(shí)候,傳入 AnimatorListenerAdapter 即可。這樣我們就只需要實(shí)現(xiàn)自己需要的方法即可。

animator.addListener(new AnimatorListenerAdapter() {
 @Override
 public void onAnimationEnd(Animator animation) {
  super.onAnimationEnd(animation);
  Toast.makeText(MainActivity.this,"Animation End",Toast.LENGTH_SHORT).show();
 }
});

ValueAnimator

簡介

ValueAnimator 本身不作用于任何一個(gè)屬性,也不提供任何一種動(dòng)畫。它就是一個(gè)數(shù)值發(fā)生器,可以產(chǎn)生想要的各種數(shù)值。Android 系統(tǒng)為它提供了很多計(jì)算數(shù)值的方法,如 int、float 等等。我們也可以自己實(shí)現(xiàn)計(jì)算數(shù)值的方法。其實(shí),在屬性動(dòng)畫中,如何產(chǎn)生每一步的動(dòng)畫效果,都是通過 ValueAnimator 計(jì)算出來的。

比如我們要實(shí)現(xiàn)一個(gè)從 0-100 的位移動(dòng)畫。隨著動(dòng)畫時(shí)間的持續(xù),它產(chǎn)生的值也會(huì)從 0-100 遞增。通過這個(gè) ValueAnimator 產(chǎn)生的值,再進(jìn)行屬性的設(shè)置即可。

那么 ValueAnimator 究竟是如何產(chǎn)生這些值的呢?

  • 首先 ValueAnimator會(huì)根據(jù)會(huì)根據(jù)動(dòng)畫已進(jìn)行的時(shí)間與它持續(xù)的總時(shí)間的比值,產(chǎn)生一個(gè)0-1的時(shí)間因子。有了這樣的時(shí)間因子,經(jīng)過相應(yīng)的變換,就可以根據(jù)初始值和最終值來生成中間的相應(yīng)值。同時(shí),通過插值器的使用,我們還可以進(jìn)一步控制每一個(gè)時(shí)間因子產(chǎn)生值的變化速率。如果我們使用的是線性插值器,那么它生成值的時(shí)候就會(huì)呈一個(gè)線性變化。如果我們使用一個(gè)加速度插值器,那么它生成值時(shí)便會(huì)呈一個(gè)二次曲線,增長率越來越快。

由于 ValueAnimator 不作用于任何一個(gè)屬性,也不提供任何一種動(dòng)畫。因此并沒有 ObjectAnimator 使用得廣泛。
實(shí)際上,ObjectAnimator 就是基于 ValueAnimator 進(jìn)行的一次封裝。我們可以查看 ObjectAnimator 的源碼,會(huì)發(fā)現(xiàn)它繼承自 ValueAnimator,是它的一個(gè)子類。正是 ValueAnimator 產(chǎn)生的變化值,才使得 ObjectAnimator 可以將它應(yīng)用于各個(gè)屬性。

使用方法

我們可以通過 ValueAnimator 的 ofXXX 產(chǎn)生一個(gè) XXX 類型的值(如ofInt),然后為 ValueAnimator 添加一個(gè)更新的回調(diào)事件。在回調(diào)事件中,通過參數(shù) animation 的 getAnimationValue() 方法,來獲取對應(yīng)的 value。有了這個(gè)值,我們就可以實(shí)現(xiàn)我們所有想要的動(dòng)畫效果。

比如此處就通過 ValueAnimator 實(shí)現(xiàn)了一個(gè)計(jì)時(shí)器的動(dòng)畫效果。

ValueAnimator animator = ValueAnimator.ofInt(0,100);
animator.setDuration(5000);
animator.addUpdateListener(new AnimatorUpdateListener() {
 @Override
 public void onAnimationUpdate(ValueAnimator animation) {
  Integer value = (Integer) animation.getAnimatedValue();
  mButton.setText(""+value);
 }
});
animator.start();

自定義數(shù)值生成器

前面提到,ValueAnimator 可以創(chuàng)建自定義的數(shù)值生成器,做法就是調(diào)用 ValueAnimator 的 ofObject 方法,創(chuàng)建一個(gè) TypeEvaluator 作為參數(shù)。之后我們可以通過重寫 TypeEvaluator 的 evaluate 方法,來按照自己的規(guī)則返回具體的值。

ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator() {
 @Override
 public Object evaluate(float fraction, Object startValue, Object endValue) {
  //計(jì)算
  return null; //返回值
 }
});

我們來看一下 evaluate 方法的幾個(gè)參數(shù)

  • float fraction:前面提到的時(shí)間因子
  • Object startValue:起始值
  • Object endValue:結(jié)束值

通過這三個(gè)值,我們就可以經(jīng)過計(jì)算產(chǎn)生所有我們想要的值。

其實(shí),通過 TypeEvaluator,我們不光能產(chǎn)生普通的數(shù)據(jù),還能結(jié)合泛型,我們還能定義更加復(fù)雜的數(shù)據(jù):

我們可以在創(chuàng)建 TypeEvaluator 時(shí)指定具體類型,來達(dá)到更豐富的效果。比如這里就用到了一個(gè)名為 PointF 的數(shù)據(jù)類型:

ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator() {
 @Override
 public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
  //計(jì)算
  return null; //返回值
 }
});

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對創(chuàng)新互聯(lián)的支持。


文章題目:Android動(dòng)畫教程之屬性動(dòng)畫詳解
轉(zhuǎn)載來源:http://weahome.cn/article/gogsgp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部