⛳
SwiftUIの複数なテキストフィールドのキーボードを消す方法
例えば画面には一個のテキストフィールドだけが存在する場合、
キーボードを消すために、その消す用の@FocusState
変数を作り、フォーカス状態と連携させ実装することができます。
しかし、複数なテキストフィールドが存在する画面には、同じ多く@FocusState
変数を作るのが、管理しにくいと思います。
そういう悩みを解決するために、以下のフォーカス管理コードを導入しましょう。
初めに
まずはサンプルコードはこうです。
「name」と「description」の二つのテキストフィールドがあります。
struct TestView: View {
@State private var name = ""
@State private var description = ""
var body: some View {
List {
TextField("name", text: $name)
TextField("description", text: $description)
}
}
}
enum
タイプを定義
カスタムテキストフィールドの数と名前を合わせて、enum
を作ります
struct TestView: View {
@State private var name = ""
@State private var description = ""
+ private enum Field: Hashable {
+ case name, description
+ }
var body: some View {
List {
TextField("name", text: $name)
TextField("description", text: $description)
}
}
}
@FocusState
変数を定義
@FocusState
変数は、現在フォーカス中か、フォーカスしてないのか(Bool型)の定義ではなく
現在フォーカスしているのがどのテキストフィールドか(カスタムField型)を定義します。
テキストフィールドが一つもフォーカスしてない状態も可能なので
(キーボードが閉じている画面)
Field?
で型を定義します
struct TestView: View {
@State private var name = ""
@State private var description = ""
+ @FocusState private var focusedField: Field?
private enum Field: Hashable {
case name, description
}
var body: some View {
List {
TextField("name", text: $name)
TextField("description", text: $description)
}
}
}
Modifier実装
テキストフィールドと、先ほど定義した@FocusState
変数を連携させます
struct TestView: View {
@State private var name = ""
@State private var description = ""
@FocusState private var focusedField: Field?
private enum Field: Hashable {
case name, description
}
var body: some View {
List {
TextField("name", text: $name)
+ .focused($focusedField, equals: .name)
TextField("description", text: $description)
+ .focused($focusedField, equals: .description)
}
}
}
キーボードを閉じるボタン
キーボードの上に、「Done」ボタンを加えて
そのボタンをクリックすると、フォーカス中のボタンはどっちかの変数にnil
を定義させ
キーボードを閉じます。
struct TestView: View {
@State private var name = ""
@State private var description = ""
@FocusState private var focusedField: Field?
private enum Field: Hashable {
case name, description
}
var body: some View {
List {
TextField("name", text: $name)
.focused($focusedField, equals: .name)
TextField("description", text: $description)
.focused($focusedField, equals: .description)
}
+ .toolbar {
+ ToolbarItem(placement: .keyboard) {
+ HStack {
+ Spacer()
+ Button("Done") {
+ focusedField = nil
+ }
+ }
+ }
+ }
}
}
Discussion