1

There has been a question to something related a while ago: Move TextField up when the keyboard has appeared in SwiftUI

It seems like the previous problem has been fixed. However, if we put the VStack in a ScrollView. SwiftUI seems to ignore the the keyboard safe area and keep the scrollview behind the keyboard. With one vertical scroll view and a textfield in it, we still get the desired behaviour, the scroll view scrolls up to the textfield. The problem occurs if we use a horizontal scroll view in the vertical scroll view. The scroll view does not move up to have the textfield visible. Does anyone know how to solve that?

struct ContentView: View {
    
    @State var text = ""
    
    var body: some View {
        
        ScrollView(.vertical, showsIndicators: false) {
            VStack {
                
                ForEach(0..<10) {_ in
                    
                    ScrollView(.horizontal, showsIndicators: false) {
                        HStack(spacing: 20) {
                            ForEach(0..<10) {_ in
                                
                                VStack {
                                    Rectangle()
                                        .fill(Color.red)
                                        .frame(width: 500, height: 300)
                                    TextField("Test", text: $text)
                                    
                                }
                            }
                        }
                    }
                    
                }
            }
            
        }
        
    }
}

enter image description here

enter image description here

aheze
  • 24,434
  • 8
  • 68
  • 125
NilsBerni
  • 83
  • 2
  • 13

2 Answers2

0

Try create extension to View:

extension View {

    func keyboardSensible(_ offsetValue: Binding<CGFloat>, contentHeight: CGFloat) -> some View {
        return self
            .padding(.bottom, offsetValue.wrappedValue)
            .animation(.spring())
            .onAppear {
                NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { notification in

                    let keyWindow = UIApplication.shared.connectedScenes
                        .filter({$0.activationState == .foregroundActive})
                        .map({$0 as? UIWindowScene})
                        .compactMap({$0})
                        .first?.windows
                        .filter({$0.isKeyWindow}).first

                    let userFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect ?? .zero
                    
                    offsetValue.wrappedValue = userFrame.height
                }

                NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { _ in
                    offsetValue.wrappedValue = 0
                }
        }
    }
}

Usage example for content adjustments:

    @State private var offsetValue: CGFloat = 0.0


    var body: some View {
        GeometryReader { geometryReader in
            VStack {
        ...
        
        }.keyboardSensible(self.$offsetValue, contentHeight: geometryReader.size.height)
0

I just have some additional info for this problem, not the solution however. If you put the TextFiled in the first ScrollView it does avoid the keyboard. Maybe this info helps someone to solve it:

''' struct ContentView: View {

@State var text = ""

var body: some View {
    
    ScrollView(.vertical, showsIndicators: false) {
        VStack {
            
            ForEach(0..<10) {_ in
                VStack {
                  ScrollView(.horizontal, showsIndicators: false) {
                    HStack(spacing: 20) {
                        ForEach(0..<10) {_ in
                            
                            VStack {
                                Rectangle()
                                    .fill(Color.red)
                                    .frame(width: 500, height: 300)
                                
                            }
                        }
                    }
                  }
                  TextField("Test", text: $text)
                }
                
                
            }

        }
        
    }
    
}

} '''

  • I do know that, the problem really only occurs if it is in the vertical scroll view. But thank you, this might help someone :) – NilsBerni May 23 '21 at 08:29