創(chuàng)建Material Design風格的Android應(yīng)用--使用自定義動畫

摘要

動畫在Material Design設(shè)計中給用戶反饋放用戶點擊時捡需,并且在程序用戶界面中提供連貫的視覺热押。Material主題為按鈕(Button)和activity的轉(zhuǎn)換提供了一些默認的動畫膜毁,在android5.0(api 21)和更高的版本,你可以自定義這些動畫和創(chuàng)建一個新動畫,本文介紹如何使用和自定義動畫。
android Material Design animation java

動畫在Material Design設(shè)計中給用戶反饋放用戶點擊時,并且在程序用戶界面中提供連貫的視覺娇澎。Material主題為按鈕(Button)和activity的轉(zhuǎn)換提供了一些默認的動畫,在android5.0(api 21)和更高的版本睹晒,你可以自定義這些動畫和創(chuàng)建一個新動畫:

  1. Touch feedback(觸摸反饋)
  2. Circular Reveal(循環(huán)揭露效果)
  3. Activity transitions(Activity轉(zhuǎn)換效果)
  4. Curved motion(曲線運動)
  5. View state changes (視圖狀態(tài)改變)

自定義觸摸反饋

觸摸反饋在Material Design中在觸摸點提供了一個即時視覺確認當用戶作用在UI元素趟庄。按鈕的默認觸摸反饋動畫是使用了新的RippleDrawable類括细,它會是波紋效果在不同狀態(tài)間變換。

大多數(shù)情況下戚啥,我們可以使用這個功能通過在xml文件中定義背景:

?android:attr/selectableItemBackground 有界限的波紋
?android:attr/selectableItemBackgroundBorderless 可以超出視圖區(qū)域的波紋
?android:attr/selectableItemBackgroundBorderless 是21新添加的api

另外勒极,還以使用ripple元素定義RippleDrawable作為一個xml資源。

你可以給RippleDrawable對象分配一個顏色虑鼎。使用主題的android:colorControlHighlight屬性可以改變默認的觸摸反饋顏色。

更多信息键痛,查看RippleDrawable類的api指南炫彩。

使用揭露效果

揭露動畫為用戶提供視覺上的持續(xù)性擋顯示或者隱藏一組界面元素。ViewAnimationUtils.createCircularReveal()方法使你可以使用動畫效果來揭露或者隱藏一個視圖絮短。

這樣揭露一個先前隱藏的視圖:

// previously invisible view
View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());

// create the animator for this view (the start radius is zero)
Animator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);

// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();```

這樣隱藏一個先前顯示的視圖:

// previously visible view
final View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();

// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);

// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});

// start the animation
anim.start();```

自定義activity轉(zhuǎn)換效果

activity間轉(zhuǎn)換在Material Design程序中提供不同狀態(tài)間的視覺連接通過在公用元素上動作或者轉(zhuǎn)換江兢。你可以為進入或退出的轉(zhuǎn)換自定義動畫,共享元素在不同的activity之間的轉(zhuǎn)換效果丁频。
進入過渡決定activity中的視圖怎樣進入場景杉允。比如在爆裂進入過渡效果中犬金,視圖從屏幕外面飛向屏幕中間進入場景已日。

退出過渡決定activity中的視圖怎樣退出場景汰寓。比如砸狞,在爆裂退出過渡效果中匣摘,視圖從中間向遠處退出場景拾并。
共享元素過渡決定兩個activity之間共享的視圖怎么在兩個activity之間過渡豺旬。比如怕敬,兩個activity有一個相同的圖片咖为,在不同的位置和不同的大小秕狰,changeImageTransform(圖片變換變化)讓共享元素平滑的平移和縮放圖片在兩個activity之間。

android 5.0(api 21)提供以下進入和退出效果:

  • explode(爆裂) - 從場景中間移動視圖進入或者退出
  • slide(滑動) - 視圖從場景的一個邊緣進入或者退出
  • fade(淡入淡出) - 從場景添加或者移除一個視圖通過改變他的透明
    所有過渡效果都繼承Visibility類躁染,因此支持作為一個進入或者退出過渡效果鸣哀。

更多細節(jié),看Transition類的api指南吞彤。

Android5.0(api 21)也支持共享元素過渡效果:

  • changeBounds - 改變目標視圖的布局邊界
  • changeClipBounds - 裁剪目標視圖邊界
  • changeTransform - 改變目標視圖的縮放比例和旋轉(zhuǎn)角度
  • changeImageTransform - 改變目標圖片的大小和縮放比例
    當你在程序中開啟activity間的過渡動畫時我衬,默認的交叉淡入淡出效果會在兩個activity之間激活。

一個共享元素過渡效果

指定過渡效果

首先备畦,使用在從material theme繼承的樣式中低飒,使用android:windowContentTransitions屬性開啟窗口內(nèi)內(nèi)容過渡效果。也可以在樣式定義中第一進入懂盐,退出褥赊,共享元素的效果:

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowContentTransitions">true</item>

  <!-- specify enter and exit transitions -->
  <item name="android:windowEnterTransition">@transition/explode</item>
  <item name="android:windowExitTransition">@transition/explode</item>

  <!-- specify shared element transitions -->
  <item name="android:windowSharedElementEnterTransition">
    @transition/change_image_transform</item>
  <item name="android:windowSharedElementExitTransition">
    @transition/change_image_transform</item>
</style>```

