工作中經(jīng)常會遇到彈出視圖的需求芭逝,通常還會要求有一些動效塌碌,之前使用OC寫代碼的時候,使用的是STModal
旬盯,現(xiàn)在使用Swift
台妆,就決定自己來寫一個。目前僅僅是寫了一個彈出視圖的控制器胖翰,還非常的簡陋,后期再來添加自定義Alert
視圖等功能萨咳。
很多地方參考了STModal
搂漠,當然也做了一些修改和優(yōu)化。
兩種實現(xiàn)方式某弦,核心代碼是一樣的桐汤,不同點在于:
- 將
GJModal
定義為單例,這種方式適用于靶壮,所有的彈出視圖的彈出方式都是一樣的怔毛。 - 將
GJModalWindow
定義為單例,這種方式適用于腾降,彈出視圖有多種彈出方式拣度。
效果圖:
效果圖
使用方式
- 第一種實現(xiàn)方式
GJModal.modal.isHideWhenTouchOutside = true
GJModal.modal.show(contentView: view, animated: true)
- 第二種實現(xiàn)方式
let modal = GJModal.init(isHideWhenTouchOutside: false)
modal.show(contentView: view, animated: true)
核心代碼
初始化
init(isHideWhenTouchOutside: Bool) {
containerView.addSubview(bgView)
self.isHideWhenTouchOutside = isHideWhenTouchOutside
if isHideWhenTouchOutside {
let tap = UITapGestureRecognizer(target: self, action: #selector(backgroundTaped))
bgView.addGestureRecognizer(tap)
}
}
彈出視圖
func show(contentView: UIView, animated: Bool) {
self.contentView = contentView
containerView.addSubview(self.contentView)
self.contentView.center = containerView.center
window.modalsStack.append(self)
window.addSubview(containerView)
if isShowBgView {
window.isHidden = false
UIView.animate(withDuration: bgViewShowDuration, animations: {
self.bgView.backgroundColor = UIColor.black
self.bgView.alpha = self.bgViewAlpha
})
}
isShowAnimated = animated
showAnimation()
}
private func showAnimation() {
if isShowAnimated {
let d1 = 0.2
let d2 = 0.15
let animation2 = CABasicAnimation(keyPath: "transform")
animation2.autoreverses = true
animation2.duration = d1
animation2.beginTime = 0
animation2.fromValue = NSValue(caTransform3D: CATransform3DMakeScale(0.4, 0.4, 1))
animation2.toValue = NSValue(caTransform3D: CATransform3DMakeScale(1.2, 1.2, 1))
let animation3 = CABasicAnimation(keyPath: "transform")
animation3.autoreverses = true
animation3.duration = d2
animation3.beginTime = d1
animation3.fromValue = NSValue(caTransform3D: CATransform3DMakeScale(1.2, 1.2, 1))
animation3.toValue = NSValue(caTransform3D: CATransform3DMakeScale(1, 1, 1))
let group = CAAnimationGroup()
group.duration = d2+d1
group.animations = [animation2,animation3]
self.contentView.layer.add(group, forKey: nil)
UIView.animate(withDuration: bgViewShowDuration, animations: {
self.contentView.alpha = 1
})
} else {
UIView.animate(withDuration: bgViewShowDuration, animations: {
self.contentView.alpha = 1
})
}
}
移除視圖
func hide(animated: Bool) -> Void {
if contentView != nil {
isHideAnimated = animated
hideAnimation()
}
}
private func hideAnimation() {
if isHideAnimated {
let d1 = 0.2
let d2 = 0.15
UIView.animate(withDuration: d1, animations: {
self.contentView.transform = CGAffineTransform.init(scaleX: 1.2, y: 1.2)
}) { (finished) in
UIView.animate(withDuration: d2, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.contentView.alpha = 0
self.contentView.transform = CGAffineTransform.init(scaleX: 0.2, y: 0.2)
}, completion: { (finished) in
self.window.isHidden = true
self.containerView.removeFromSuperview()
self.window.modalsStack.removeAll()
})
}
} else {
UIView.animate(withDuration: bgViewShowDuration, animations: {
self.contentView.alpha = 0
self.containerView.removeFromSuperview()
self.window.modalsStack.removeAll()
})
}
if isShowBgView {
UIView.animate(withDuration: bgViewShowDuration, animations: {
self.bgView.backgroundColor = UIColor.clear
self.bgView.alpha = 0
})
}
}
遇到的問題
- 把視圖添加到
window
上以后,視圖的點擊效果無法觸發(fā)螃壤。自己感覺可能是因為點擊手勢的Target
與window
之間不存在引用關系抗果,然后就在GJModalWindow
里加了一個modalsStack
的屬性,用來添加GJModal
奸晴。不知道具體原因是不是我想的這個冤馏,最終結果是實現(xiàn)了想要的點擊效果。 - 在做視圖彈出動畫的時候寄啼,本來想簡單的使用
View
的transform
屬性來實現(xiàn)逮光,但是發(fā)現(xiàn)如果你要彈出的視圖是使用Autolayout
來布局的話代箭,彈出后會造成布局混亂的問題,所以最后采用了CAAnimation
動畫涕刚。 - 在使用
CAAnimation
動畫的時候嗡综,發(fā)現(xiàn)動畫總是同時觸發(fā),不是我想要的一個動畫結束后再執(zhí)行另一個動畫杜漠。然后采用了CAAnimationGroup
來實現(xiàn)動畫組极景,通過設置Animation
的beginTime
來控制動畫的執(zhí)行。
版本記錄
-
V1.0
僅實現(xiàn)了彈出視圖控制器驾茴。 2017.7.24