基本特效:餓了麼絲滑無縫過度搜尋欄的實現

androidwing發表於2017-01-02

新年好,首先給大家發個紅包。

[意念紅包]請閉上眼睛通過念力領取。


本文同步自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縮放操作。所以現在要做的動畫有:

  1. 左側箭頭的Y軸平移動畫。
  2. 右側搜尋的Y軸平移動畫。
  3. 中間文字以及背景的Y軸平移動畫。
  4. 中間背景的X縮放動畫。
  5. 下部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

參考文章: 低版本實現共享元素動畫

相關文章