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
- ribs
- Human interface guide
- RxCocoa
- SWIFT
- HIG
- UICollectionView
- 스위프트
- swift documentation
- UITextView
- uiscrollview
- rxswift
- swiftUI
- tableView
- 리팩토링
- Protocol
- combine
- 리펙토링
- Xcode
- 애니메이션
- MVVM
- uitableview
- ios
- 리펙터링
- Observable
- collectionview
- Clean Code
- map
- clean architecture
- 클린 코드
- Refactoring
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - SwiftUI] Swipe Down To Dismiss (아래로 스와이프하여 뷰 dismiss하는 방법) 본문
iOS 응용 (SwiftUI)
[iOS - SwiftUI] Swipe Down To Dismiss (아래로 스와이프하여 뷰 dismiss하는 방법)
jake-kim 2022. 9. 30. 22:50
Swipe Down To Dismiss 구현 아이디어
- .gesture()와 DragGesture를 사용하여 drag 제스쳐 구현
(gesture와 DragGesture 개념을 모른다면, 이전 포스팅 글 참고) - gesture 안에서 y축이 얼마나 변했는지와, y축 velocity 값을 가지고 dismiss할것인지 결정
- dismiss할때는 NavigationLink의 인수 중 Binding 프로퍼티인 isActive값을 false로 변경
구현
- 편리를 위해 CGSize extension으로 - operator 구현
extension CGPoint {
static func - (lhs: Self, rhs: Self) -> Self {
CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
}
- 필요한 프로퍼티 선언
- draggedOffset: 드래그하는 만큼 뷰도 움직이게 하기위해 Binding하여 사용될 프로퍼티
- isActive: NavigationLink의 인수로 들어가며, dismiss할때 사용
import SwiftUI
import Combine
struct ContentView: View {
@State private var draggedOffset = CGSize.zero
@State private var isActive = false
var body: some View {
}
}
- body부분 뷰 구현
var body: some View {
NavigationView {
NavigationLink(
isActive: $isActive,
destination: {
Image("background")
.offset(draggedOffset)
.gesture(swipeDownToDismiss)
},
label: {
Text("다음 화면")
}
)
}
}
var swipeDownToDismiss: some Gesture {
// TODO
}
- swipeDownToDimsss 구현
var swipeDownToDismiss: some Gesture {
DragGesture()
.onChanged { gesture in
guard
gesture.location > 30, // NavigationView의 왼쪽 끝에서 오른쪽으로 하면 dimisss되는 기능을 사용할 때 제스쳐 처리 방지 guard문
gesture.translation.height > 0 // 아래로만 드래그 되도록 구현
else { return }
draggedOffset = gesture.translation
}
.onEnded { gesture in
if checkIsDismissable(gesture: gesture) {
isActive = false
}
draggedOffset = .zero
}
}
func checkIsDismissable(gesture: _ChangedGesture<DragGesture>.Value) -> Bool {
// TODO
}
- checkIsDismissable 구현
- (여기서 한계값은 임의로 경험적으로 정한 것)
- veolocity를 구할때는 gesture.predictedEndLocation에 현재 위치를 빼면 gesture의 속도를 쉽게 알아내기가 가능
func checkIsDismissable(gesture: _ChangedGesture<DragGesture>.Value) -> Bool {
let dismissableLocation = gesture.translation.height > 50
let dismissableVolocity = (gesture.predictedEndLocation - gesture.location).y > 50
return dismissableLocation || dismissableVolocity
}
List를 사용할땐, dismiss 방법
- dismiss 방법
- List를 사용 X - isActive 프로퍼티를 사용
- List를 사용 O - @Environment(\.presentationMode) private var presentationMode 사용
* List를 사용하지 않을때 @Environment(\.presentationMode)를 사용해도 동작하지 않으므로 주의
- List에서 @Environment(\.presentationMode)를 사용하지 않고 isActive를 사용하면 엉뚱한 Cell이 보여질 수 있으므로 @Environemnt를 사용 권장
presentationMode.wrappedValue.dismiss()
* 전체 코드: https://github.com/JK0369/ExSwipeDownToDismiss-SwiftUI
'iOS 응용 (SwiftUI)' 카테고리의 다른 글
Comments