示例中的過渡change_image_transform定義如下:



<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeImageTransform/>
</transitionSet>```

changeImageTransform元素對應(yīng)ChangeImageTransform類。更多信息莉恼,查看Transition的api指南拌喉。

在代碼中啟用窗口內(nèi)容過渡效果速那,使用Window.requestFeature()方法:

// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

// set an exit transition
getWindow().setExitTransition(new Explode());```

在代碼中定義過渡效果,使用下面的方法尿背,并傳一個Transition對象:

* Window.setEnterTransition() 
* Window.setExitTransition() 
* Window.setSharedElementEnterTransition() 
* Window.setSharedElementExitTransition() 
setExitTransition()和setSharedElementExitTransition()方法為調(diào)用的activity定義退出過渡效果端仰,setEnterTransition()和setSharedElementEnterTransition()方法為調(diào)用的activity定義進入過渡效果。

為了達到完整的過渡效果田藐,必須在進入的和退出的兩個activity上都啟用window內(nèi)容過渡荔烧。否則,正調(diào)用的activity會開始退出過渡汽久,你就會看到窗口過渡效果(比如縮放鹤竭,或者淡出)。

更快的開始一個進入過渡景醇,使用Window.setAllowEnterTransitionOverlap()方法在被調(diào)用的activity臀稚。這讓你有更加激動人心的進入過渡效果。

#####打開activity使用過渡
如果你為一個activity開啟過渡并且設(shè)置了一個退出過渡效果三痰,過渡效果會在你打開其他activity的時候激活吧寺,像這樣:

startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this).toBundle());```

如果你給第二個activity設(shè)置了進入過渡動畫,過渡也會在第二個activity啟動的時候激活散劫。當你啟動其他的activity時稚机,如果需要禁用過渡效果,提供一個為null的bundle選項舷丹。

打開一個activity包含一個共享元素

使用一個場景過渡動畫在兩個activity之間包括一個共享元素:

  1. 在theme中開啟窗口內(nèi)容過渡效果
  2. 在style中指定一個共享元素過渡效果
  3. 在xml中定義過渡樣式
  4. 在兩個activity的樣式文件中給共享元素分配一個相同的名字使用android:transitionName屬性
  5. 使用ActivityOptions.makeSceneTransitionAnimation()方法抒钱。
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);

// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);

// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, Activity2.class);
        // create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        ActivityOptions options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
        // start the new activity
        startActivity(intent, options.toBundle());
    }
});```

