LoginSignup
1
1

SwiftUIでキーボードを閉じる

Last updated at Posted at 2024-03-05

SwiftUIでキーボードを閉じたい!

SwiftUIでは、キーボード自体に閉じるボタンを追加することはできません。しかし、画面のどこかをタップするとキーボードが閉じるようにすることは可能です。

以下のように、TapGestureを使用して画面全体にタップジェスチャーを追加し、そのアクションでpinFocusStateをnilに設定します。

@FocusState var focus:Bool

var body: some View {
    VStack {
        // Your existing code...
    }
    .gesture(
        TapGesture()
            .onEnded { _ in
                pinFocusState = nil
            }
    )
}

こちらに完成品のコードございます。pincodeなるものを作りたくて試してました。キーボードが閉じれなくて困っておりました💦
キーボードの上の画面をタップすると閉じます!

状態を扱うコード

import SwiftUI
import Combine

struct OtpModifer: ViewModifier {

    @Binding var pin : String

    var textLimt = 1

    func limitText(_ upper : Int) {
        if pin.count > upper {
            self.pin = String(pin.prefix(upper))
        }
    }


    //MARK -> BODY
    func body(content: Content) -> some View {
        content
            .multilineTextAlignment(.center)
            .keyboardType(.numberPad)
            .onReceive(Just(pin)) {_ in limitText(textLimt)}
            .frame(width: 45, height: 45)
            .background(Color.white.cornerRadius(5))
            .background(
                RoundedRectangle(cornerRadius: 5)
                    .stroke(Color("blueColor"), lineWidth: 2)
            )
    }
}

Viewのコード

import SwiftUI
import Combine

struct OtpFormFieldView: View {
    //MARK -> PROPERTIES

    enum FocusPin {
        case  pinOne, pinTwo, pinThree, pinFour
    }

    @FocusState private var pinFocusState : FocusPin?
    @State var pinOne: String = ""
    @State var pinTwo: String = ""
    @State var pinThree: String = ""
    @State var pinFour: String = ""
    
    @FocusState var focus:Bool


    //MARK -> BODY
    var body: some View {
        VStack {
            
            Text("Verify your Email Address")
                .font(.title2)
                .fontWeight(.semibold)
            
            
            Text("Enter 4 digit code we'll text you on Email")
                .font(.caption)
                .fontWeight(.thin)
                .padding(.top)
            
            HStack(spacing:15, content: {
                
                TextField("", text: $pinOne)
                    .modifier(OtpModifer(pin:$pinOne))
                    .onChange(of:pinOne){newVal in
                        if (newVal.count == 1) {
                            pinFocusState = .pinTwo
                        }
                    }
                    .focused($pinFocusState, equals: .pinOne)
                    .overlay(
                        RoundedRectangle(cornerRadius: 3)
                            .stroke(Color.blue, lineWidth: 2)
                    )
                
                TextField("", text:  $pinTwo)
                    .modifier(OtpModifer(pin:$pinTwo))
                    .onChange(of:pinTwo){newVal in
                        if (newVal.count == 1) {
                            pinFocusState = .pinThree
                        }
                    }
                    .focused($pinFocusState, equals: .pinTwo)
                    .overlay(
                        RoundedRectangle(cornerRadius: 3)
                            .stroke(Color.blue, lineWidth: 2)
                    )
                
                
                TextField("", text:$pinThree)
                    .modifier(OtpModifer(pin:$pinThree))
                    .onChange(of:pinThree){newVal in
                        if (newVal.count == 1) {
                            pinFocusState = .pinFour
                        }
                    }
                    .focused($pinFocusState, equals: .pinThree)
                    .overlay(
                        RoundedRectangle(cornerRadius: 3)
                            .stroke(Color.blue, lineWidth: 2)
                    )
                
                
                TextField("", text:$pinFour)
                    .modifier(OtpModifer(pin:$pinFour))
                    .focused($pinFocusState, equals: .pinFour)
                    .overlay(
                        RoundedRectangle(cornerRadius: 3)
                            .stroke(Color.blue, lineWidth: 2)
                    )
                
                
            })
            .padding(.vertical)
            
            
            Button(action: {}, label: {
                Spacer()
                Text("Veify")
                    .font(.system(.title3, design: .rounded))
                    .fontWeight(.semibold)
                    .foregroundColor(.white)
                Spacer()
            })
            .padding(15)
            .background(Color.blue)
            .clipShape(Capsule())
            .padding()
        }
        .gesture(
        TapGesture()
            .onEnded { _ in
                pinFocusState = nil
            }
    )
    }
}

struct OtpFormFieldView_Previews: PreviewProvider {
    static var previews: some View {
        OtpFormFieldView()
    }
}

Previewするとこんな感じです。
スクリーンショット 2024-03-05 21.09.26.png

作ったコンポーネントをimportしてビルドして試してみてください。

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        OtpFormFieldView()
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
}

最後に

海外の記事を参考に、pincodeのようなUIとキーボードを閉じるロジックを実装する方法をご紹介いたしました。番号を入力するキーボードだと閉じるのに工夫が必要でした。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1