用UIKit和UIView在視圖上執行iOS動畫

来源:https://www.cnblogs.com/Julday/archive/2020/03/25/12566829.html
-Advertisement-
Play Games

本文旨在成為iOS動畫的入門讀物,目的是詳盡地介紹不同的實現方法。 鑒於該主題的廣泛性,我們將在相當高的層次上簡潔地涵蓋每個部分。這樣做的目的是通過一組選項來教育讀者將動畫添加到他/她的iOS應用程式中。 在我們開始討論與IOS相關的主題之前,讓我們先簡單地看一看動畫的速度。 60 Fps動畫 通常 ...


本文旨在成為iOS動畫的入門讀物,目的是詳盡地介紹不同的實現方法。

鑒於該主題的廣泛性,我們將在相當高的層次上簡潔地涵蓋每個部分。這樣做的目的是通過一組選項來教育讀者將動畫添加到他/她的iOS應用程式中。

在我們開始討論與IOS相關的主題之前,讓我們先簡單地看一看動畫的速度。

60 Fps動畫

通常,在視頻中,每一幀由圖像表示,幀速率決定在序列中翻轉的圖像數量。這被稱為“幀每秒”或FPS。

FPS確定在一秒鐘內翻轉的靜止圖像的數量,這實際上意味著圖像/幀的數量越多,視頻中顯示的細節/信息就越多。這也適用於動畫。

FPS通常用於確定動畫的質量。有一種流行的觀點認為,任何好的動畫應該運行在60英尺或更高-任何低於60 fps將感到有點不對勁。

你想看看30 FPS和60 FPS之間的區別嗎?看看這個!

你註意到區別了嗎?人的眼睛肯定能感覺到低fps的抖動。因此,確保您所創建的任何動畫都遵循運行在60 fps或更高的基本規則,這是一個很好的實踐。這讓它感覺更現實,更有活力。

在查看了FPS之後,現在讓我們深入研究不同的核心iOS框架,這些框架為我們提供了一種執行動畫的方法

核心框架

在本節中,我們將討論可以用於創建視圖動畫的IOSSDK中的框架。我們將對它們進行快速的瀏覽,並以相關的示例說明它們的特性集。<

UIKIT/UIVIEW動畫

UIView是任何在iOS應用程式中顯示內容的視圖的基類。

UIKit是為我們提供UIView的框架,它已經為我們提供了一些基本的動畫功能,使得開發人員可以通過更少的操作來實現更多的目標。

APIUIView.animate,因為通過提供基於塊的語法中的屬性值,任何視圖的屬性都可以很容易地被動畫化。

在UIKit動畫中,建議只修改UIVIew的可動畫屬性,否則動畫可能會導致視圖處於意外狀態。

動畫(附圖:動畫:完成)

此方法接受動畫持續時間,這是一組需要動畫化的視圖的可動畫屬性更改。完成塊在視圖執行動畫時提供回調。

幾乎任何類型的動畫,如移動,縮放,旋轉,褪色,等等,在一個視圖可以實現這個單一的API。

現在,考慮您想要動畫一個按鈕大小的變化,或者您想要一個特定的視圖放大到屏幕。這就是我們如何使用UIView.animateAPI:

let newButtonWidth: CGFloat = 60

UIView.animate(withDuration: 2.0) { //1
    self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) //2
    self.button.center = self.view.center //3
}

我們在這裡做的是:

  1. 我們稱之為UIView.animate方法具有傳遞給它的持續時間值,該值表示在塊中描述的動畫應該運行多長時間。
  2. 我們設置按鈕的新框架,它應該表示動畫的最終狀態。
  3. 我們設置按鈕center它的超級視圖的中心,使它保持在屏幕的中心。

上面的動畫代碼塊應該觸發按鈕框架的動畫,而不是當前的框架:

Width = 0, Height = 0

最後一個框架:

Width = Height = newButtonWidth

下麵是動畫的樣子:

 

 

 

animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion

此方法類似於動畫方法的擴展,您可以在前面的API中執行所有可以執行的操作,並將一些物理行為添加到視圖動畫中。

例如,如果您想在上面所做的動畫中實現彈簧阻尼效果,那麼代碼如下所示:

let newButtonWidth: CGFloat = 60
UIView.animate(withDuration: 1.0, //1
    delay: 0.0, //2
    usingSpringWithDamping: 0.3, //3
    initialSpringVelocity: 1, //4
    options: UIView.AnimationOptions.curveEaseInOut, //5
    animations: ({ //6
        self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth)
        self.button.center = self.view.center
}), completion: nil)

下麵是我們使用的一組參數:

  1. duration
    表示確定代碼塊應運行多長時間的動畫持續時間。
  2. delay
    表示我們希望在動畫開始之前具有的初始延遲。
  3. SpringWithDamping
    表示我們希望視圖表現的彈性效果的值。數值必須在0到1之間。值越低,彈簧振蕩越高。
  4. velocity
    表示動畫應以何種速度啟動。
  5. options
    要應用於視圖動畫的動畫曲線類型。
  6. 最後,我們設置需要動畫的按鈕框架的代碼塊。它和以前的動畫一樣。

下麵是用上面的動畫配置動畫的樣子:

 

 

 

UIViewProperty動畫

為了更好的控制動畫,UIViewPropertyAnimator它為我們提供了暫停和恢復動畫的方法。您可以有自定義的定時,並使您的動畫具有交互性和可中斷性。這在執行動畫時非常有用,這些動畫也可以與用戶操作交互。

經典的“滑動解鎖”手勢和播放器視圖“解散/擴展動畫”(在音樂應用程式中)是互動式動畫和可中斷動畫的例子。您可以開始用手指移動視圖,然後釋放它,視圖將回到原來的位置。或者,您可以在動畫期間捕捉視圖並繼續用手指拖動視圖。

下麵是一個簡單的示例,說明如何使用UIViewPropertyAnimator:

let newButtonWidth: CGFloat = 60
let animator = UIViewPropertyAnimator(duration:0.3, curve: .linear) { //1
    self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth)
    self.button.center = self.view.center
}
animator.startAnimation() //2

我們正在做的事情如下:

  1. 我們稱之為UIViewPropertyAPI通過傳遞持續時間和動畫曲線。
  2. 與上面的UIView.動畫API不同,除非您自己指定動畫,即完全控制完整的動畫過程/流,否則動畫不會啟動。

現在,讓我們假設你想要更多的控制動畫。例如,您希望設計和控制動畫中的每個幀。還有另一個APIanimateKeyframes。但是在我們深入研究它之前,讓我們快速地看看一個框架是什麼,在一個動畫中。

什麼是Aframe?

視圖的框架更改/轉換集合(從開始狀態到最終狀態)定義為animation動畫期間視圖的每個位置都被稱為frame.

動畫關鍵幀

這個API提供了一種設計動畫的方法,使您可以定義具有不同時間和轉換的多個動畫。發佈這篇文章後,API簡單地將所有動畫集成到一個無縫體驗中。

假設我們想以隨機的方式移動屏幕上的按鈕。讓我們看看如何使用KeyFrame動畫API來做到這一點。

UIView.animateKeyframes(withDuration: 5, //1
  delay: 0, //2
  options: .calculationModeLinear, //3
  animations: { //4
    UIView.addKeyframe( //5
      withRelativeStartTime: 0.25, //6
      relativeDuration: 0.25) { //7
        self.button.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.maxY) //8
    }

    UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.25) {
        self.button.center = CGPoint(x: self.view.bounds.width, y: start.y)
    }

    UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25) {
        self.button.center = start
    }
})

詳細情況如下:

  1. duration
    通過傳遞動畫的持續時間來調用API。
  2. delay
    動畫的初始延遲持續時間。
  3. options
    要應用於視圖動畫的動畫曲線類型。
  4. animations
    塊,該塊接受開發人員/用戶設計的所有關鍵幀動畫。
  5. addKeyFrame
    調用API來設計每個動畫。在我們的例子中,我們定義了按鈕的每一個動作。我們可以有更多的這樣的動畫,我們需要,添加到塊。
  6. relativeStartTime
    定義動畫塊集合中動畫的啟動時間。
  7. relativeDuration
    定義此特定動畫的總體持續時間。
  8. center
    在我們的示例中,我們只需更改按鈕的中間屬性,將按鈕移動到屏幕周圍。