對于在代碼中生成的動態(tài)共享視圖,使用`View.setTransitionName()方法在兩個activity中給指定相同的名字颜凯。
當完成第二個activity的時候谋币,如果需要逆轉(zhuǎn)該過渡動畫,使用Activity.finishAfterTransition()方法代替Activity.finish()

#####打開一個activity包含多個共享元素
使用一個場景過渡動畫在兩個activity之間包括多于一個共享元素症概,在兩個activity中定義所有的的共享元素使用android:transitionName屬性(或使用View.setTransitionName()方法在所有的activity中),并且創(chuàng)建一個像下面這樣的ActivityOptions對象:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
Pair.create(view1, "agreedName1"),
Pair.create(view2, "agreedName2"));```

使用曲線運動

Material Design中蕾额,動畫依賴時間插值和空間移動模式曲線。在android5.0(api 21)和更高版本彼城,你可以為動畫自定義時間曲線和移動曲線诅蝶。

PathInterpolator類是一個新的基于貝塞爾曲線或Path對象的插值器。這個插值器在1*1的正方形上定義了曲線運動募壕,以(0调炬,0)和(1,1)點作為錨點舱馅,根據(jù)夠照參數(shù)控制點缰泡。你也可以使用xml文件的定義一個路徑插值器,如:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.4"
    android:controlY1="0"
    android:controlX2="1"
    android:controlY2="1"/>```

Material Design設(shè)計規(guī)范中代嗤,系統(tǒng)提供了三個基本曲線的xml資源:

* @interpolator/fast_out_linear_in.xml 
* @interpolator/fast_out_slow_in.xml 
* @interpolator/linear_out_slow_in.xml 

我們可以給Animator.setInterpolator()傳一個PathInterpolator對象來設(shè)置棘钞。

ObjectAnimator類有新的構(gòu)造方法缠借,你可以一次使用兩個或者屬性使用path獨立于坐標動畫。比如宜猜,下面的動畫使用一個Path對象去動作一個視圖的x和y屬性:

ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();```

視圖狀態(tài)改變動畫

StateListAnimator定義動畫當視圖的狀態(tài)改變的時候運行泼返,下面的例子是怎么在xml中定義一個StateListAnimator動畫:

<!-- animate the translationZ property of a view when pressed -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="@android:integer/config_shortAnimTime"
        android:valueTo="2dp"
        android:valueType="floatType"/>
        <!-- you could have other objectAnimator elements
             here for "x" and "y", or other properties -->
    </set>
  </item>
  <item android:state_enabled="true"
    android:state_pressed="false"
    android:state_focused="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="0"
        android:valueType="floatType"/>
    </set>
  </item>
</selector>```

給視圖附加自定義的視圖狀態(tài)動畫,使用selector元素在xml文件中定義一個動畫祥例子中這樣姨拥,給視圖分配動畫使用android:stateListAnimator屬性绅喉。在代碼中使用,使用AnimationInflater.loadStateListAnimator()方法叫乌,并且使用View.setStateListAnimator()方法霹疫。

當你的主題是繼承的Material主題,按鈕默認有一個Z動畫综芥。如果需要避免這個動畫,設(shè)置android:stateListAnimator屬性為@null 即可猎拨。

AnimatedStateListDrawable類讓你創(chuàng)建可繪制圖在相關(guān)聯(lián)的視圖狀態(tài)改變膀藐。android5.0的一些系統(tǒng)組件默認使用這些動畫。下面的例子是如何在xml文件中定義一個AnimatedStateListDrawable:


<animated-selector
xmlns:android="http://schemas.android.com/apk/res/android">

<!-- provide a different drawable for each state-->
<item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
    android:state_pressed="true"/>
<item android:id="@+id/focused" android:drawable="@drawable/drawableF"
    android:state_focused="true"/>
<item android:id="@id/default"
    android:drawable="@drawable/drawableD"/>

<!-- specify a transition -->
<transition android:fromId="@+id/default" android:toId="@+id/pressed">
    <animation-list>
        <item android:duration="15" android:drawable="@drawable/dt1"/>
        <item android:duration="15" android:drawable="@drawable/dt2"/>
        ...
    </animation-list>
</transition>
...

</animated-selector>```

可繪矢量動畫

可繪制矢量圖在拉伸時不會失真红省。AnimatedVectorDrawable類讓你可以在可繪制矢量圖上面作用動畫额各。

