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 | 31 |
Tags
- Refactoring
- map
- Observable
- ios
- tableView
- 리펙토링
- 리펙터링
- 리팩토링
- collectionview
- MVVM
- rxswift
- Protocol
- RxCocoa
- 애니메이션
- swift documentation
- Clean Code
- combine
- Human interface guide
- ribs
- SWIFT
- swiftUI
- Xcode
- uitableview
- 클린 코드
- HIG
- uiscrollview
- UITextView
- 스위프트
- clean architecture
- UICollectionView
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 1. long press gesture와 애니메이션 - 드래그 구현 방법 (snapshotView, CGAffineTransform) 본문
UI 컴포넌트 (swift)
[iOS - swift] 1. long press gesture와 애니메이션 - 드래그 구현 방법 (snapshotView, CGAffineTransform)
jake-kim 2023. 7. 18. 01:521. long press gesture와 애니메이션 - 드래그 구현 방법 (snapshotView, CGAffineTransform)
3. long press gesture와 애니메이션 - 드래그와 cornerRadius, shadow 효과 (CABasicAnimation)
4. long press gesture와 애니메이션 - UIStackView에 DragDrop 적용 (DragDropStackView 구현)
5. long press gesture와 애니메이션 - gesture 도중 화면 끝으로 가면 자동으로 스크롤되는 기능 구현 (#Horizontal Scroll, #수평 스크롤)
드래그 구현 아이디어
- UILongPressGestureRecognizer를 뷰에 붙이기
- began, changed, ended에서 드래그 앤 드롭 처리
- 이동 시킬 뷰를 CGAffineTransform를 통해 바로 이동시키면, 실제로 frame이 이동되는게 아니기 때문에 이동 시킬 뷰와 동일한 뷰를 snapshotView를 통해 복사하여, 이 뷰를 CGAffineTransform를 통해 이동
- began: snapshotView를 사용하여 이동시킬 뷰 캡쳐, 기존 뷰 alpha = 0 설정
- changed: snapshotView를 CGAffineTransform으로 이동
- ended: 기존 뷰 alpha = 1 설정, 기존 뷰의 frame을 snapshotView와 동일하게 설정
구현
- 필요한 프로퍼티 선언
- someView: 롱 프레스하여 이동시킬 뷰
- snapshotedView: 복제할 뷰를 저장할 프로퍼티
- isDragging: 현재 드래깅 되고 있는지 여부 프로퍼티
- originalPosition: 롱 프레스하여 이동시킬 뷰의 드래그 하기 전의 위치
import UIKit
class ViewController: UIViewController {
private let someView = UIView()
private var snapshotedView: UIView?
private var isDragging = false
private var originalPosition = CGPoint.zero
}
- 기본 뷰 레이아웃 설정
override func viewDidLoad() {
super.viewDidLoad()
someView.backgroundColor = .green
view.addSubview(someView)
someView.frame = .init(x: 120, y: 120, width: 200, height: 200)
// TODO: long press 붙이기
}
- long press 붙이기
- 주의) delegate = self로 설정한 다음 gestureRecognizerShouldBegin 델리게이트 추가
- 의미: 롱 프레스 후 드래그할 때 다른 제스쳐를 막기 위함
let longPressGesture = UILongPressGestureRecognizer()
longPressGesture.minimumPressDuration = 0.3
longPressGesture.isEnabled = true
longPressGesture.delegate = self
longPressGesture.addTarget(self, action: #selector(handleLongPress))
someView.addGestureRecognizer(longPressGesture)
...
extension ViewController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
!isDragging
}
}
- long press 헨들러 추가
@objc private func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case .began:
handleBegan(gesture)
case .changed:
handleChanged(gesture)
default:
// ended, canceled, failed
handleEnded(gesture)
}
}
private func handleBegan(_ gesture: UILongPressGestureRecognizer) {
// TODO
}
private func handleChanged(_ gesture: UILongPressGestureRecognizer) {
// TODO
}
private func handleEnded(_ gesture: UILongPressGestureRecognizer) {
// TODO
}
- handleBegan 구현
- originalPosition 저장
- snapshotView(afterScreenUpdates:)로 기존 뷰 캡쳐
- 기존 뷰 가리기
private func handleBegan(_ gesture: UILongPressGestureRecognizer) {
originalPosition = gesture.location(in: view)
snapshotedView = someView.snapshotView(afterScreenUpdates: true)
snapshotedView?.frame = someView.frame
view.addSubview(snapshotedView!)
someView.alpha = 0
}
- handleChanged 구현
- 위에서 저장한 originalPosition 값을 이용하여 이동된 offset을 구한 후 CGAffineTransform을 통해 좌표 이동
private func handleChanged(_ gesture: UILongPressGestureRecognizer) {
let newLocation = gesture.location(in: view)
let xOffset = newLocation.x - originalPosition.x
let yOffset = newLocation.y - originalPosition.y
let translation = CGAffineTransform(translationX: xOffset, y: yOffset)
snapshotedView?.transform = translation
}
- handleEnded 구현
- 캡쳐된 뷰를 다시 지우고, 원본 뷰의 프레임 업데이트
private func handleEnded(_ gesture: UILongPressGestureRecognizer) {
someView.frame = snapshotedView?.frame ?? .zero
snapshotedView?.alpha = 0
snapshotedView?.removeFromSuperview()
someView.alpha = 1
}
(완료)
'UI 컴포넌트 (swift)' 카테고리의 다른 글
Comments