在很多人的心目中iPhone的經典機型應該是iPhone4,精湛的工藝、完美的屏幕配上暗色的鎖屏壁紙,看著屏幕底部閃爍的slide to unlock字樣,高逼格彰顯無遺。時至今日無論iPhone機身樣式如何改變,屏幕尺寸如何改變,iOS系統如何改變,唯有鎖屏底部閃爍的滑動來解鎖不變。它的動畫效果是如何實現的呢,這篇文章會告訴你們答案。
新建一個應用名為GradientAnimation,打開Main.storyboard,將ViewController的View背景色設置為灰黑色,拖一個UIView到ViewController中,將其顏色設置為無色并設置好布局約束:
接著我們拖一個UILabel到剛才拖入的UIView中,設置高寬等同于它的父視圖:
我對該UILabel的屬性設置如下:
之后,我們在ViewController中添加UIView和UILabel的Outlet:
接下來回到ViewController.swift,我們添加一個常量屬性gradientLayer:
[cpp] view plaincopy
let gradientLayer = CAGradientLayer()
這里出現了CALayer的另一個子類CAGradientLayer,這個類的作用就是能在Layer上繪制出漸變顏色的效果,然后在viewDidLoad()中添加如下代碼:
[cpp] view plaincopy
gradientLayer.bounds = CGRect(x: 0, y: 0, width: backgroundView.frame.size.width, height: backgroundView.frame.size.height)
gradientLayer.position = CGPoint(x: backgroundView.frame.size.width/2, y: backgroundView.frame.size.height/2)
上述兩行的代碼是設置Layer的大小及位置,這在上兩篇文章中已經講過,這里就不再累贅了。接著我們繼續添加兩行代碼:
[cpp] view plaincopy
gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
既然CAGradientLayer可以繪制出漸變顏色的效果,那自然有顏色漸變的方向,所以這兩行代碼的作用就是設置顏色漸變的起始點和結束點,這兩個屬性共同決定了顏色漸變的方向:
從上面的示意圖中可以看出,CAGradientLayer是通過起始點和結束點的坐標位置來決定顏色漸變的方向的,起始點的默認值是(0.5, 0),結束點的默認值是(0.5, 1),也就是說默認的顏色漸變方向是沿垂直中線從上往下漸變的,我們在這里將它改成了沿水平中線從左往右漸變。
接下來我們設置CAGradientLayer的漸變顏色,接著添加如下代碼:
[cpp] view plaincopy
gradientLayer.colors = [
UIColor.blackColor().CGColor,
UIColor.whiteColor().CGColor,
UIColor.blackColor().CGColor
]
CAGradientLayer的colors屬性類型是一個數組[AnyObject],這就意味著我們可以實現多個顏色的漸變效果,并且可以規定各個顏色的順序。不過在我們這個示例中我們只需要兩種顏色,不過需要注意的是雖然顏色只有兩種,但是整個顏色漸變的過程中有三個原色點,那就是黑、白、黑,所以我們在這個數組中也需要按照原色點的數量和順序添加相應的顏色,哪怕顏色都是一樣的。
我們既然設置了漸變的三個原色,那么就要對這原色出現的位置進行設置,接著添加如下代碼:
[cpp] view plaincopy
gradientLayer.locations = [0.2, 0.5, 0.8]
從上述代碼中不難看出,我們將個黑色原色出現的位置設置在了整個Layer長度的十分之二的位置,第二個白色原色在中間,第三個黑色原色在十分之八的位置:
設置完CAGradientLayer的相關屬性后,我們將gradientLayer添加到backgroundView的Layer中:
[cpp] view plaincopy
backgroundView.layer.addSublayer(gradientLayer)
現在我們編譯運行一下代碼看看效果:

接下來我們需要讓顏色漸變動起來,先創建一個方法gradinetAnimate(),在方法中添加如下代碼:
[cpp] view plaincopy
let gradient = CABasicAnimation(keyPath: "locations")
gradient.fromValue = [0, 0, 0.25]
gradient.toValue = [0.75, 1, 1]
gradient.duration = 2.5
gradient.repeatCount = HUGE
gradientLayer.addAnimation(gradient, forKey: nil)
首先,創建了一個locations類型的動畫實例gradient,將fromValue屬性,也就是起始位置的屬性設置為[0, 0, 0.25],它的意思是動畫開始前,黑色、白色這兩個原色的位置在整個Layer的前端,第二個黑色原色在0.25的位置:
而結束位置toValue,將白色和第二個黑色原色位置設置在整個Layer的末端,個黑色原色在0.75的位置:
從圖中可以看出,此時整個Layer都變成了黑色。也就是說,在整個動畫中,個黑色原色從0移動到0.75的位置,白色原色從0移動到1的位置,第二個黑色原色從0.25移動到1的位置。然后設置動畫時間為2.5秒,無線重復次數,后將gradient動畫添加到gradientLayer中。我們在viewDidAppear()方法中調用該動畫方法gradientAnimate(),編譯運行看看效果:
動畫效果還不賴,但是如何將顏色漸變的動畫作用在UILabel的文字上呢?其實非常簡單,就是讓UILabel上的文字稱為CAGradientLayer的遮罩即可,我們先在ViewController中定義一個常量:
[cpp] view plaincopy
var text = "DevTalking"
然后在viewDidAppear()中的gradientAnimate()方法之前添加如下代碼:
[cpp] view plaincopy
textLabel.text = text
gradientLayer.mask = textLabel.layer
我們再編譯運行代碼看看效果:
到目前為止,鎖屏中滑動來解鎖的動畫效果就完成了,這個動畫效果在Facebook的Paper應用中也有使用。下一節,我們在該動畫的基礎上對文字再加點小動畫。
首先我們打開AppDelegate.swift,在import UIKit下面添加一個方法:
[cpp] view plaincopy
func delay(seconds seconds: Double, completion:()->()) {
let intervalTime = dispatch_time(DISPATCH_TIME_NOW, Int64( Double(NSEC_PER_SEC) * seconds ))
dispatch_after(intervalTime, dispatch_get_main_queue(), {
completion()
})
}
這個方法的作用如其名稱一樣,是一個延遲方法,該方法的個參數是想要延遲的時間,第二個參數是一個閉包,也就是延遲的主體。這個方法用到了GCD的知識,dispatch_time主要是用于創建一個類型為dispatch_time_t的相對時間,它的個參數指的是起始時間,一般都是用預定義的DISPATCH_TIME_NOW作為個參數的值,代表當前的時間。第二個參數代表時間間隔,注意這個參數需要的時間單位是納秒,所以我們使用預定義的NSEC_PER_SEC納秒單位乘以希望間隔的秒數。
dispatch_after用于在隊列中定時執行任務,當你想在一段時間后執行一個任務,那么就可以用這個函數。該函數的個參數指定延遲的時間,第二個參數指定一個隊列,用于添加任務,第三個參數是一個閉包,也就是要執行的任務。
然后回到ViewController.swift,添加如下方法:
[cpp] view plaincopy
func textAnimate(text: String) {
if text.characters.count > 0 {
textLabel.text = "\(textLabel.text!)\(text.substringToIndex(text.startIndex.successor()))"
delay(seconds: 0.4, completion: {
self.textAnimate(text.substringFromIndex(text.startIndex.successor()))
})
}
}
該方法的參數text就是UILabel中要顯示的文字內容。substringToIndex(_ to: Int)方法的作用是從字符串的開頭一直截取到指定的位置,但不包括該指定位置的字符。text.startIndex.successor()這句意思是從text的起始位置開始取后面的一個字符。substringFromIndex(_ from: Int)方法的作用是以指定位置并包括指定位置的字符開始,一直截取之后的全部字符。所以整個方法的作用是每隔0.4秒顯示一個字符,直到將整個字符串顯示完。后在viewDidAppear()中注釋掉textLabel.text = text這行代碼,并在方法后調用textAnimate(text)方法。編譯運行代碼看看終效果:
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。