Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show complete List when keyboard is showing up in SwiftUI

Tags:

ios

swift

swiftui

How is it possible to show the complete List when the keyboard is showing up? The keyboard is hiding the lower part of the list.

I have a textField in my list row. When the keyboard shows up it is not possible to scroll down to see the complete list. The keyboard is in front of the list and not "under" the list. This is my coding:

struct ContentView: View {

    @State private var name = ""

    var body: some View {
        List {
            VStack {
                Text("Begin")
                    .frame(width: UIScreen.main.bounds.width)
                    .padding(.bottom, 400)
                    .background(Color.red)

                TextField($name, placeholder: Text("enter text"), onEditingChanged: { _ in
                    //
                }) {
                    //
                }

                Text("End")
                    .frame(width: UIScreen.main.bounds.width)
                    .padding(.top, 400)
                    .background(Color.green)
            }
            .listRowInsets(EdgeInsets())
        }
    }
}

Can anybody help me how I can do this?

Thank you very much.

like image 695
stefOCDP Avatar asked Jun 22 '19 14:06

stefOCDP


People also ask

How to move the view when the keyboard height changes in SwiftUI?

SwiftUI will automatically update the view whenever the keyboard height changes. Add padding to the bottom of the view, which will make it move up and down with the keyboard. Update the view state with the latest value emitted by the keyboardHeight publisher. Now, when focusing and defocusing the text field, the view will move up and down:

How do I manage the iOS keyboard in SwiftUI?

It can be a TextField component from SwiftUI, a UITextField and UITextView from UIKit, or a text input field inside a web view. Whenever the iOS keyboard appears, it overlaps parts of your interface. The common approach to keyboard management is to move up the focused part of the view to avoid its overlapping.

Why use iqkeyboardmanager in SwiftUI?

In my traditional Swift/UIKit applications, I use IQKeyboardManager to make sure that the on-screen keyboard does not obscure the text field (or text view) being edited. What is the situation in SwiftUI? Is this something that is part of the "it just works" part of the framework, or do I still have to implement it?

Can we add a first responder in SwiftUI?

It would be great to be able to set the first responder manually in SwiftUI (e.g. focus TextField or dismiss the keyboard). It would be great to be able to add a toolbar above the keyboard (add custom buttons like a ready or next button) It would be great to be able to automatically shrink the visible view when the keyboard comes in to view.


1 Answers

An alternative implementation of the KeyboardResponder object using Compose, as seen here.

final class KeyboardResponder: ObservableObject {

    let willChange = PassthroughSubject<CGFloat, Never>()

    private(set) var currentHeight: Length = 0 {
        willSet {
            willChange.send(currentHeight)
        }
    }

    let keyboardWillOpen = NotificationCenter.default
        .publisher(for: UIResponder.keyboardWillShowNotification)
        .first() // keyboardWillShow notification may be posted repeatedly
        .map { $0.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect }
        .map { $0.height }

    let keyboardWillHide =  NotificationCenter.default
        .publisher(for: UIResponder.keyboardWillHideNotification)
        .map { _ in CGFloat(0) }

    func listen() {
        _ = Publishers.Merge(keyboardWillOpen, keyboardWillHide)
            .subscribe(on: RunLoop.main)
            .assign(to: \.currentHeight, on: self)
    }

    init() {
        listen()
    }
}

An even nicer method is to pack the above as a ViewModifier (loosely adapted from here):

struct AdaptsToSoftwareKeyboard: ViewModifier {

    @State var currentHeight: Length = 0

    func body(content: Content) -> some View {
        content
            .padding(.bottom, currentHeight)
            .edgesIgnoringSafeArea(currentHeight == 0 ? Edge.Set() : .bottom)
            .onAppear(perform: subscribeToKeyboardEvents)
    }

    private let keyboardWillOpen = NotificationCenter.default
        .publisher(for: UIResponder.keyboardWillShowNotification)
        .map { $0.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect }
        .map { $0.height }

    private let keyboardWillHide =  NotificationCenter.default
        .publisher(for: UIResponder.keyboardWillHideNotification)
        .map { _ in Length.zero }

    private func subscribeToKeyboardEvents() {
        _ = Publishers.Merge(keyboardWillOpen, keyboardWillHide)
            .subscribe(on: RunLoop.main)
            .assign(to: \.currentHeight, on: self)
    }
}

And then it could be used like this:

Group {

   ........

}.modifier(AdaptsToSoftwareKeyboard())
like image 162
Bogdan Farca Avatar answered Sep 30 '22 17:09

Bogdan Farca