일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- GIT
- it
- listview
- Swift
- SwiftGen
- keyWindow
- OSLog
- xcode
- IOS
- ToDoRim
- pubspec.yaml
- designPattern
- toyproject
- COMMIT
- pubspec
- protocol
- basic
- github
- Widget
- dart
- reetcode
- swiftlint
- UIAccessibility
- algorithm
- Leetcode
- enumerations
- tip
- flutter
- Equatable
- Extentsion
- Today
- Total
수니의 개발새발
[iOS/Swift] Custom Animation Popup 만들기 (with. Storyboard) 본문
📌 이번 글은
UIView.animate를 사용하여, Custom Animation Popup을 만드는 방법입니다.
해당 포스팅은 Storyboard intreface 기반 Swift 프로젝트입니다.
1. UIWindow+Ext.swift 준비
팝업 호출 뷰의 디폴트 값을 최상위 뷰로 하기 위해, 최상위 뷰 컨트롤러를 얻는 UIWindow Extension을 먼저 만들어 줍니다.
참고 포스팅 : [iOS/Swift] 최상위에 있는 뷰 컨트롤러 얻기
[iOS/Swift] 최상위에 있는 뷰컨트롤러 얻기
개발하면서 앱의 최상위 뷰 컨트롤러를 찾아야 할 일이 종종 있어요. 처음에는 최상위 뷰에 얼럿을 띄우기 위해 작업을 했지만, 한번 extension으로 빼놓으니 1) 웹뷰 통신(브릿지 호출)으로 뷰 이
sunidev.tistory.com
import UIKit
extension UIWindow {
public var visibleViewController: UIViewController? {
return self.visibleViewControllerFrom(vc: self.rootViewController)
}
/**
# visibleViewControllerFrom
- Author: suni
- Date:
- Parameters:
- vc: rootViewController 혹은 UITapViewController
- Returns: UIViewController?
- Note: vc내에서 가장 최상위에 있는 뷰컨트롤러 반환
*/
public func visibleViewControllerFrom(vc: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nc = vc as? UINavigationController {
return self.visibleViewControllerFrom(vc: nc.visibleViewController)
} else if let tc = vc as? UITabBarController {
return self.visibleViewControllerFrom(vc: tc.selectedViewController)
} else {
if let pvc = vc?.presentedViewController {
return self.visibleViewControllerFrom(vc: pvc)
} else {
return vc
}
}
}
}
2. SnapKit 코코아팟 설치
스토리보드가 아닌 소스 코드로 Auto Layout을 컨트롤할 때, 쉽게 하기 위해 SnapKit을 설치하여 사용합니다.
SnapKit은 iOS 및 OS X에서 Auto Layout을 쉽게 하기 위한 DSL(Domain-specific Language)입니다.
Podfile을 생성하여 SnapKit을 추가하고 설치합니다.
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'SNPopup' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for SNPopup
######################## UI
# AutoLayout 관련
pod 'SnapKit'
end
참고 포스팅 : [iOS/Xcode] CocoaPods(코코아팟) 사용하기
[iOS/Xcode] CocoaPods(코코아팟) 사용하기
CocoaPods는 Swift 및 Objective-C 코코아 프로젝트의 종속성 관리자입니다. 28,000개가 넘는 라이브러리를 가지고 있으며 170만 개가 넘는 응용 프로그램(앱)에서 사용되고 있습니다. CocoaPod은 프로젝트를
sunidev.tistory.com
3. BasePopVC.swift 생성
먼저, UIViewController를 상속받는 BasePopVC를 생성합니다.
BasePopVC.swift는 Custom Animation Popup 기능을 만들어, 필요한 팝업 클래스에 상속할 클래스입니다.
class BasePopVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.layoutIfNeeded()
}
}
4. 애니메이션 관련 enum 생성
BasePopVC.swift에 애니메이션에 필요한 enum을 선언합니다.
/**
# (E) PopupPosition
- Author: suni
- Date:
- Note: PopupVC에 애니메이션 시작 포지션을 정하는 enum
*/
enum PopupPosition: String {
case top = "Top"
case bottom = "Bottom"
case left = "Left"
case right = "Rigth"
case center = "Center"
case none = ""
}
/**
# (E) PopupType
- Author: suni
- Date:
- Note: PopupVC에 애니메이션 타입을 모아둔 enum
*/
enum PopupType: String {
case fadeInOut = "Fade In Out"
case move = "Move"
case none = ""
}
5. 상수 선언
애니메이션 시간도 선언합니다.
public let ANIMATION_DURATION: TimeInterval = 0.5
6. BasePopVC.swift
Custom Animation Popup 기능을 수행하는 BasePopVC 클래스 소스입니다.
class BasePopVC: UIViewController {
// popup dim 투명도
private final let DIM_ALPHA: CGFloat = 0.3
// popup dim view
@IBOutlet weak var vDim: UIView!
// popup content view
@IBOutlet weak var vPopup: UIView!
// popup animation type
private var type: PopupType = .none
// popup push start position
private var position: PopupPosition = .none
override func viewDidLoad() {
super.viewDidLoad()
self.view.layoutIfNeeded()
}
}
extension BasePopVC {
/**
# showAnim
- Author: suni
- Date:
- Parameters:
- vc : 팝업을 노출할 뷰컨트롤러
- type : 팝업의 애니메이션 타입
- position : 팝업 애니메이션 시작 포지션
- parentAddView : 해당 뷰컨트롤러의 뷰를 적용할 부모 뷰컨트롤러의 뷰
- completeion : 해당 화면 노출 애니메이션이 완료된 이후에 부모 뷰컨트롤러에서 처리할 클로저
- Returns:
- Note: 팝업 화면을 애니메이션을 넣어서 보이는 함수
*/
func showAnim(vc: UIViewController? = UIApplication.shared.keyWindow?.visibleViewController, type: PopupType = .fadeInOut, position: PopupPosition = .none, parentAddView: UIView?, _ completion: @escaping ()->()) {
guard let currentVC = vc else {
completion()
return
}
var pView = parentAddView
if pView == nil {
pView = vc?.view
}
guard let parentView = pView else {
completion()
return
}
self.type = type
self.position = position
currentVC.addChild(self)
self.view.translatesAutoresizingMaskIntoConstraints = false
parentView.addSubview(self.view)
self.view.snp.makeConstraints {
$0.edges.equalToSuperview()
}
switch type {
case .fadeInOut:
self.vDim.alpha = 0.0
self.vPopup.alpha = 0.0
self.view.layoutIfNeeded()
UIView.animate(withDuration: ANIMATION_DURATION/2) { [weak self] in
if let _self = self {
_self.vDim.alpha = _self.DIM_ALPHA
}
} completion: { (complete) in
UIView.animate(withDuration: ANIMATION_DURATION/2) { [weak self] in
if let _self = self {
_self.vPopup.alpha = 1.0
}
} completion: { (complete) in
completion()
}
}
case .move:
self.vDim.alpha = 0.0
let originalTransform = self.vPopup.transform
var moveX: CGFloat = 0.0
var moveY: CGFloat = 0.0
switch position {
case .top:
moveX = 0.0
moveY = -(self.vPopup.frame.maxY)
case .bottom:
moveX = 0.0
moveY = UIScreen.main.bounds.size.height - self.vPopup.frame.minY
case .left:
moveX = -(self.vPopup.frame.maxX)
moveY = 0.0
case .right:
moveX = UIScreen.main.bounds.size.width - self.vPopup.frame.minX
moveY = 0.0
case .center:
moveX = 0.0
moveY = 0.0
default:
break
}
let hideTransform = originalTransform.translatedBy(x: moveX, y: moveY)
self.vPopup.transform = hideTransform
self.vPopup.alpha = 0.0
UIView.animate(withDuration: ANIMATION_DURATION) { [weak self] in
if let _self = self {
_self.vPopup.transform = originalTransform
_self.vPopup.alpha = 1.0
_self.vDim.alpha = _self.DIM_ALPHA
}
} completion: { (complete) in
completion()
}
default:
completion()
}
}
/**
# hideAnim
- Author: suni
- Date: 20.08.19
- Parameters:
- type : 팝업의 애니메이션 타입
- position : 팝업 애니메이션 숨김 포지션
- completeion : 해당 화면 숨김 애니메이션이 완료된 이후에 부모 뷰컨트롤러에서 처리할 클로저
- Returns:
- Note: 팝업 화면을 애니메이션을 넣어서 숨기는 함수
*/
func hideAnim(type: PopupType = .none, position: PopupPosition = .none, _ completion: @escaping ()->()) {
DispatchQueue.main.async {
switch self.type {
case .fadeInOut:
UIView.animate(withDuration: ANIMATION_DURATION/2, animations: { [weak self] in
if let _self = self {
_self.vPopup.alpha = 0.0
}
}) { (complete) in
UIView.animate(withDuration: ANIMATION_DURATION/2, animations: { [weak self] in
self?.vDim.alpha = 0.0
}) { [weak self] complete in
if let _self = self {
_self.view.removeFromSuperview()
_self.removeFromParent()
}
}
}
break
case .move:
let originalTransform = self.vPopup.transform
var moveX: CGFloat = 0.0
var moveY: CGFloat = 0.0
switch position {
case .top:
moveX = 0.0
moveY = -(self.vPopup.frame.maxY)
case .bottom:
moveX = 0.0
moveY = UIScreen.main.bounds.size.height - self.vPopup.frame.minY
case .left:
moveX = -(self.vPopup.frame.maxX)
moveY = 0.0
case .right:
moveX = UIScreen.main.bounds.size.width - self.vPopup.frame.minX
moveY = 0.0
case .center:
moveX = 0.0
moveY = 0.0
default:
break
}
let hideTransform = originalTransform.translatedBy(x: moveX, y: moveY)
UIView.animate(withDuration: ANIMATION_DURATION, animations: { [weak self] in
if let _self = self {
_self.vDim.alpha = 0.0
_self.vPopup.alpha = 0.0
_self.vPopup.transform = hideTransform
}
}) { [weak self] complete in
if let _self = self {
_self.view.removeFromSuperview()
_self.removeFromParent()
completion()
}
}
break
default:
completion()
}
}
}
@IBAction func btnCancelPressed(_ sender: UIButton) {
self.hideAnim(type: self.type, position: self.position) {
}
}
@IBAction func btnCompletePressed(_ sender: UIButton) {
self.hideAnim(type: self.type, position: self.position) {
}
}
}
6. 사용 예제
BasePopVC를 상속받는 커스텀 팝업 클래스를 생성합니다.
import UIKit
class SNPopVC: BasePopVC {
override func viewDidLoad() {
super.viewDidLoad()
}
}
Storyboard에서 팝업을 커스텀하여 만든 뒤, Custom Class > Class에 팝업의 클래스명을 입력합니다.
Identity > StoryboardID에 클래스명을 입력한 뒤, Use Storyboard ID를 입력합니다.
BasePopVC에 vDim과 vPopup을 연결합니다.
BasePopVC에 btnCompleteProssed Action을 연결합니다.
이제 아래 코드로 팝업을 호출하면 됩니다.
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let popVC = storyBoard.instantiateViewController(withIdentifier: "SNPopVC") as! SNPopVC
popVC.showAnim(vc: self, type: .move, position: .bottom, parentAddView: self.view) { }
👩🏻💻 프로젝트 예제 소스
GitHub - SuniDev/CustomAnimationPopup-storyboard: Custom Animation Popup 만들기 (with. storyboard)
Custom Animation Popup 만들기 (with. storyboard). Contribute to SuniDev/CustomAnimationPopup-storyboard development by creating an account on GitHub.
github.com
'iOS - Swift' 카테고리의 다른 글
[iOS/Swift] 특정 상황에 VoiceOver 알림 등록하기 (0) | 2021.12.29 |
---|---|
[iOS/Swift] iOS13 에서 라이트모드(또는 다크모드)만 지원하기 (turn off darkmode) (0) | 2021.12.29 |
[iOS/Swift] UIAlertController를 사용하여 Alert 만들기 (0) | 2021.12.29 |
[iOS/Swift] 최상위에 있는 뷰컨트롤러 얻기 (0) | 2021.12.29 |
[iOS/Swift] xib로 TableView 만들기 (TableViewCell Select Highlight) (0) | 2021.12.28 |