最後的動畫是這樣的:

 

 

 

共動畫

任何基於UIKit的動畫都是在內部轉換成核心動畫。因此,核心動畫框架充當任何UIKit動畫的支持層或骨幹。因此,所有UIKit動畫API都只是以一種易於消費或方便的方式封裝了核心動畫API的層。

UIKit動畫API不提供對視圖執行的動畫的太多控制,因為它們主要用於視圖的可動畫屬性。因此,在這種情況下,如果您想要控制動畫的每一個幀,最好直接使用底層的核心動畫API。或者,UIView動畫和核心動畫也可以一起使用。

UIView+核心動畫

讓我們看看如何重新創建相同的按鈕更改動畫,同時使用UIView和Core動畫API指定時間曲線。

我們可以用CATransaction的定時功能,它允許您指定和控制動畫曲線。

讓我們來看一個按鈕大小變化動畫的例子,它的角半徑使用CATransaction的定時功能和UIView動畫的組合:

let oldValue = button.frame.width/2
let newButtonWidth: CGFloat = 60

/* Do Animations */
CATransaction.begin() //1
CATransaction.setAnimationDuration(2.0) //2
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)) //3

// View animations //4
UIView.animate(withDuration: 1.0) {
    self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth)
    self.button.center = self.view.center
}

// Layer animations
let cornerAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.cornerRadius)) //5
cornerAnimation.fromValue = oldValue //6
cornerAnimation.toValue = newButtonWidth/2 //7

