I am a beginner coder. I develop my very first app using SwiftUI and I have a huge problem(bug) with keyboard: the View is moving up when TextField is touched. I don’t want my View to move at all.
I have a ContentView(the one with the problem), that contains custom Navigation Bar and several Views.
Simplified code below.
My ContentView:
struct ContentView: View {
var body: some View {
CustomNavBarContainerPreview {
ZStack {
Color(.purple)
.opacity(0.4)
.ignoresSafeArea(.all)
VStack(alignment: .center) {
//view with textfield
PullView()
RandomView()
LanguageView()
Button {
//action
} label: {
ZStack {
RoundedRectangle(cornerRadius: 15)
.foregroundColor(.cyan)
.frame(minWidth: 300, idealWidth: 340, maxWidth: 340, minHeight: 70, idealHeight: 85, maxHeight: 85, alignment: .center)
Text("Accept Settings")
.font(Font.custom("Ubuntu-Regular", size: 24))
.foregroundColor(.white)
}
.padding(.vertical, 10)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
//using this isn't prevent the view from pusing up
.ignoresSafeArea(.keyboard, edges: .bottom)
}
// it doesn't work too
.ignoresSafeArea(.keyboard)
.onTapGesture {
dismissKeyboard()
}
}
}
func dismissKeyboard() {
UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.endEditing(true)
}
}
My SubViews:
struct PullView: View {
@State var num1: String = ""
@State var num2: String = ""
var body: some View {
ZStack(alignment: .topLeading) {
Rectangle()
.frame(minWidth: 342, idealWidth: 342, maxWidth: 342, minHeight: 150, idealHeight: 178, maxHeight: 178, alignment: .center)
.foregroundColor(.white)
VStack {
HStack {
Text("Title One")
.bold()
.multilineTextAlignment(.leading)
.foregroundColor(.black)
.padding(.leading, 15)
Spacer()
Image(systemName: "info.circle.fill")
.scaledToFill()
.frame(alignment: .trailing)
.padding(.trailing, 15)
}
.frame(maxWidth: 342, maxHeight: 50)
.padding(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.background(Rectangle()
.foregroundColor(Color(red: 230/255, green: 234/255, blue: 242/255))
.opacity(0.5))
HStack(alignment: .center) {
Text("field1")
.foregroundColor(.black)
TextField("", value: $num1, formatter: NumberFormatter())
.textFieldStyle(DefaultTextFieldStyle())
.foregroundColor(.black)
.multilineTextAlignment(.center)
.frame(width: 90, height: 48)
.keyboardType(.numberPad)
.background(.green)
Text("field2")
.foregroundColor(.black)
TextField("", value: $num2, formatter: NumberFormatter())
.textFieldStyle(DefaultTextFieldStyle())
.foregroundColor(.black)
.multilineTextAlignment(.center)
.frame(width: 90, height: 48)
.keyboardType(.numberPad)
.background(.green)
}
.padding(.all, 10)
}
}
}
}
struct RandomView: View {
var body: some View {
ZStack(alignment: .topLeading) {
Rectangle()
.frame(minWidth: 342, idealWidth: 342, maxWidth: 342, minHeight: 150, idealHeight: 178, maxHeight: 178, alignment: .center)
.foregroundColor(.white)
VStack {
HStack {
Text("Title Two")
.bold()
.multilineTextAlignment(.leading)
.foregroundColor(.black)
.padding(.leading, 15)
Spacer()
Image(systemName: "info.circle.fill")
.scaledToFill()
.frame(alignment: .trailing)
.padding(.trailing, 15)
}
.frame(maxWidth: 342, maxHeight: 50)
.padding(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.background(Rectangle()
.foregroundColor(Color(red: 230/255, green: 234/255, blue: 242/255))
.opacity(0.5))
Text("Random settings")
Text("Subview test")
}
}
}
}
struct LanguageView: View {
var body: some View {
ZStack(alignment: .topLeading) {
Rectangle()
.frame(minWidth: 342, idealWidth: 342, maxWidth: 342, minHeight: 150, idealHeight: 178, maxHeight: 178, alignment: .center)
.foregroundColor(.white)
VStack {
HStack {
Text("Title Three")
.bold()
.multilineTextAlignment(.leading)
.foregroundColor(.black)
.padding(.leading, 15)
Spacer()
Image(systemName: "info.circle.fill")
.scaledToFill()
.frame(alignment: .trailing)
.padding(.trailing, 15)
}
.frame(maxWidth: 342, maxHeight: 50)
.padding(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.background(Rectangle()
.foregroundColor(Color(red: 230/255, green: 234/255, blue: 242/255))
.opacity(0.5))
Text("Language settings")
Text("Subview test")
}
}
}
}
And Custom NavBarViews
struct CustomNavBar: View {
var body: some View {
ZStack {
Rectangle()
.foregroundColor(.clear)
.frame(width: .infinity, height: 70)
.background(.mint)
HStack {
Button("Back") {
}
Spacer()
Text("Heading")
.bold()
.foregroundColor(.white)
Spacer()
Button("Next") {
}
}
.padding(.horizontal)
}
.navigationBarHidden(true)
}
}
struct CustomNavBarContainerPreview<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
VStack(spacing: 0) {
CustomNavBar()
content
}
}
}
My GitHub test project here:
Ready to test
What’s the problem may be with this? How I can fix it?
I dug StackOverflow and didn’t find the answer. I saw this is a common bug in SwiftUI.
I tried to paste .ignoresSafeArea(.keyboard)
and .ignoresSafeArea(.keyboard, edges: .bottom)
everywhere in my code below (in ContentView, SettingsViews, custom Navigation Bar), to use Spacers()
and .ignoresSafeArea(.all)
, and it didn’t give any results: View is still moving.
Also I used a hack with ScrollView to fix it, but it didn’t work correct for me.
May be I can embed UIKit code to control the View and the keyboard? But I don’t know how to do this.
2
Answers
Thanks to everyone who didn't pass by my problem, but unfortunately, I didn't find a suitable answer for me here. I figured it out myself, and the perfect solution for my case turned out to be placing my View in
GeometryReader{}
and applying the.ignoresSafeArea(.keyboard)
modifier to it, and it worked!I know you wrote that adding a ScrollView didn’t help you. I copied your code one for one into a fresh Xcode project added a ScrollView around the VStack in ContentView and for me the keyboards don’t push the view up anymore after that.