📖
[SwiftUI]自作HalfModalの作り方
今回作成するもの
iOS15からUIKitではUISheetPresentationControllerが追加されたので、標準でハーフモーダルと言われるものを簡単に表現できるようになりました。
しかしSwiftUIでは追加されませんでしたので自作するか、外部ライブラリをしようするかでしか実装できません。今回は自作する方法をご紹介したいと思います。
以下完成イメージです。
ボタンを押すとハーフモーダルが表示され、ドラッグ少し上に引っ張るとモーダル表示されます。
(このあたりのサイズは使用しやすいように適時変更していただければと思います)
環境
・ macOS: Monterey
・ Xcode: 13.2
実装
ハーフモーダルで使用するViewを適当に作ります。
struct HalfModalView: View {
var body: some View {
ZStack {
Rectangle()
.foregroundColor(.gray)
VStack {
RoundedRectangle(cornerRadius: 10)
.frame(width: 60, height: 5)
.padding(.top)
Spacer()
}
}
}
}
先ほど作ったHalfModalViewに対してハーフモーダルのように表示されるようにmodifierを追加していきます。
使用するプロパティ
@State var show = false
@State var showFull = false
@State var position = CGSize.zero
@State var viewSize = UIScreen.main.bounds
@State var higthRate = 0.35
実装するコード
HalfModalView()
.cornerRadius(20)
.offset(y:show ? viewSize.height * 0.4 : viewSize.height)
.offset(y: position.height)
.animation(.timingCurve(0.2, 0.8, 0.2, 1, duration: 0.9), value: show)
.gesture(
DragGesture().onChanged { value in
position = value.translation
if showFull {
position.height += -(viewSize.height * higthRate)
}
if position.height < -(viewSize.height * higthRate) {
position.height = -(viewSize.height * higthRate)
}
}
.onEnded { value in
if position.height > 50 {
show = false
}
if (position.height < -100 && !showFull) || (position.height < -250 && showFull) {
position.height = -(viewSize.height * higthRate)
showFull = true
} else {
position = .zero
showFull = false
}
}
)
後は適当にボタンを作れば完成です。
Button {
show.toggle()
} label: {
Text("half modal")
}
まとめ
gestureを使用して、モーダルの高さによってFull表示とHalf表示をする実装をしてみましたが、コードがどうしても冗長的になってしまいます。SwiftUIでも標準で追加される事を期待しています。
Discussion