通常需要在三個xml文件中定義可動的矢量圖:

一個矢量圖使用<vector>元素,放在res/drawable/下。
一個可動的矢量圖使用<animated-vector>元素吧恃,放在res/drawable/下虾啦。
一個或更多個動畫對象使用<objectAnimator>元素,放在res/anim/下痕寓。

可動矢量圖可以使用<group>和<path>元素傲醉。<group>元素定義一系列路徑或者子組,<path>元素定義可繪圖的路徑呻率。

當你定義了一個想要作用動畫的矢量可繪制圖硬毕,使用android:name屬性給每個group和path指定一個唯一的名字,這樣你可以從動畫的定義中找到他們礼仗。比如:

<!-- res/drawable/vectordrawable.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>```

可動的矢量繪制通過剛剛說到定義的名字吐咳,來找到這些path和group:


<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vectordrawable" >
<target
android:name="rotationGroup"
android:animation="@anim/rotation" />
<target
android:name="v"
android:animation="@anim/path_morph" />
</animated-vector>```

動畫的定義表現(xiàn)在ObjectAnimator和AnimatorSet對象中。第一個動畫在這個例子中是讓目標組旋轉(zhuǎn)360度:

<!-- res/anim/rotation.xml -->
<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360" />```

第二個動畫例子是把矢量可繪圖從一個形狀變成另一種元践。所有的路徑必須兼容變換:他們必須有相同數(shù)量的命令韭脊,每個命令要有相同的參數(shù)。


<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType" />
</set>```

更多的信息单旁,看AnimatedVectorDrawable的api指南沪羔。

PS后記

這個系列終于寫完了,說實話基本上大部分都是翻譯的谷歌的官方文檔慎恒。因為時間問題任内,再加上自己的英語夠爛撵渡,最近越來慢。不過死嗦,這樣一下來趋距,加上自己的一些代碼練習,對于Material設(shè)計算是能夠基本使用了越除〗诟可惜,大部分的style還都不能向下兼容摘盆,只好等5了翼雀。

網(wǎng)上有一些大神進來已經(jīng)開源了一些開源組件,大家可以借此曲線救國孩擂,下次有空在專門整理一下狼渊。

本文參考: http://developer.android.com/training/material/animations.html
原文地址:http://blog.isming.me/2014/11/13/creating-app-with-material-design-five-animations/,轉(zhuǎn)載請注明出處类垦。
原文地址:http://my.oschina.net/sammy1990/blog/344184狈邑,轉(zhuǎn)載請注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚤认,一起剝皮案震驚了整個濱河市米苹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砰琢,老刑警劉巖蘸嘶,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異陪汽,居然都是意外死亡训唱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門挚冤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雪情,“玉大人,你說我怎么就攤上這事你辣⊙餐ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵舍哄,是天一觀的道長宴凉。 經(jīng)常有香客問我,道長表悬,這世上最難降的妖魔是什么弥锄? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上籽暇,老公的妹妹穿的比我還像新娘温治。我一直安慰自己,他們只是感情好戒悠,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布熬荆。 她就那樣靜靜地躺著,像睡著了一般绸狐。 火紅的嫁衣襯著肌膚如雪卤恳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天寒矿,我揣著相機與錄音突琳,去河邊找鬼。 笑死符相,一個胖子當著我的面吹牛拆融,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啊终,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼冠息,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了孕索?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤躏碳,失蹤者是張志新(化名)和其女友劉穎搞旭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菇绵,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡肄渗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了咬最。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翎嫡。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖永乌,靈堂內(nèi)的尸體忽然破棺而出惑申,到底是詐尸還是另有隱情,我是刑警寧澤翅雏,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布圈驼,位于F島的核電站,受9級特大地震影響望几,放射性物質(zhì)發(fā)生泄漏绩脆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望靴迫。 院中可真熱鬧惕味,春花似錦、人聲如沸玉锌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芬沉。三九已至躺同,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丸逸,已是汗流浹背蹋艺。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留黄刚,地道東北人捎谨。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像憔维,于是被迫代替她去往敵國和親涛救。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容