【Xcode/SwiftUI】@FocusStateを使ってみる

@FocusStateとは?

簡単に言うと、テキストフィールドとかの表示要素のフォーカス制御をすることが出来るものです。

自分の場合、説明だけでは完全に理解できなかったのでググって実際にコードを書いてみました。

サンプルその1

Focus on TextFieldボタンを押したら自動でTextFieldにフォーカスをあてると言う実装です。

import SwiftUI

struct HomeView: View {
    @State private var textFieldInput: String = ""
    @FocusState private var foucusValue: Bool

    var body: some View {
        VStack(spacing: 32) {
            Text("Focus: \(foucusValue == true ? "True" : "False" )")
                .font(.system(size: 24, weight: .bold))

            TextField("Your Texts Here", text: $textFieldInput)
                .focused($foucusValue)
                .textFieldStyle(.roundedBorder)

            Button(action: {
                foucusValue = true
            }, label: {
                Text("Focus on TextField")
                    .font(.system(size: 24, weight: .bold))
                    .frame(width: 300, height: 60, alignment: .center)
                    .foregroundColor(.white)
                    .background(.orange)
                    .cornerRadius(12)
            })

            Button(action: {
                foucusValue = false
            }, label: {
                Text("Unfocus TextField")
                    .font(.system(size: 24, weight: .bold))
                    .frame(width: 300, height: 60, alignment: .center)
                    .foregroundColor(.white)
                    .background(.green)
                    .cornerRadius(12)
            })
        }
        .padding()
    }
}

サンプルその2

複数のTextFieldがある時に、enumを使ってどちらのTextFieldにフォーカスをあてるのか分ける実装です。

import SwiftUI

enum FocusField: String, RawRepresentable {
    case first
    case second
}

struct HomeView: View {
    @State private var firstValue: String = ""
    @State private var secondValue: String = ""
    @FocusState private var focusField: FocusField?

    var body: some View {
        ZStack {
            Color.gray.opacity(0.4)
                .ignoresSafeArea()
            VStack(spacing: 32) {
                Text("Focus Status: \(focusField?.rawValue ?? "Unfocused" )")
                    .font(.system(size: 24, weight: .bold))

                TextField("First TextField", text: $firstValue)
                    .focused($focusField, equals: .first)
                    .textFieldStyle(.roundedBorder)

                TextField("Second TextField", text: $secondValue)
                    .focused($focusField, equals: .second)
                    .textFieldStyle(.roundedBorder)

                Button(action: {
                    focusField = .first
                }, label: {
                    Text("Focus on First")
                        .font(.system(size: 24, weight: .bold))
                        .frame(width: 300, height: 60, alignment: .center)
                        .foregroundColor(.white)
                        .background(.green)
                        .cornerRadius(12)
                })

                Button(action: {
                    focusField = .second
                }, label: {
                    Text("Focus on Second")
                        .font(.system(size: 24, weight: .bold))
                        .frame(width: 300, height: 60, alignment: .center)
                        .foregroundColor(.white)
                        .background(.yellow)
                        .cornerRadius(12)
                })

                Button(action: {
                    focusField = nil
                }, label: {
                    Text("UnFocus TextField")
                        .font(.system(size: 24, weight: .bold))
                        .frame(width: 300, height: 60, alignment: .center)
                        .foregroundColor(.white)
                        .background(.red)
                        .cornerRadius(12)
                })
            }
            .padding()
        }
    }
}

これは確かに有効活用出来そうですね、積極的に使っていきましょう。