新年好,首先給大家發個紅包。
[意念紅包]請閉上眼睛通過念力領取。
本文同步自wing的地方酒館
這都2017年了,是時候來一波基礎特效教程了!
如果我不偷懶的話,或許可以成為一個系列都基礎教程哦。當然如果成為了一個系列,這個系列就像標題說的一樣,是基礎特效。所以內容會比較簡單,如果你是老司機的話,可以直接飄過了(順便帶我上車!)。
本次專案地址:github.com/githubwing/…
這次依然拿餓了麼開刀。來庖丁一個搜尋欄過度效果,如下圖:
額,圖片還是比較大的,為了不浪費排版空間,這次就不上餓了麼原圖了,直接上效果圖。效果還是差不多的哈。
如你所見,這是一個過度效果。 用一個群友的話來說就是絲滑過度根本看不出來是兩個Activity。
一個Activity還是兩個?
這是兩個Activity,看起來順化的原因是使用了一種叫做共享元素的概念。Android 5.0自帶共享元素的實現,但是有一些缺點比如:不能改變大小, 不能相容4.X 等等。
如何實現?
其實本次的效果在高仿微信下滑返回PhotoView中有運用以及介紹。但是由於篇幅沒有做詳細的介紹,現在就向大家介紹實現這種效果的思路。
首先既然叫做共享元素,那麼可想而知肯定有兩個Activity擁有一項共同的元素,可能是圖片、一個TextView、一個EditText等等。如效果圖,他就是共享一整個EditText。準確地說是一個組成看似EditText的元素組。
為了實現這個效果,我們需要在兩個Activity中都放置同樣的搜尋欄元素。
<FrameLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#0096FF"
android:padding="10dp">
<TextView
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="廣東省廣州市番禺區"
android:textColor="#fff"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_search_bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/ele_search_bg"
android:gravity="center"
android:padding="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="搜尋商家、商品名稱" />
<TextView
android:gravity="center"
android:textColor="#fff"
android:text="燒烤 螺螄粉 火鍋 巴掌 麥當勞 冒菜 臭豆腐 雲吞麵 "
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>複製程式碼
現在我們兩個Activity都有這個元素了。接下來要做的只有一步:那就是startActivity。
哈哈,我真的沒有逗你,因為其實所有你看到的動畫都是在第二個Activity完成的。由效果圖可以看到,在動畫執行的過程中還是可以看到前一個Activity的,所以我們需要對第二個Activity進行特殊的“透明處理”。
在style.xml裡面新增加一個透明的主題,並且應用給第二個Activity。
<style name="Translucent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
</style>複製程式碼
接下來,只要在第二個Activity開啟的時候,進行一些動畫即可。所以首先我們要把第一個Activity中元素的座標傳給第二個Activity。
Intent intent = new Intent(EleActivity.this,EleSearchActivity.class);
int location[] = new int[2];
mSearchBGTxt.getLocationOnScreen(location);
intent.putExtra("x",location[0]);
intent.putExtra("y",location[1]);
startActivity(intent);
overridePendingTransition(0,0);複製程式碼
注意這裡拿到的是在螢幕中的座標。所以在第二個Activity中,獲取第二個元素的座標也要用螢幕中的座標。
拿到之後,再根據兩個座標的差值進行平移操作,這樣位移起來就完全不需要考慮其他座標系了。至於為什麼,留個作業(斜眼):
float originY = getIntent().getIntExtra("y", 0);
int location[] = new int[2];
mSearchBGTxt.getLocationOnScreen(location);
float translateY = originY - (float) location[1];複製程式碼
如果你想要預覽位置效果,可以直接view.setTranslateY(translateY);
接下來動畫只要交給ValueAnimator,在這裡把搜尋欄的背景單獨抽成一個View,用來進行X縮放操作。所以現在要做的動畫有:
- 左側箭頭的Y軸平移動畫。
- 右側搜尋的Y軸平移動畫。
- 中間文字以及背景的Y軸平移動畫。
- 中間背景的X縮放動畫。
- 下部View內容的透明動畫。
translateVa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mSearchBGTxt.setY((Float) valueAnimator.getAnimatedValue());
mArrowImg.setY(mSearchBGTxt.getY() + (mSearchBGTxt.getHeight() - mArrowImg.getHeight()) / 2);
mHintTxt.setY(mSearchBGTxt.getY() + (mSearchBGTxt.getHeight() - mHintTxt.getHeight()) / 2);
mSearchTxt.setY(mSearchBGTxt.getY() + (mSearchBGTxt.getHeight() - mSearchTxt.getHeight()) / 2);
}
});複製程式碼
等動畫執行完畢以後,只需要將View正確歸為即可!
當然返回的時候,只需要往相反的地方做動畫~ 另外還需要特別注意的地方有,在啟動或者關閉Activity的時候,需要呼叫下面的程式碼來關閉切換動畫來保證效果。
overridePendingTransition(0, 0);複製程式碼
感覺這次效果雖然簡單,但是應用場景還是挺廣得。
本次專案地址:github.com/githubwing/…
如果你喜歡 歡迎Star,也可以加入我的Android酒館:425983695
參考文章: 低版本實現共享元素動畫