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()
}
}
作ったコンポーネントをimportしてビルドして試してみてください。
import SwiftUI
struct ContentView: View {
var body: some View {
OtpFormFieldView()
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
}
最後に
海外の記事を参考に、pincodeのようなUIとキーボードを閉じるロジックを実装する方法をご紹介いたしました。番号を入力するキーボードだと閉じるのに工夫が必要でした。