参考
【iOS】遷移方法まとめとエンジニア1年生の独り言
上部左右から出現するメニューを作る
SwiftUIのGestureについてまとめ
画面遷移について
- モーダル ... 下から画面が出現
- プッシュ ... 右から画面が出現
- タブ ... 瞬時の切り替わり(タブアイテムのタップ)
- ページ ... 左右から画面が出現(左右スワイプ) ※サイドメニューと同義
ページ遷移(上部)の実装
写真
動画
ページ遷移(上部) pic.twitter.com/UMy5vxnxM4
— 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
自身の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が終了した際に発火