Android魔法(第二弹)——一步步实现淹没、展开效果
目錄
1、效果展示
2、動(dòng)畫分析
3、整體布局
4、源碼解析
5、知識(shí)點(diǎn)總結(jié)
ObjectAnimator
ViewWrapper
源碼:
本篇文章我們實(shí)現(xiàn)一個(gè)簡單的動(dòng)畫效果,目的是熟悉和加深A(yù)ndroid屬性動(dòng)畫的使用。另外這次我們使用kotlin來進(jìn)行開發(fā),不熟悉kotlin的同學(xué)可以自行簡單了解一下kotlin語法,基本應(yīng)該能看懂
我們知道,android的View Animation動(dòng)畫可以移動(dòng)、放大等效果,但是不能改變布局的實(shí)際屬性。比如使用scaleAnimation使布局縮放,但是布局的實(shí)際大小并沒有改變,所以會(huì)遮蓋旁邊的布局,并不是把布局撐開,擠壓其他布局。
1、效果展示
現(xiàn)在我們要實(shí)現(xiàn)一種效果如下: 這時(shí)候使用ViewAnimation就會(huì)比較麻煩,所以我們使用ObjectAnimator來實(shí)現(xiàn)。2、動(dòng)畫分析
這個(gè)效果一共有三個(gè)狀態(tài): (狀態(tài)1) (狀態(tài)2)?(狀態(tài)3)
整個(gè)效果包含兩個(gè)階段: 淹沒 —— 從狀態(tài)1到狀態(tài)2。整個(gè)粉紅色的區(qū)域向上淹沒整個(gè)頁面 展開 —— 從狀態(tài)2到狀態(tài)3。當(dāng)淹沒整個(gè)頁面后,從中間展開直至整個(gè)頁面3、整體布局
這兩個(gè)階段就是實(shí)際上就是通過兩部分動(dòng)畫的依次執(zhí)行來實(shí)現(xiàn)的,我們先來看看布局: <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width= "match_parent"android:layout_height= "match_parent" ><RelativeLayoutandroid:id="@+id/animation_content"android:layout_width="match_parent"android:layout_height="300dp"android:layout_gravity="bottom"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:src="@drawable/girl1"/><FrameLayoutandroid:id="@+id/spread_view"android:layout_width="match_parent"android:layout_height="0dp"android:layout_centerInParent="true" /><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@id/spread_view"android:drawableBottom="@drawable/camera_top"android:background="#e07468" /><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@id/spread_view"android:drawableTop="@drawable/camera_bottom"android:background="#e07468" /></RelativeLayout > </FrameLayout>整個(gè)布局主要由四個(gè)部分組成:
- animation_content —— 這個(gè)就是整個(gè)粉色區(qū)域的部分。
- spread_view —— 這個(gè)是黑色區(qū)域的部分,一開始高度是0
- 兩個(gè)textview —— 中間的圓形button實(shí)際上由上下兩個(gè)獨(dú)立的部分組成的,而且這兩部分中間夾著spread_view(這么布局是為了第二階段的動(dòng)畫,下面會(huì)詳細(xì)講解)
這里要注意,我們使用了textview而不是imageview來實(shí)現(xiàn)button的布局,是因?yàn)槿绻褂胕mageview,當(dāng)?shù)诙A段展開到button的兩部分超出屏幕頂部和底部時(shí),imageview中的圖片會(huì)被縮小而不是溢出,差別如下
使用ImageView的效果
使用TextView的效果 所以我們這里使用TextView。并通過drawableBottom等屬性來設(shè)置圖片,這樣當(dāng)區(qū)域縮小時(shí),圖片大小并不會(huì)改變。4、源碼解析
下面就是實(shí)現(xiàn)的代碼: class?FloodAndSpreadActivity?:?Activity()?{override?fun?onCreate(savedInstanceState:?Bundle?)?{super.onCreate(savedInstanceState)setContentView(R.layout.flood_and_spread_activity)init()}fun?init(){val?height:?Int?=?window.windowManager.defaultDisplay.heightvar?floodWrapper?=?ViewWrapper(animation_content)var?spreadWrapper?=?ViewWrapper(spread_view)var?floodAnimation?=?ObjectAnimator.ofInt(floodWrapper,?"height",?height)floodAnimation.duration?=?1000floodAnimation.start()floodAnimation.addListener(object:?Animator.AnimatorListener{override?fun?onAnimationRepeat(p0:?Animator?)?{}override?fun?onAnimationCancel(p0:?Animator?)?{}override?fun?onAnimationStart(p0:?Animator?)?{}override?fun?onAnimationEnd(p0:?Animator?)?{ObjectAnimator.ofInt(spreadWrapper,?"height",?height).setDuration(1000).start()}})}class?ViewWrapper?(var?mTarget:?View){fun?getHeight():Int{return?mTarget.layoutParams.height}fun?setHeight(height:?Int){mTarget.layoutParams.height?=?heightmTarget.requestLayout()}} }Kotlin的一個(gè)優(yōu)點(diǎn)就是能夠大量的簡化代碼,可以看到只用十幾行就實(shí)現(xiàn)了這個(gè)效果。
回到代碼本身,我們通過上面的分析知道整個(gè)過程由兩部分動(dòng)畫組成:淹沒和展開。
在代碼中可以看到淹沒動(dòng)畫floodAnimation,它通過floodWrapper來動(dòng)態(tài)改變animation_content的高度直至屏幕高度,這樣就實(shí)現(xiàn)了淹沒的效果。而且由于spread_view設(shè)置成了centerInParent,而button的兩個(gè)部分與spread_view關(guān)聯(lián),所以在這個(gè)動(dòng)畫過程中button會(huì)跟隨著一起移動(dòng)并始終處于animation_content中心。
5、知識(shí)點(diǎn)總結(jié)
ObjectAnimator
這里簡單說說我們用到的方法:ofInt(floodWrapper, "height", height)。這個(gè)方法主要針對(duì)int類型的參數(shù)。第一個(gè)參數(shù)是要改變屬性的類,可以是代理類,下面會(huì)講到;第二個(gè)參數(shù)是要改變的屬性名,實(shí)際上是調(diào)用類的對(duì)應(yīng)的getter和setter方法;第三個(gè)參數(shù)是屬性的最終值,整個(gè)動(dòng)畫過程中改屬性會(huì)從當(dāng)前的值逐漸改變至最終值。
ObjectAnimator還有很多方法,大家有興趣可以自行學(xué)習(xí)。
ViewWrapper
這里要先說一說floodWrapper,它是一個(gè)ViewWrapper對(duì)象。ObjectAnimator會(huì)通過getter和setter方法來改變類某個(gè)屬性的值,但是如果沒有對(duì)應(yīng)的方法或者需要更多的操作,我們可以使用代理的形式,ViewWrapper就是一個(gè)代理類。由于View只有g(shù)etHeight函數(shù)沒有setHeight函數(shù),所以我們使用ViewWrapper代理它并實(shí)現(xiàn)getHeight和setHeight函數(shù)。
再回到floodAnimation,我們看到有一個(gè)監(jiān)聽器,當(dāng)動(dòng)畫結(jié)束的時(shí)候開始了另外一個(gè)動(dòng)畫。動(dòng)畫的這種關(guān)聯(lián)行為也可以使用另外一種方式:AnimatorSet,通過AnimatorSet可以實(shí)現(xiàn)多個(gè)動(dòng)畫的不同順序的執(zhí)行,處理復(fù)雜的動(dòng)畫效果非常有用。由于本篇只是一個(gè)簡單的順序執(zhí)行就沒有使用,關(guān)于AnimatorSet的使用比較簡單,大家可以查閱官方文檔。
在floodAnimation完成時(shí)我們執(zhí)行了另外一個(gè)動(dòng)畫,這就是第二個(gè)階段:展開。這次我們改變的是spread_view的高度,由于button的兩個(gè)部分是與spread_view關(guān)聯(lián)的,所以當(dāng)spread_view高度改變時(shí),button的兩個(gè)部分也隨著分離開,這樣就形成了展開的效果,直到spread_view展開到整個(gè)屏幕。
這樣這個(gè)效果就完成了,這個(gè)效果實(shí)際的應(yīng)用是一個(gè)過渡或者過場(chǎng)動(dòng)畫。主要的知識(shí)點(diǎn)就是屬性動(dòng)畫的使用。
大家有興趣可以自己手動(dòng)實(shí)現(xiàn)一下,對(duì)這兩個(gè)功能有更深入的了解。
源碼:
關(guān)注公眾號(hào):BennuCTech,發(fā)送“FastWidget”獲取完整源碼
總結(jié)
以上是生活随笔為你收集整理的Android魔法(第二弹)——一步步实现淹没、展开效果的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 剖析Picasso加载压缩本地图片流程(
- 下一篇: Android魔法(第三弹)—— 一步步