Android 中的轉場動畫及兼容處理

2021-02-14 鴻洋

本文由湫水投稿。

湫水的博客地址:

http://blog.csdn.net/wl9739

Android 中的動畫有很多,除了在一個界面上使用幀動畫、屬性動畫將一個或多個 View 進行動畫處理以外,還可以用於兩個界面之間過渡、跳轉。在 Android 5.0 之前,我們已經有了 overridePendingTransition() 方法來實現一些轉場效果。然而,在 Android 5.0 以後,轉場效果更加炫酷。 比如下面的動畫:


本篇文章,主要就是解說如何實現上述的效果。主要內容包括:


實現轉場動畫只需三步:

在 res/ 目錄下創建 transition 文件夾,在該文件夾下定義界面轉場動畫和共享元素的動畫。

在 res/value/style 文件中為每個 Activity 指定轉場動畫的 style ,並在 AndroidManifest.xml 文件中為每個 Activity 設置對應的 android:theme。

在 Activity 調用 startActivity() 切換動畫前,使用 ActivityOptionsCompat 來創建轉場動畫時的共享對象。

下面就來對這三步進行詳細講解。


定義轉場動畫

在 res/ 目錄下創建了 transition 資源文件夾後,就可以在該文件夾下對每一種動畫進行定義。

一般來說,對 Activity 定義一個過渡動畫可以寫成下面的形式:


其中, 是動畫效果的名稱,Android 5.0(API 級別 21)支持這些進入與退出轉換:

而每一種動畫效果,都有額外的屬性。比如滑動 slide,可以使用 android:slideEdge="top" 設置滑動的方向;淡入淡出(fade)可以使用 android:fadingMode="fade_in" 設置具體是淡入(fade_in)還是淡出(fade_out)等。

標籤裡面定義需要轉場(或者不需要轉場)的目標 id ,這個 id 可以使系統自帶的,也可以是我們自己視圖中的 view 的 id,每一個 id 需要單獨在 標籤中定義,android:targetId 表示目標ID需要進行過渡轉換的 view,而 android:excludeId 表示我們不需要該 ID 的 view 進行過渡轉場。上面的那段代碼的意思是說,除了狀態欄和導航欄以外所有的 view,都執行 explode 動畫。

如果我們想要在同一個過渡狀態中實現兩種或多種動畫效果怎麼辦?

也簡單,將根標籤替換為 ,然後定義每一種動畫效果,最後記得在根標籤中使用 android:transitionOrdering 註明這幾種動畫的演示順序,sequential 表示順序執行,而 together 表示同時執行。比如像下面的代碼:


這段代碼的意思就很簡單了,該 xml 定義了兩個過渡動畫,並且同時執行。第一個動畫是針對 id 為 cardView 的 view 進行滑動,第二個動畫將除了狀態欄、導航欄和 cardview 以外的 view,進行淡入淡出。

為每個 Activity 定義轉場樣式

這裡的每一種動畫,指的是在進行界面跳轉過渡時,兩個界面的狀態。比如對於 Activity A 和 Activity B 這兩個界面,可能的狀態如下:

一般來說,所有的 Activity 過渡動畫都可以定義成如下的形式:


當然,你可以不用寫全,比如在我的 Demo 中一個界面的轉場動畫文件如下:


調用 ActivityOptionsCompat

轉場動畫是在兩個界面的跳轉返回時發生的,所以,當使用 intent 跳轉界面時,需要調用 ActivityOptionsCompat來指定動畫的運行。

一般來說,調用 ActivityOptionsCompat 的模板代碼如下:


ActivityOptionsCompat 是在support v4 包裡面的,其實它是 ActivityOptions 的一個兼容(ActivityOptions是API 16引入的)。

然後,我們需要在第二個 Activity 中,將轉場的圖片獲取並顯示到界面中就可以了。

多個共享元素的過渡實現

有時候我們需要讓多個元素產生動畫效果,可以使用 Pair 來實現:


現在市面上,Android 5.0 以下的手機系統還有一定的市場份額,所以為了照顧這些用戶,我們只能手動實現一下共享元素的轉場動畫效果。

實現的思路也比較簡單,大概的步驟如下:

那麼我們開始一步步實現上面的步驟。

獲取共享元素位置信息

在第一個界面中,我們需要獲取到共享元素的位置信息,並將其傳遞給下一個界面。於是乎,我們可以在第一個界面元素點擊事件中,這麼寫:


其中,getGlobalVisibleRect() 方法的含義是,獲取 可見的狀態欄高度+可見的標題欄高度+Rect左上角到標題欄底部的距離,如果標題欄被隱藏了,那麼可見標題欄高度為0。

接下來,就在在第二個界面接收位置信息並將該圖片展示出來了。


模擬轉場動畫

在第二個界面中,我們需要做如下的操作:

獲取上共享元素信息。

計算共享元素縮放比例和位移距離。

調用動畫,完成模擬轉場效果。

我將上面三個步驟的代碼如下,你也可以下載我完整的 Demo(https://github.com/wl9739/UITransitionDemo) 來查看。


在12行,通過設置 Margin 的形式來確定圖片的位置,需要注意的是,由於狀態欄是在父控制項 FramLayout 之外的,因此我們要將 Rect.top 的值減去狀態欄的高度,這樣才是相對於屏幕的絕對位置。然後,getBundleInfo() 方法的代碼如下:


動畫處理


最後我們需要使用動畫來模擬轉場效果,代碼如下:


很簡單,至此,入場動畫效果基本模擬完畢。

而退場動畫就更簡單了,直接上代碼:


當然,這只是簡單的模擬,如果想要和 Android 5.0+ 的轉場效果相同,還需要做很多的動畫處理。

本篇文章的 Demo 地址:

    https://github.com/wl9739/UITransitionDemo

推薦閱讀:定義定製動畫

    https://developer.android.com/training/material/animations.html?hl=zh-cn

如果你有好的文章想和大家分享,歡迎投稿,直接向我投遞文章連結即可。

歡迎長按下圖->識別圖中二維碼或者掃一掃關注我的公眾號:

相關焦點

  • Android 轉場動畫
    聲明轉載自:顏家大少原文連結:https://juejin.im/post/5b0e8554f265da08ed7a15d1轉載已獲得作者授權,如需轉載請聯繫原作者轉場動畫: 是Android L 引入的動畫效果, 可以說是api19引入的場景(Scene)動畫的擴展. 使開發者更加方便的實現布局(界面)變化時候的過渡動畫.
  • 高逼格Android轉場動畫
    轉場動畫在交互上非常有優勢,本文從轉場動畫的使用場景和方法起,最後是實現掘金中用戶頭像的轉場動畫。轉場動畫適用的版本Activity transition APIs 只有在Android 5.0(API 21)或者更高的版本上能使用。所以在使用之前需要進行版本判斷。當版本API 大於21時使用轉場動畫,否則不使用。
  • 如何實現高逼格轉場動畫?
    點擊上方「劉望舒」,馬上關注,每天早上8:42準時推送作者: IDhankinghttps://www.jianshu.com/p/31434ec06073前言轉場動畫在交互上非常有優勢,本文從轉場動畫的使用場景和方法起,最後是實現掘金中用戶頭像的轉場動畫。
  • Android View 動畫
    設置動畫集合所採用的插值器,默認值為@android:anim/accelerate_decelerate_interpolator-->    <!--android:shareInterpolator-->    <!--Boolean. 表示集合中的動畫是否共享集合的插值器。
  • Android 有近10種動畫,你都知道嗎?
    可能有很多人迅速的反應出,缺少了目前使用也相對較多的 airbnb/lottie-android 動畫。不可置疑,Lottie 庫目前在 Android 開發中尤其複雜動畫效果上地位顯著。但我們今天要是的 Android 原生上為我們提供的能使用的動畫方式,Lottie 動畫今天暫且擱置。同時對於 RecyclerView item 加載動畫今天也暫且不提。
  • Android到底有多少種動畫?準確告訴你
    可能有很多人迅速的反應出,缺少了目前使用也相對較多的 airbnb/lottie-android 動畫。不可置疑,Lottie 庫目前在 Android 開發中尤其複雜動畫效果上地位顯著。但我們今天要是的 Android 原生上為我們提供的能使用的動畫方式,Lottie 動畫今天暫且擱置。同時對於 RecyclerView item 加載動畫今天也暫且不提。
  • Android之屬性動畫Animator
    Android 3.0之前已有動畫框架Animation(詳見:Android之視圖動畫Animation),但存在一些局限性,當某個元素發生視圖動畫後,其響應事件位置還在動畫前的地方。於是3.0之後,Google提出了屬性動畫。
  • Android自定義View-視圖動畫
    ="50%" * android:repeatCount="infinite" * android:repeatMode="reverse" * android:toXScale="0.5" * android:toYScale="0.5"> * </scale> *  * 完成一次動畫的持續時間,單位毫秒 * 動畫結束後
  • Android動畫:這些補間動畫的使用你必須要了解!
    前言    動畫的使用是Android 開發中常用的知識。
  • Android幀動畫和補間動畫看這篇足夠了
    在 Android 中常用的動畫分類無外乎三種,最早的 幀動畫 、補間動畫,以及 3.0 之後加入的 屬性動畫,是它們組成了 Android 中各種炫酷亮眼的動畫效果。關於動畫相關的博文說實話很多,但是為什麼要寫這篇文章呢?
  • 轉場動畫,讓你的PPT演示更有衝擊力
    筒子們,上圖中的PPT演示是不是很帥氣呀?人物當然是很帥氣的,除此之外….轉場動畫也功不可沒哦!轉場動畫是什麼呢?
  • Android 屬性動畫詳解,屬性動畫基本用法
    在Tween動畫的討論中,我們提到在Android中動畫可以分為三類:①幀動畫②Tween(補間動畫)③Property Animation(屬性動畫),在前面的文章中,分別對幀動畫和Tween動畫進行了非常詳細的討論,如果有興趣可以去上面的連結去閱讀。
  • GitHub Top 100的Android開源庫
    >android-async-http 是 Android 一款老牌異步請求庫, 專門對 Android 在 Apache 的 HttpClient 基礎上構建的異步 http 連接, 該庫有很多特徵, 例如: 庫的 size 小, 支持文件上傳不需使用第三方庫支持, 內部使用線程池來處理並發, 等等11.
  • 做動畫廣告怎麼轉場才酷炫?
    精彩的點在於如何設計「流暢的招式動線」,轉場技巧相對單純。這次的蜘蛛人動畫創意呢,目標則聚焦在他的經歷上:雙重身份的切換、蜘蛛人身份面對猛毒與綠惡魔時、彼得帕克的學生身份時。要在短短15秒囊括這些資訊(去掉最後LOGO出場其實只剩10秒),怎麼「轉場」就是重點啦!
  • Android Jetpack CameraX 庫 Beta 版正式發布!
    除了在自動化測試農場擴大測試範圍,有很多應用也在生產環境中使用了CameraX庫,這使得我們有信心向各位開發者推薦CameraX,推薦大家開始嘗試並將基於CameraX的應用發布到應用商店。我們也預想到可能會出現一些bug,但是我們會及時處理各種問題,來幫助大家實現最佳的相機使用體驗。如果您需要幫助,可以通過GoogleGroups討論群組或者新建一個issue來向我們反饋。
  • 對於Android Button,你可能並不了解
    也確實是我自己測試疏漏,由於LitePal 2.1.0版本中對Kotlin有了更加完善的支持,我當時想使用同一份代碼既兼容Java又兼容Kotlin,最後歷經千辛萬苦終於將Kotlin代碼都調試通過了,卻疏漏了Java部分的調試工作,我想當然地認為Java工程是沒問題的,結果問題就出在Java工程上,會直接導致項目崩潰。
  • 用轉場動畫彌補PPT切換效果的不足
    如果我們經常看一些很酷的全動畫PPT作品,就會發現,一些頁面之間的切換效果與PPT自帶的切換效果並不相同,它們就是動畫大師們所設計的轉場動畫,作為普通的PPT設計者或愛好者,我們無需去設計轉場動畫,但是可以搞懂這些轉場動畫的原理並學會運用。
  • Android Notes|BottomNavigationView 愛上 Lottie
    中也有對深色模式的兼容方法:    /**     * 驗證當前是否為深色模式     */    fun isDarkTheme(context: Context): Boolean {        val flag = context.resources.configuration.uiMode and
  • 轉場動畫——一分鐘讓你的PPT高大上
    想我以前在初涉較為高級的PPT動畫時,就是從學做轉場動畫開始的。什麼是轉場動畫呢,說白了,轉場動畫跟PPT中的切換所起的作用是一樣的,就是從一個畫面轉到另一個畫面的時候,這中間的過渡。後臺回覆:轉場,下載動畫源文件。
  • Android屬性動畫:這是一份全面 & 詳細的核心使用類ObjectAnimator學習攻略
    >在Java代碼中啟動動畫Animator animator = AnimatorInflater.loadAnimator(context, R.animator.view_animation); // 載入XML動畫animator.setTarget(view); // 設置動畫對象animator.start