Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- HIG
- Observable
- map
- 리팩토링
- Clean Code
- uitableview
- collectionview
- Protocol
- Xcode
- 리펙터링
- MVVM
- 클린 코드
- combine
- 리펙토링
- swiftUI
- tableView
- UICollectionView
- Human interface guide
- 스위프트
- ribs
- ios
- rxswift
- UITextView
- uiscrollview
- 애니메이션
- RxCocoa
- SWIFT
- clean architecture
- swift documentation
- Refactoring
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 4. Hero - UIViewController간의 화면전환 애니메이션 프레임워크 (셀 이동, 뷰 이동 애니메이션 예시) 본문
iOS framework
[iOS - swift] 4. Hero - UIViewController간의 화면전환 애니메이션 프레임워크 (셀 이동, 뷰 이동 애니메이션 예시)
jake-kim 2022. 2. 26. 22:041. Hero - UIViewController간의 화면전환 애니메이션 프레임워크 (개념, UIPenGestureRecognizer)
2. Hero - UIViewController간의 화면전환 애니메이션 프레임워크 (modal)
3. Hero - UIViewController간의 화면전환 애니메이션 프레임워크 (편한 extension, hero.id를 이용한 애니메이션)
4. Hero - UIViewController간의 화면전환 애니메이션 프레임워크 (셀 이동, 뷰 이동 애니메이션 예시)
애니메이션 아이디어
- 회색 뷰: 첫 번째 뷰와 두 번째 뷰의 hero.id를 같도록 설정
- 빨간색 cell 애니메이션 설정
- cell에는 단순히 hero.modifiers라는 프로퍼티로 애니메이션 설정이 간편하게 가능
collectionView.hero.modifiers = [.cascade]
...
// in cellForItemAt 델리게이트
cell.hero.modifiers = [.fade, .scale(0.5)]
첫 번째 뷰 준비 (아직 Hero 미적용)
ViewController.swift
import UIKit
class ViewController: UIViewController {
private let button: UIButton = {
let button = UIButton()
button.setTitle("open", for: .normal)
button.setTitleColor(.white, for: .normal)
button.setTitleColor(.lightGray, for: .highlighted)
button.backgroundColor = .systemGray
button.layer.cornerRadius = 14
button.layer.cornerCurve = .continuous
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.button)
self.button.translatesAutoresizingMaskIntoConstraints = false
self.button.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -40).isActive = true
self.button.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -40).isActive = true
self.button.widthAnchor.constraint(equalToConstant: 50).isActive = true
self.button.heightAnchor.constraint(equalToConstant: 50).isActive = true
self.button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
}
@objc private func didTapButton() {
let vc2 = VC2()
self.navigationController?.pushViewController(vc2, animated: true)
}
}
두 번째 뷰 준비
VC2.swift
import UIKit
class VC2: UIViewController {
private enum Constants {
static let itemSize = CGSize(width: 60, height: 72)
static let lineSpacing = 4.0
static let minimumInteritemSpacing = 0.0
static let collectionViewContentInset = UIEdgeInsets(top: 10, left: 6, bottom: 10, right: 6)
}
private let titleLabel: UILabel = {
let label = UILabel()
label.textColor = .white
label.backgroundColor = .systemGray
label.textAlignment = .center
label.text = "예제 타이틀"
return label
}()
private let collectionViewFlowLayout: UICollectionViewFlowLayout = {
let view = UICollectionViewFlowLayout()
view.itemSize = Constants.itemSize
view.minimumLineSpacing = Constants.lineSpacing
view.minimumInteritemSpacing = Constants.minimumInteritemSpacing
return view
}()
private lazy var collectionView: UICollectionView = {
let view = UICollectionView(frame: .zero, collectionViewLayout: self.collectionViewFlowLayout)
view.contentInset = Constants.collectionViewContentInset
view.backgroundColor = UIColor.clear
view.register(MyCell.self, forCellWithReuseIdentifier: "MyCell")
return view
}()
private var dataSource: [Int] { (0...50).map { $0 } }
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.view.addSubview(self.collectionView)
self.collectionView.translatesAutoresizingMaskIntoConstraints = false
self.collectionView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
self.collectionView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
self.collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -56).isActive = true
self.collectionView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 400).isActive = true
self.collectionView.dataSource = self
self.view.addSubview(self.titleLabel)
self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
self.titleLabel.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 120).isActive = true
self.titleLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
self.titleLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
self.titleLabel.heightAnchor.constraint(equalToConstant: 60).isActive = true
}
}
extension VC2: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
self.dataSource.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell
cell.prepare(text: "\(self.dataSource[indexPath.item])")
return cell
}
}
final class MyCell: UICollectionViewCell {
private let label: UILabel = {
let label = UILabel()
label.textColor = .white
label.textAlignment = .center
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.backgroundColor = .red
self.contentView.addSubview(self.label)
self.label.translatesAutoresizingMaskIntoConstraints = false
self.label.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
self.label.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
self.label.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
self.label.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
self.contentView.layer.cornerRadius = 14
self.contentView.layer.cornerCurve = .continuous
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
super.prepareForReuse()
self.prepare(text: nil)
}
func prepare(text: String?) {
self.label.text = text
}
}
회색 뷰에 애니메이션 적용
- 첫 번째 뷰
- 주의사항) navigationController에도 애니메이션 적용하려면 navigationController.isHeroEnabled 활성화 필요
// ViewController.swift
// in viewDidLoad()
self.navigationController?.isHeroEnabled = true
self.button.isHeroEnabled = true
self.button.hero.id = "myAnimation"
- 두 번째 뷰
// VC2.swift
label.isHeroEnabled = true
label.hero.id = "myAnimation"
셀에 애니메이션 적용
// VC2.swift
// collectionView에 hero 애니메이션 적용
self.collectionView.hero.modifiers = [.cascade]
// in cellForItemAt 델리게이트
cell.hero.modifiers = [.fade, .scale(0.5)]
'iOS framework' 카테고리의 다른 글
Comments