實現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中使用,或者提起商量好了再合作編碼。另外關于狀態欄適配,可以參考 這里
謝謝大家的觀看,如果覺得本文有意義的話,不妨點個贊或者分享吧!