🙄

【SwiftUI】TextFieldのタップエリアが狭すぎる

2025/03/07に公開

SwiftUI Tipsです。

問題

このようなデザインのSwiftUIの入力フィールドを実装しました。

TextFieldの範囲に対して、ちょっとマージンがあって、枠線があるデザインです。
コードは↓こんな実装です。

struct MailInputView: View {
    @State var email: String = ""
    @FocusState private var focusedField: Field?
    enum Field: Hashable {
        case email
    }

    var body: some View {
        TextField("メールアドレス", text: $email)
            .font(.body)
            .keyboardType(.emailAddress)
            .padding(.horizontal, 8)
            .frame(height: 48)
            .overlay(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(.gray, lineWidth: 1)
            )
            .padding()
            .focused($focusedField, equals: .email)
    }
}

これで最低限の機能は実現できるんですが、実機で触ってみると
「なんかタップ範囲やたら狭いな」という感覚がありました。
なぜそう感じたのかというと、タップ範囲が↓このエリアになるためです。

視覚的にはグレー線の中が全てタップ可能と感じますが、
実際はTextFieldがタップ範囲なので、実際は赤線の中になります。

対策

SwiftUIのタップ範囲について調べると、だいたい.contentShapeつけて、.onTapGestureをつけろというアドバイスが出てきます。
今回のケースでもこのアプローチしかなさそうです。
本当はTextFieldにタップ範囲広くできる何かがあると良かったのですが。

struct MailInputView: View {
    var body: some View {
        TextField("メールアドレス", text: $email)
            .font(.body)
            .keyboardType(.emailAddress)
            .padding(.horizontal, 8)
            .frame(height: 48)
            .overlay(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(.gray, lineWidth: 1)
            )
+           .contentShape(.rect)         
+           .onTapGesture {              
+               focusedField = .email    
+           }                            
            .padding()
            .focused($focusedField, equals: .email)
    }
}

これで直感的にTextFieldが反応するようになりました。

おまけ

加えてですが、TextFieldの外をタップしたら、フォーカスを外すというのも欲しい動作です。
これはSwiftUIだとサラッと実現できました。

var body: some View {
    VStack {
        // …
    }
    .onTapGesture {
        focusedField = nil
    }
}

このようにonTapGestureを指定してあげると、いい感じにフォーカスが外れました。

(了)

Discussion