How can I dismiss the keyboard, and have a new view behind it, while keeping the .toolbar visable in SwiftUI?

46 Views Asked by At

I am looking to be able to click a button, which dismisses the keyboard, and replace the keyboard space with a new view. Notion has this functionality in their app. I've attached a gif for clarity on what functionality I'm trying to achieve.

demo

1

There are 1 best solutions below

1
lorem ipsum On BEST ANSWER

You can get the height of the keyboard with

.onReceive(NotificationCenter
    .default
    .publisher(for: UIResponder.keyboardWillShowNotification)
    .compactMap { $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue }
    .map { $0.cgRectValue.height }, perform: { height in
        self.height = height //Adjust the height based on the keyboard
})

Then bring the keyboard in/out by setting

@FocusState var isFocused: Bool

to true/false

Here is a full sample.

import SwiftUI

struct KeyboardHeightView: View {
    //Use this to bring/dismiss keyboard
    @FocusState var isFocused: Bool
    @State private var height: CGFloat = 300
    @State private var text: String = "test"
    @ScaledMetric var buttonHeight = 40
    var body: some View {
        VStack{
            TextEditor(text: $text)
                .focused($isFocused)
            //Parent for buttons and actions
            Rectangle()
                .fill(Color.white)
                .border(Color.green)
                .overlay {
                    //Area for buttons and actions
                    VStack {
                        //Space for the buttons
                        HStack{
                            Text("tap to dismiss")
                                .onTapGesture {
                                    isFocused = false //Dismiss Keyboard
                                }
                        }
                        .frame(height: buttonHeight)
                        .frame(maxWidth: .infinity)
                        .border(Color.red)
                        //Space for other actions.
                        Button("perform some action") {
                            //Do something
                            isFocused = true //Show the  keyboard again.
                        }
                        Spacer()
                    }
                }
                .frame(height: height + buttonHeight) //Keyboard + the space for the buttons that dismiss keyboard and show actions
        }.ignoresSafeArea(.keyboard)
            .edgesIgnoringSafeArea(.bottom)
            .onReceive(NotificationCenter
                .default
                .publisher(for: UIResponder.keyboardWillShowNotification)
                .compactMap { $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue }
                .map { $0.cgRectValue.height }, perform: { height in
                    self.height = height //Adjust the height based on the keyboard
                })
            .task {
                isFocused = true //Show keyboard when the View appears
            }
    }
}

#Preview {
    KeyboardHeightView()
}