先日リリースした私のアプリに使用した技術の解説です。
私のアプリはこちら。
sheetメソッドとは
ビューをモーダル表示させるメソッド。下から出てきて画面の一番手前に表示される。
実際の動作
「わかった!」ボタンを押すと下から答え合わせのビューが出てきて、画面の一番手前に表示されているのがわかるかと思います。
また、このシートは上下に動かすことができ、一定の位置まで下げて指を離すと閉じるようになっています。
基本の書き方
.sheet(isPresented: ブール値, content: { 表示させたいビュー })
sheetメソッドはさまざまな引数を取りますが、一番シンプルな書き方はこのようになります。isPresented
がtrueになったとき、content
の{ }内のビューが表示されます。
ソースコード
上のサンプルアプリのコードの一部です。
import SwiftUI
struct ContentView: View {
@State var answer = ""
@State var moveAnswer = false //シートを出すためのブール型の変数
var body: some View {
VStack{
Text("なぞなぞ")
.font(.title)
.padding()
Text("パンはパンでも白黒のかわいいパンは\nぱ〜んだ?")
TextField("こたえを書いてね", text: $answer)
.frame(width: 200)
.padding()
.border(Color.black)
// シートを出すトリガーになるボタン
Button(action: {
moveAnswer = true //シートを出すためのアクション
}, label: {
Text("わかった!")
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(10)
})
//moveAnswerがtrueになったときに出てくるシート
.sheet(isPresented: $moveAnswer, content: {
Answer(answer: answer, moveAnswer: $moveAnswer)
})
}
}
}
こちらのコードを部分ごとにわけて解説したいと思います。
シートを出すための仕組み
まず、ContentViewのプロパティとしてブール型の変数を用意します。
@State var moveAnswer = false //シートを出すためのブール型の変数
アプリ起動時はシートが出ていない状態にしたいため、初期値にfalseを入れています。逆に言えば、初期値をtrueにすればアプリ起動時にシートを出すことができます。
次は、シートを出すトリガーになるボタンです。
// シートを出すトリガーになるボタン
Button(action: {
moveAnswer = true //シートを出すためのアクション
}, label: {
Text("わかった!")
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(10)
})
ボタンをタップするとmoveAnswerにtrueが代入されます。
そして、sheetメソッドを見ていきます。
.sheet(isPresented: $moveAnswer, content: {
Answer(answer: answer, moveAnswer: $moveAnswer)
})
ボタンのアクションによってmoveAnswerにtrueが入るとisPresented
がtrueになり、content
のAnswerビューが表示されます。
今回、AnswerビューはAnswer.swiftという別のファイルを作って書きました。そちらのビューも見てみましょう。
今回シートに表示したビュー
import SwiftUI
struct Answer: View {
let answer: String //前の画面のなぞなぞの答え
@Binding var moveAnswer: Bool //前の画面のmoveAnswerを反映させるための変数
var body: some View {
VStack{
//なぞなぞの答えが正解かどうかで表示を変える
if answer == "パンダ" {
Text("せいかい!!\nすごい!天才だ!")
.font(.title)
Image("correct")
}else{
Text("ちがうよ。もういちどもんだいをよく読んでみよう。")
.font(.title)
Image("fault")
}
//シートを閉じるためのトリガーになるボタン
Button(action: {
moveAnswer = false //シートを閉じるためのアクション
}, label: {
Text("もどる")
.font(.title)
.padding()
})
}
}
}
動画内でもやっていたように、わざわざボタンを作らなくてもシートを閉じる操作はできますが、ボタンがあった方が便利な場面もあるかと思います。このボタンの作り方について解説したいと思います。
シートを閉じるためのボタンの作り方
シートを閉じるためには、ContentViewのmoveAnswerがfalseになる必要があります。そのため、まずはContentViewのmoveAnswerをAnswerビューに反映させます。
@Binding var moveAnswer: Bool //前の画面のmoveAnswerを反映させるための変数
@Binding
をつけることで、このmoveAnswerに入れたブール値の状態を共有しています。つまり、AnswerのmoveAnswerがfalseになると、ContentViewのmoveAnswerもfalseに変わるようにしています。
そしてこちらがシートを閉じるためのトリガーとなるボタンです。
//シートを閉じるためのトリガーになるボタン
Button(action: {
moveAnswer = false //シートを閉じるためのアクション
}, label: {
Text("もどる")
.font(.title)
.padding()
})
このボタンを押すことでmoveAnswerにfalseが入り、シートを閉じることができます。