iosswiftswiftuiios-keyboard-extension

iOS 15 Keyboard hides textfield


I am trying to create a messaging page layout but the keyboard hides the textfield and moves everything to the the top. I have looked at many tutorials online and replicated them exactly but none of them seem to work.

Here is all the code I have written:

struct MessagingPage: View {
    var user: OfficialUserModel
    @ObservedObject private var vm = TheUserModel()
    @State var screenWidth = UIScreen.main.bounds.width
    @State var imageSize = UIScreen.main.bounds.width / 12
    @State var text = ""
    @State var show = false
    @Environment(\.presentationMode) var presentationMode
    
    var body: some View {
        NavigationView{
            ZStack{
                VStack{
                    
                    HStack{
                        Spacer()
                        
                        NavigationLink(destination: UserDisplayPage(user: user)) {
                                HStack{
                                    WebImage(url: URL(string: user.imageURL ))
                                        .resizable()
                                        .aspectRatio( contentMode: .fill)
                                        .frame(width: imageSize, height: imageSize
                                        )
                                        .cornerRadius(imageSize/2)
                                    
                                    VStack(alignment: .leading){
                                        Text(user.FullName)
                                            .font(.body)
                                            .fontWeight(.bold)
                                            .foregroundColor(.white)
                                        
                                        Text("\(user.City) , \(user.Country)")
                                            .font(.caption)
                                            .fontWeight(.semibold)
                                            .foregroundColor(.white)
                                    }
                                }
                        }
                        Spacer()
                        
                        HStack{
                            Button{
                                presentationMode.wrappedValue.dismiss()
                            } label: {
                                Image(systemName: "chevron.down")
                                    .font(.title)
                                    .foregroundColor(.myWhite)
                            }
                        }
                        .padding(.trailing)
                        
                    }
                    .padding(.top, 30)
                    .frame(height: 75)
                    .background(Color.mainBlack)
                    
                    ScrollView{
                        Spacer()
                        ForEach(0..<2){ num in
                            HStack{
                                Spacer()
                                HStack{
                                    Text("Hello \(user.firstName)")
                                        .foregroundColor(.orange)
                                }
                                .padding()
                                .background(Color.mainBlack)
                                .cornerRadius(15)
                                .shadow(color: .orange, radius: 2)
                            }
                            .padding(.horizontal)
                            .padding(.top, 8)
                        }
                        HStack{Spacer()}
                        
                        HStack{
                            HStack{
                                Text("\(user.FullName) is unable to recieve your message at this time. Please try again at a later time.")
                                    .foregroundColor(.green)
                            }
                            .padding()
                            .background(Color.mainBlack)
                            .cornerRadius(15)
                            .shadow(color: .green, radius: 2)
                            
                            Spacer()
                        }
                        .padding(.horizontal)
                        .padding(.top, 8)
                    
                    HStack{Spacer()}
                    }
                    .background(Color.mainBlack)
                    
                    ZStack{
                    HStack{
                        HStack{
                        
                        HStack{
                            TextField("Say Something...", text: self.$text)
                                .placeholder(when: text.isEmpty) {
                                    Text("Say Something...").foregroundColor(.myWhite.opacity(0.5))
                                }
                                .frame(width: screenWidth - 200, height: screenWidth/25)
                                .foregroundColor(.myCyan)
                                .accentColor(.myCyan)
                                .background(Color.mainBlack)
                                .textContentType(.emailAddress)
                            
                            if !text.isEmpty{
                                Button{
                                    print(text)
                                    self.text = ""
                                }label: {
                                    Image(systemName: "paperplane")
                                        .foregroundColor(.myCyan)
                                        .font(.system(size: 20))
                                }
                            }
                            else{
                                Button{
                                    print("Show more options")
                                }label: {
                                    Image(systemName: "plus")
                                        .foregroundColor(.myCyan)
                                        .font(.system(size: 20))
                                }
                            }
                           
                        }
                        .frame(width: screenWidth - 150, height: screenWidth/25)
                        .padding()
                        .background(Color.mainBlack)
                        .cornerRadius(30)
                        .shadow(color: .myCyan, radius: 5)
                        .padding(.bottom,5)
                    }
                    
                    }
                    .padding(.bottom, 50)
                    .frame(width: screenWidth)
                    }
                }
            }
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
            .background(Color.mainBlack)
            .navigationBarTitle("")
            .navigationBarHidden(true)
           
        }
        
    }
}