button.layer.cornerRadius = newButtonWidth/2 //8
button.layer.add(cornerAnimation, forKey: #keyPath(CALayer.cornerRadius)) //9

CATransaction.commit() //10

詳細情況如下:

  1. begin
    表示動畫代碼塊的開始。
  2. duration
    整體動畫持續時間。
  3. curve
    表示需要應用於動畫的計時曲線。
  4. UIView.animate
    我們的第一個動畫改變框架的按鈕。
  5. CABasicAnimation
    我們創建CABasicAnimation引用cornerRadius按鈕作為鍵盤,因為這是我們想要的動畫。類似地,如果希望對關鍵幀動畫具有粒度級控制,則可以使用CAKeyframeAnimation班級。
  6. fromValue
    表示動畫的起始值,即cornerRadius從動畫必須從哪裡開始的按鈕的值。
  7. toValue
    表示動畫的最終值,即最終值。cornerRadius動畫必須結束的按鈕的值。
  8. cornerRadius
    我們必須設置`cornerRadius屬性的屬性,以動畫的最終值,否則,按鈕的角半徑值將在動畫完成後自動恢復到其初始值。
  9. addAnimation
    通過表示動畫需要執行的Keypath,我們將包含整個動畫過程配置的動畫對象附加到該層。
  10. commit
    表示動畫代碼塊的結束並開始動畫。

最後的動畫是這樣的:

 

 

 

這個博客是一個偉大的閱讀,以幫助創建更高級的動畫,因為它整齊地帶您通過大多數核心動畫框架API指導您通過每一步的道路。

UIKITDYNAMICS

UIKitDynamic是UIKit的物理引擎,它使您能夠在UIKit控制項中添加任何物理行為,如碰撞、重力、推、扣等。

UIKitDynamic動畫

這是UIKitDynamicyFramework的管理類,它規範由任何給定UI控制項觸發的所有動畫。

UIKitDynamicBehavior

它使您可以將任何物理行為添加到動畫師中,從而使其能夠在附在其上的視圖上執行操作。

UIKitDynamic的各種行為包括:

  • UIAttachmentBehavior
  • UICollisionBehavior
  • UIFieldBehavior
  • UIGravityBehavior
  • UIPushBehavior
  • UISnapBehavior

UIKitDynamic的體繫結構類似於。請註意,項目1至5可以替換為單個視圖。

讓我們把一些物理行為應用到我們的按鈕上。我們將看到如何將重力應用到按鈕上,這樣它就能給我們一種處理真實物體的感覺。

var dynamicAnimator   : UIDynamicAnimator!
var gravityBehavior   : UIGravityBehavior!

dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1

gravityBehavior = UIGravityBehavior(items: [button]) //2
dynamicAnimator.addBehavior(gravityBehavior) //3

詳細情況如下:

  1. UIKitDynamicAnimator
    我們創建了一個UIKitDynamicAnimator對象,它充當執行動畫的協調器。我們還傳遞了作為引用視圖的按鈕的SuperView。

  2. UIGravityBehavior
    我們創建了一個UIGravityBehavior對象,並將我們的按鈕傳遞到註入此行為的數組元素中。

  3. addBehavior
    我們給動畫師添加了重力物體。

    這將創建如下所示的動畫:


     
註意按鈕是如何從屏幕的中心(它的原始位置)掉到底部和後面的。

我們應該告訴動畫師考慮屏幕底部是地面。這裡是`UICollisionBehavior`進入畫面。

```
var dynamicAnimator   : UIDynamicAnimator!
var gravityBehavior   : UIGravityBehavior!
var collisionBehavior : UICollisionBehavior!

dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1

gravityBehavior = UIGravityBehavior(items: [button]) //2
dynamicAnimator.addBehavior(gravityBehavior) //3

collisionBehavior = UICollisionBehavior(items: [button]) //4
collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5
dynamicAnimator.addBehavior(collisionBehavior) //6
```
  1. UICollisionBehavior
    我們創建了一個UICollisionBehavior對象並沿按鈕傳遞,以便將行為添加到元素中。

  2. translatesReferenceBoundsIntoBoundary
    啟用此屬性會告訴動畫師將引用視圖邊界作為結束,在我們的示例中,這是屏幕的底部。

  3. addBehavior
    我們在這裡給動畫師添加了碰撞行為。

    現在,我們的按鈕應該按在地面上,靜止不動,如下所示:

     
    挺不錯的,不是嗎?

     

現在,讓我們嘗試添加一個彈跳效應,使我們的對象感覺更真實。為此,我們將使用UIDynamicItemBehavior班級。

```
var dynamicAnimator   : UIDynamicAnimator!
var gravityBehavior   : UIGravityBehavior!
var collisionBehavior : UICollisionBehavior!
var bouncingBehavior  : UIDynamicItemBehavior!

dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1

gravityBehavior = UIGravityBehavior(items: [button]) //2
dynamicAnimator.addBehavior(gravityBehavior) //3

collisionBehavior = UICollisionBehavior(items: [button]) //4
collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5
dynamicAnimator.addBehavior(collisionBehavior) //6

//Adding the bounce effect
bouncingBehavior = UIDynamicItemBehavior(items: [button]) //7
bouncingBehavior.elasticity = 0.75 //8
dynamicAnimator.addBehavior(bouncingBehavior) //9
```
  1. UIDynamicItemBehavior
    我們創建了一個UIDynamicItemBehavior對象並沿按鈕傳遞,以便將行為添加到元素中。
  2. elasticity
    數值必須在0-1之間,它代表彈性,即物體在地面上和地面上彈跳的次數。這就是魔術發生的地方--通過調整這個屬性,你可以區分不同種類的物體,比如球、瓶子、硬物品等等。
  3. addBehavior
    我們在這裡給動畫師添加了碰撞行為。

現在,我們的按鈕在觸地時應該會反彈,如下所示:

 

 

 

這個回購是非常有用的,並顯示了所有的UIKitDynamicsActions在行動中。它還提供了用於處理每一種行為的源代碼。在我看來,這應該是一系列在視圖上執行iOS動畫的方法。

在下一節中,我們將簡要介紹幫助我們測量動畫性能的工具。我也建議你看看優化Xcode構建的方法因為它將節省大量的開發時間。

性能調諧

在本節中,我們將研究如何測量和調優iOS動畫的性能。作為iOS開發人員,您可能已經使用Xcode工具(如記憶體泄漏和分配)來衡量整個應用程式的性能。同樣,也有一些工具可以用來衡量動畫的表現。

Core Animation儀器

試試看Core Animation儀器和你應該能夠看到你的應用屏幕提供的FPS。這是一個很好的方法來衡量任何動畫呈現在你的iOS應用程式的性能/速度。

繪圖

FPS在這個應用程式中被大大降低了,它顯示的內容很重,就像圖像中的陰影一樣。在這種情況下,而不是直接將圖像分配給UIImageView的圖像屬性,嘗試使用CoreGraphicsAPI在上下文中分別繪製圖像。當在單獨的線程中而不是在主線程中執行圖像解壓縮邏輯時,這會過度地減少圖像顯示時間。

光柵化

Rasteralization是一個用於緩存複雜層信息的過程,以便這些視圖在呈現時不會被重新繪製。重繪視圖是FPS減少的主要原因,因此,最好對將要重覆使用的視圖應用柵格化。

包起來

最後,我還總結了用於iOS動畫的有用資源列表。當你在iOS動畫上工作時,你可能會發現這很方便。此外,您可能還會發現這套設計工具在深入研究動畫之前,作為一個(設計)步驟很有幫助。

我希望我已經能夠涵蓋儘可能多的主題,圍繞iOS動畫。如果我在這篇文章中遺漏了什麼,請在下麵的評論部分告訴我,我很樂意做這個補充!

作為一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是一個我的iOS交流群:1012951431 不管你是小白還是大牛歡迎入駐 ,分享BAT,阿裡面試題、面試經驗,討論技術, 大家一起交流學習成長!

另附上一份各好友收集的大廠面試題,進群可自行下載!

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • distinct這個關鍵字來過濾掉多餘的重覆記錄只保留一條,但往往只用它來返回不重覆記錄的條數,而不是用它來返回不重記錄的所有值。 ...
  • 上一篇介紹了邏輯備份工具mysqldump,本文將通過應用更為普遍的物理備份工具xtrabackup來演示數據備份及恢復的第二篇內容。 1. xtrabackup 工具的安裝 1.1 安裝依賴包 /* xtrabackup 的使用需要安裝相關的依賴包 否則使用過程中會報相關錯誤 */ yum ins ...
  • MySQL 字元串截取函數:left(), right(), substring(), substring_index()。還有 mid(), substr()。 其中,mid(), substr() 等價於 substring() 函數,substring() 的功能非常強大和靈活。 1. 字元串 ...
  • MySQL資料庫 前言: 隨著時代的進步,大數據也逐漸走進大家的生活中,成為大家密不可分的一樣東西。因此,作為程式員的我們,要學習並會使用資料庫。 什麼是資料庫? 資料庫就是一個文件系統,通過標準的SQL語句獲取數據 MySQL資料庫又是什麼呢? MySQL資料庫是一個關係型資料庫。 (關係型資料庫 ...
  • 7.關於pyinstaller打包生成exe的方法 安裝pip 、 pyinstaller 在pycharm 的Terminal視窗中輸入 註:輸入參數的含義 F 表示生成單個可執行文件 w 表示去掉控制台視窗,這在GUI界面時非常有用。不過如果是命令行程式的話那就把這個選項刪除吧! p 表示你自己 ...
  • 經常提到資料庫的事務,那你知道資料庫還有事務隔離的說法嗎,事務隔離還有隔離級別,那什麼是事務隔離,隔離級別又是什麼呢?本文就幫大家梳理一下。 MySQL 事務 本文所說的 MySQL 事務都是指在 InnoDB 引擎下,MyISAM 引擎是不支持事務的。 資料庫事務指的是一組數據操作,事務內的操作要 ...
  • 不適配深色模式 直接在info新加一個欄位 設置值為 適配深色模式 適配深色模式info裡面的那個欄位就不用添加了 但是需要在每個 裡面增加下麵的這個方法 在這個方法里去判斷和更改當前界面所有元素的顏色 我專門做了一個單例,把應用程式中的所有顏色都單獨保存起來 還有兩個方法,分別是把所有的顏色改成與 ...
  • 1.win10安裝ubuntu 18.04或Ubuntu發行版 搜索:Microsoft Store >搜索:Ubuntu //下載即可 >下載完之後安裝,啟動即可. 搜索:ubuntu啟動即可. 註意:源最好不要替換 2.安裝所需的庫 安裝emacs的cscope + autocomplete需要 ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...