實現Activity間的共享控件轉場動畫
原文出處: http://www.jianshu.com/p/841f7b95ca77
Lollipop中有shared_element可以進行元素在activity之間進行共享,網上已經有很多介紹了,然而目前還有大量的kitkat設備,所以說啊,兼容更重要。
如下的方法,可以實現在舊的手機上實現動畫效果。采用了類似于豌豆莢的開眼項目使用的技術.
Preview
實現原理
最近逛業界良心酷安網,發現了豌豆莢的一款叫做 開眼 的項目,這個項目的意義就是每天把墻外的東西搬運回來讓村里的阿Q們開開眼,這款app至少目前看還沒有那么毒瘤,還是比較小而美的,于是下載試用了一下。
有個轉場動畫使用了類似上面gif的效果,第一感覺是自定義了一個popwindow,于是起床,打開電腦,對兩個效果的始末進行查詢
# grep 是 unix命令,windows下先進shell再輸入dump...內容 adb shell dumpsys window windows | grep -E 'mCurrentFocus'
結果如下,可以發現是2個activity,而不是自定義view實現的
mCurrentFocus=xx/com.wandoujia.eyepetizer.ui.activity.FeedActivity} mCurrentFocus=xx/com.wandoujia.eyepetizer.ui.activity.DetailActivity}
反復研究,最后發現原理如下
-
FeedActivity將view的top/width/height,內容等信息通過intent進行發送
-
DetailActivity設置為背景透明模式,轉場動畫關閉,這里關閉是非常重要的
-
DetailActivity接著讀取intent,并根據高度等信息進行動畫繪制,由于DetailActivity的背景是透明的,所以用戶會誤認為是進行了“放大”操作
在UED中,“放大”與“右轉”是兩種常見的場景切換操作,安利一個叫做《Learn iOS Design》的書,Android開發者也值得借鑒一下
步驟
步驟非常簡單,主要時間是耗在了調試動畫上
1. 設置DetailActivity的主題
<style name="DetailedTheme" parent="AppTheme"> <!--背景透明--> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> <!--無進入動畫--> <item name="android:windowAnimationStyle">@null</item> </style>
2. 獲取FeedActivity中的itemview
樓主在RecyclerView的Adapter中的viewholder中手動加了一個接口,在主界面實現
@Override public void onItemClick(View v, int position) { Parcelable imgInfo = ((CardAdapter) mRecyclerView.getAdapter()).getData().get(position); int top = v.getTop(); int heigh = v.getHeight(); int width = v.getWidth(); //發送Intent Extra DetailedActivity.startActivity(v.getContext(), imgInfo, top, heigh, width); }
3. 在DetailActivity中進行動畫
動畫沒有什么技巧,跟老司機開車一樣,屬于熟練工種,我們這里主要是使用了AnimationSet進行并發動畫
void anim(View view, int top, int height, int width, boolean isEnter, Animation.AnimationListener listener) { //記住括號哦,我這里調試了一小時 float delta = ((float) width) / ((float) height); float fromDelta, toDelta, fromY, toY; if (isEnter) { fromDelta = 1f; toDelta = delta; fromY = top; toY = 0; } else { fromDelta = delta; toDelta = 1f; fromY = 0; toY = top; } Animation anim = new ScaleAnimation(fromDelta, toDelta, // Start and end values for the X axis scaling fromDelta, toDelta, // Start and end values for the Y axis scaling Animation.RELATIVE_TO_SELF, 0.5f, // scale from mid of x Animation.RELATIVE_TO_SELF, 0f); // scale from start of y Animation trans = new TranslateAnimation(0, 0f, fromY, toY); AnimationSet set = new AnimationSet(true); //添加并行動畫 set.addAnimation(anim); set.addAnimation(trans); //動畫結束后保持原樣 set.setFillEnabled(true); set.setFillAfter(true); //監聽器 set.setAnimationListener(listener); set.setDuration(AnimateUtils.ANIM_DORITION); view.startAnimation(set); }
這樣,動畫就搞定了,是不是很簡單?
總結
源碼仍在更新中,后期可能將加入大量仿iOS的組件
https://github.com/miao1007/Lollipop-Animation-Sample
最后,總結一下,這個東西實現不難,但是
-
調試動畫太費時間了,暗坑多
-
大部分手機fps運行狀態未知
-
編碼改動量大,很難把所有業務封裝在一個文件中,源碼亂,后期維護困難
所以除了情懷,很少有專門的人愿意這樣寫,我建議在個人app中使用,或者提起商量好了再合作編碼。另外關于狀態欄適配,可以參考 這里
謝謝大家的觀看,如果覺得本文有意義的話,不妨點個贊或者分享吧!