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.
You really have a lot of code in there - and two reasons to clean it up:
HStack{Spacer()}
instead of Spacer()
, which by the way is not needed in this context?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)
}
}
}