50天iOS挑戰(zhàn)(Swift) - 第2天:手勢(shì)操控彈性按鈕
50天,每天一個(gè)Swift語(yǔ)言的iOS練手項(xiàng)目,覆蓋iOS開發(fā)的主要知識(shí)。貴在堅(jiān)持,重在思考
文章列表:http://www.itdecent.cn/nb/13566182
Github項(xiàng)目:https://github.com/Minecodecraft/50DaysOfSwift
簡(jiǎn)介
本項(xiàng)目為制作一個(gè)可手勢(shì)操作的按鈕,支持修改顏色、手勢(shì)放大縮小、點(diǎn)擊切換等操作,并對(duì)按鈕添加彈性正反饋。
主要知識(shí)點(diǎn): Animation、Layer、Button、UIGestureRecongnizer
過(guò)程
1、 界面UI
首先是對(duì)iOS圖層基礎(chǔ)使用的練習(xí)。使用代碼設(shè)計(jì)背景,這里用到了CAGradientLayer來(lái)創(chuàng)建漸變圖層。
let backgroundLayer = CAGradientLayer()
backgroundLayer.colors = [UIColor.yellow.cgColor, UIColor.white.cgColor]
backgroundLayer.startPoint = CGPoint(x: 0.5, y: 0)
backgroundLayer.endPoint = CGPoint(x: 0.5, y: 1)
backgroundLayer.frame = self.view.bounds
self.view.layer.addSublayer(backgroundLayer)
添加子圖層使用layer屬性的addSublayer()方法
2、 手勢(shì)操作
這里簡(jiǎn)單介紹手勢(shì)操作對(duì)應(yīng)的類,具體使用方法后面專開文章講解。
- 點(diǎn)擊手勢(shì):UITapGestureRecognizer
- 長(zhǎng)按手勢(shì):UILongPressGestureRecognizer
- 拖拽手勢(shì):UIPanGestureRecognizer
- 捏合手勢(shì):UIPinchGestureRecognizer
- 旋轉(zhuǎn)手勢(shì):UIRotationGestureRecognizer
- 滑動(dòng)手勢(shì):UISwipeGestureRecognizer
其中捏合、旋轉(zhuǎn)手勢(shì)需要遵守UIGestureRecognizerDelegate代理類
3、 響應(yīng)手勢(shì)的動(dòng)畫
- 控件旋轉(zhuǎn)抖動(dòng)
通過(guò)設(shè)置動(dòng)畫過(guò)程來(lái)實(shí)現(xiàn)
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
// 周期
animation.duration = 0.08
animation.repeatCount = 2
// 抖動(dòng)幅度
animation.values = [0, -self.mainButton.frame.width/4, self.mainButton.frame.width/4, 0]
// 恢復(fù)原樣
animation.autoreverses = true
// 設(shè)置抖動(dòng)中心
self.mainButton.layer.add(animation, forKey: "rotation.x")
- 控件抖動(dòng)
控件抖動(dòng)通過(guò)設(shè)置動(dòng)畫過(guò)程來(lái)實(shí)現(xiàn):
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
// 周期
animation.duration = 0.08
animation.repeatCount = 4
// 抖動(dòng)角度
animation.fromValue = (-M_1_PI)
animation.toValue = (M_1_PI)
// 恢復(fù)原樣
animation.autoreverses = true
// 設(shè)置抖動(dòng)中心
self.mainButton.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.mainButton.layer.add(animation, forKey: "rotation.z")
- 控件拖動(dòng)
控件拖動(dòng)通過(guò)獲取點(diǎn)擊起點(diǎn)和位移終點(diǎn),并計(jì)算相對(duì)位移量實(shí)現(xiàn)。
注意,translation函數(shù)是獲取起點(diǎn),而location函數(shù)是獲取終點(diǎn)。起初仿照油管上一個(gè)作者的做法利用location來(lái)實(shí)現(xiàn),會(huì)導(dǎo)致開始單擊時(shí)出現(xiàn)一個(gè)跳變的位置。所以拖動(dòng)位置的計(jì)算是要用起點(diǎn)計(jì)算相對(duì)位移的方式來(lái)實(shí)現(xiàn)的。
// 獲取坐標(biāo)并修改
let movePoint = panGes.translation(in: self.view)
var curPoint = self.mainButton.center
curPoint.x += movePoint.x
curPoint.y += movePoint.y
self.mainButton.center = curPoint
- 控件旋轉(zhuǎn)
添加手勢(shì)
let rotationGes = UIRotationGestureRecognizer(target: self, action: #selector(rotationAction(_:)))
rotationGes.delegate = self
self.mainButton.addGestureRecognizer(rotationGes)
添加手勢(shì)后處理:
let rotationR = rotationGes.rotation
self.mainButton.transform = self.mainButton.transform.rotated(by: rotationR)
即可完成旋轉(zhuǎn)操作
- 控件縮放
控件縮放則是利用手勢(shì)監(jiān)視器的比例屬性來(lái)進(jìn)行比例變化,從而變化大小,代碼很簡(jiǎn)單。
let pinchScale = pinchGes.scale
self.mainButton.transform = self.mainButton.transform.scaledBy(x: pinchScale, y: pinchScale);
一點(diǎn)小小的補(bǔ)充
1.默認(rèn)情況是不能同時(shí)進(jìn)行旋轉(zhuǎn)和縮放操作的,但是這樣又很炫。讓UIGestureRecognizerDelegate的對(duì)應(yīng)方法返回真,即可允許同時(shí)響應(yīng)多個(gè)手勢(shì)。
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
2.項(xiàng)目源碼地址 GitHub,歡迎大家前來(lái)支持,希望可以隨手留個(gè)Star。多謝~