I want the the textfield to move up as well as the messages in the scrollview but the top HStack with the user image and back/dismiss button should remain in place.


Solution

  • You really have a lot of code in there - and two reasons to clean it up:

    1. To get a good answer, you need to post a minimal, reproducible example, which may also help you debug the code before posting it
    2. Many lines of code are redundant or useless, for example:

    Coming to your issue, the problem is that one of the redundant modifiers is preventing the text file to move up, and this is the line to delete:

    .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    

    Why setting a frame that is as high and large as much as the screen? This is forcing the text field to stay at the bottom.

    I tried to do some clean up, I bet some more can be done - see the code below, now the keyboard does not cover the text field anymore:

    struct MessagingPage: View {
    
       // Removed some lines of code to reproduce your issue
        @State var screenWidth = UIScreen.main.bounds.width
        @State var imageSize = UIScreen.main.bounds.width / 12
        @State var text = ""
        @State var show = false
        @Environment(\.presentationMode) var presentationMode
        
        var body: some View {
            NavigationView{
                
                // What is the purpose of this ZStack???
                //            ZStack{
                VStack{
                    
                    HStack{
                        Spacer()
                        
                        NavigationLink(destination: Text("Hello")) {
                            Text("Top bar")
                        }
                        Spacer()
                        
                        HStack{
                            Button{
                                presentationMode.wrappedValue.dismiss()
                            } label: {
                                Image(systemName: "chevron.down")
                                    .font(.title)
                                    .foregroundColor(.white)
                            }
                        }
                        .padding(.trailing)
                        
                    }
                    .padding(.top, 30)
                    .frame(height: 75)
                    .background(Color.black)
                    
                    ScrollView{
                        
                        // All the views inside the Scrollview need to be inside a VStack
                        VStack {
                            
                            // Why this spacer???
                            //                        Spacer()
                            ForEach(0..<2){ num in
                                HStack{
                                    Spacer()
                                    HStack{
                                        Text("Hello username")
                                            .foregroundColor(.orange)
                                    }
                                    .padding()
                                    .background(Color.black)
                                    .cornerRadius(15)
                                    .shadow(color: .orange, radius: 2)
                                }
                                .padding(.horizontal)
                                .padding(.top, 8)
                            }
                            HStack{Spacer()}
                            
                            HStack{
                                HStack{
                                    Text("User is unable to receive your message at this time. Please try again at a later time.")
                                        .foregroundColor(.green)
                                }
                                .padding()
                                .background(Color.black)
                                .cornerRadius(15)
                                .shadow(color: .green, radius: 2)
                                
                                Spacer()
                            }
                            .padding(.horizontal)
                            .padding(.top, 8)
                            
                            // Why a Spacer inside an HStack???
                            // HStack{Spacer()}
                        }
                        .background(Color.black)
                    }
                    
                    
                    // What is the purpose of this ZStack???
                    // ZStack{
                    
                    // Why an HStack that has only an HStack inside??
                    // HStack{
                    
                    // Why an HStack that has only an HStack inside??
                    
                    // HStack{
                    
                    HStack{
                        TextField("Say Something...", text: self.$text)
                            .frame(width: screenWidth - 200, height: screenWidth/25)
                            .foregroundColor(.cyan)
                            .accentColor(.cyan)
                            .background(Color.white)
                            .textContentType(.emailAddress)
                        
                        if !text.isEmpty{
                            Button{
                                print(text)
                                self.text = ""
                            }label: {
                                Image(systemName: "paperplane")
                                    .foregroundColor(.cyan)
                                    .font(.system(size: 20))
                            }
                        }
                        else{
                            Button{
                                print("Show more options")
                            }label: {
                                Image(systemName: "plus")
                                    .foregroundColor(.cyan)
                                    .font(.system(size: 20))
                            }
                        }
                        
                    }
                    
                    // Are you sure you want set the height of this stack based on the width?
                    //                            .frame(width: screenWidth - 150, height: screenWidth/25)
                    .frame(width: screenWidth - 150)
                    .padding()
                    .background(Color.black)
                    .cornerRadius(30)
                    .shadow(color: .black, radius: 5)
                    .padding(.bottom,5)
                    //                        }
                    
                    //                    }
                    .padding(.bottom, 50)
                    .frame(width: screenWidth)
                    //                }
                }
                //            }
                
                // Why setting a frame that is high and large as much as the screen??
                // .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
                .background(Color.black)
                .navigationBarTitle("")
                .navigationBarHidden(true)
                
            }
            
        }
    }
    

    enter image description here