SwiftUI에서 페이지 전환 (상단) 구현
참고
【iOS】전이 방법 정리와 엔지니어 1학년의 독말
상단 좌우에서 출현하는 메뉴 만들기
SwiftUI의 Gesture 소개
화면 전환 정보
페이지 천이 (상단) 구현
사진
동영상
페이지 전환 (상단) 피 c. 라고 r. 코 m / 우 My5v xM4 - APPLE (@applecoder6) April 12, 2021
코드
ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var showingModal = false
@State private var offset = CGFloat.zero // 現在のオフセット
@State private var closeOffset = CGFloat.zero // 閉状態のオフセット
@State private var openOffset = CGFloat.zero // 開状態のオフセット
var body: some View {
GeometryReader { geometry in
ZStack {
// メインコンテンツ
VStack {
Button("Show ModalView.") {
self.showingModal.toggle()
}.sheet(isPresented: $showingModal) {
ModalView()
}
Divider()
NavigationView {
NavigationLink(destination: PushView()) {
Text("Show PushView.")
}.navigationBarTitle("ContentView", displayMode: .automatic)
}
Divider()
TabView {
TabAView()
.tabItem {
Image(systemName: "moon")
Text("Tab A")
}
TabBView()
.tabItem {
Image(systemName: "moon.fill")
Text("Tab B")
}
}
}
// 上部メニュー
PageUpView()
.background(Color.gray)
.frame(width: geometry.size.width, height: geometry.size.height)
// View描画時に呼び出すメソッド
.onAppear(perform: {
// PageUpViewのオフセット初期値として負の方向(上方向)に[Safe Areaの高さ]+[PageUpView自体の高さ]分ずらす
self.offset = -1 * (geometry.frame(in: .global).origin.y + geometry.size.height)
// 閉状態のオフセット = 初期状態のオフセット
self.closeOffset = self.offset
// 開状態のオフセット = 0
self.openOffset = .zero
})
// オフセット
.offset(y: self.offset)
// アニメーション
.animation(.default)
}
//ジェスチャーに関する実装
.gesture(DragGesture(minimumDistance: 5)
// DragGestureの入力開始時の呼び出しメソッド
.onChanged { value in
// ContentViewの現在のオフセットが初期値でない かつ DragGestureの開始位置のy座標が30未満の場合
if (self.offset != self.openOffset && value.startLocation.y < 30) {
// ContentViewの現在のオフセット = 初期状態からy軸方向にDragされた距離
self.offset = self.closeOffset + value.translation.height
}
}
// DragGestureの入力終了時の呼び出しメソッド
.onEnded { value in
//Gesture終了時のViewのy座標がGesture開始時よりも高い(Viewが下方向に動いた場合)
if (value.startLocation.y < value.location.y) {
// Gestureの開始位置のy座標が30未満の場合
if (value.startLocation.y < 30) {
// PageUpViewを開状態にする
self.offset = self.openOffset
}
} else {
// PageUpViewを閉状態にする
self.offset = self.closeOffset
}
}
)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
PageUpView.swift
import SwiftUI
struct PageUpView: View {
var body: some View {
Text("This is Up Side.")
}
}
struct PageUpView_Previews: PreviewProvider {
static var previews: some View {
PageUpView()
}
}
학습 결과
GeometryReader
ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var showingModal = false
@State private var offset = CGFloat.zero // 現在のオフセット
@State private var closeOffset = CGFloat.zero // 閉状態のオフセット
@State private var openOffset = CGFloat.zero // 開状態のオフセット
var body: some View {
GeometryReader { geometry in
ZStack {
// メインコンテンツ
VStack {
Button("Show ModalView.") {
self.showingModal.toggle()
}.sheet(isPresented: $showingModal) {
ModalView()
}
Divider()
NavigationView {
NavigationLink(destination: PushView()) {
Text("Show PushView.")
}.navigationBarTitle("ContentView", displayMode: .automatic)
}
Divider()
TabView {
TabAView()
.tabItem {
Image(systemName: "moon")
Text("Tab A")
}
TabBView()
.tabItem {
Image(systemName: "moon.fill")
Text("Tab B")
}
}
}
// 上部メニュー
PageUpView()
.background(Color.gray)
.frame(width: geometry.size.width, height: geometry.size.height)
// View描画時に呼び出すメソッド
.onAppear(perform: {
// PageUpViewのオフセット初期値として負の方向(上方向)に[Safe Areaの高さ]+[PageUpView自体の高さ]分ずらす
self.offset = -1 * (geometry.frame(in: .global).origin.y + geometry.size.height)
// 閉状態のオフセット = 初期状態のオフセット
self.closeOffset = self.offset
// 開状態のオフセット = 0
self.openOffset = .zero
})
// オフセット
.offset(y: self.offset)
// アニメーション
.animation(.default)
}
//ジェスチャーに関する実装
.gesture(DragGesture(minimumDistance: 5)
// DragGestureの入力開始時の呼び出しメソッド
.onChanged { value in
// ContentViewの現在のオフセットが初期値でない かつ DragGestureの開始位置のy座標が30未満の場合
if (self.offset != self.openOffset && value.startLocation.y < 30) {
// ContentViewの現在のオフセット = 初期状態からy軸方向にDragされた距離
self.offset = self.closeOffset + value.translation.height
}
}
// DragGestureの入力終了時の呼び出しメソッド
.onEnded { value in
//Gesture終了時のViewのy座標がGesture開始時よりも高い(Viewが下方向に動いた場合)
if (value.startLocation.y < value.location.y) {
// Gestureの開始位置のy座標が30未満の場合
if (value.startLocation.y < 30) {
// PageUpViewを開状態にする
self.offset = self.openOffset
}
} else {
// PageUpViewを閉状態にする
self.offset = self.closeOffset
}
}
)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
PageUpView.swift
import SwiftUI
struct PageUpView: View {
var body: some View {
Text("This is Up Side.")
}
}
struct PageUpView_Previews: PreviewProvider {
static var previews: some View {
PageUpView()
}
}
GeometryReader
자신의 View 사이즈와 좌표 공간을 돌려주는 함수를 클로저로서 보관 유지하는 View.
GeometryReader를 통해 자신의 View( .local
)나 RootView( .global
)의 크기, 좌표 위치를 얻을 수 있다.
onAppear 한정자
View가 처음 그려지는 시점에서 호출되는 메소드.
onDisappear 한정자
View가 숨겨지는 시점에서 호출되는 메소드.
Gesture 유형
- TapGesture
→ 탭 - LongPressGesture
→ 길게 누르기 - DragGesture
→ 드래그 - MagnificationGesture
→ 핀치 - RotationGesture
→ 회전
gesture 한정자
View에 제스처가 입력되었을 때의 호출 메소드를 구현한다.
Gesture의 Callback 처리
- updating
→ Gesture 값이 업데이트되면 발화 (UI의 일시적인 상태 변경) - onChanged
→ Gesture 값이 업데이트되면 발화 (UI의 영구 상태 변경) - onEnded
→ Gesture가 종료되면 발화
Reference
이 문제에 관하여(SwiftUI에서 페이지 전환 (상단) 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/b150005/items/0ef8bd10fa58b8aa8888텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)