SwiftUI : How I can hide the navigationBar when the keyboard is shown - swiftui

enter image description here
Please check attached image file, that is situation of mine.
I tried to make this view, but when the keyboard is shown. The main view and navigationBar is mixed.
I hope to hide the navigationBar when I touched the textfield and keyboard is shown.
How I treat that? Thank you all
This is source code below.
import SwiftUI
struct FlashCardView: View {
#EnvironmentObject var itemModel : ItemModel
var item : Item
#State var isGeneral : Bool = true
#State var inputAnswer : String = ""
#State var showAlert : Bool = false
#State var isAnswer : Bool = false
#State var randomWord : (String, String) = ("", "")
var body: some View {
VStack {
HStack {
if let group = item.group {
Text("Game with ' \(group) '")
.font(.title3.bold())
.lineLimit(1)
.padding()
.background(
Color.yellow
.frame(height : 4)
.offset(y : 24)
)
}
}
HStack {
Button(action: {
isGeneral = true
makeNewCard()
}, label: {
Text(isGeneral ? "General 🔥" : "General")
.font(.headline)
.foregroundColor(isGeneral ? .white : .black)
.frame(width : 140, height : 50)
.background(isGeneral ? .blue : .gray)
.cornerRadius(10)
.padding()
})
.shadow(color: .gray.opacity(0.5), radius: 3, x: 3, y: 3)
Spacer()
Button(action: {
isGeneral = false
makeNewCard()
}, label: {
Text(!isGeneral ? "Favorite 🔥" : "Favorite")
.font(.headline)
.foregroundColor(!isGeneral ? .white : .black)
.frame(width : 140, height : 50)
.multilineTextAlignment(.center)
.background(!isGeneral ? .blue : .gray)
.cornerRadius(10)
.padding()
})
.disabled(item.children.filter({$0.isFavorite}).isEmpty)
.shadow(color: .gray.opacity(0.5), radius: 3, x: 3, y: 3)
}
Text(randomWord.0)
.font(.title2.bold())
.frame(maxWidth : .infinity)
.frame(height : UIScreen.main.bounds.height*0.33)
.multilineTextAlignment(.center)
.background(.ultraThinMaterial)
.cornerRadius(20)
.shadow(color: .gray.opacity(0.4), radius: 3, x: 3, y: 3)
.padding()
TextField("What is the answer?", text: $inputAnswer)
.frame(maxWidth : .infinity)
.frame(height : 60)
.font(.body)
.multilineTextAlignment(.center)
.autocapitalization(.none)
.submitLabel(.done)
.onSubmit {
if randomWord.1 == inputAnswer {
self.showAlert.toggle()
self.isAnswer = true
self.inputAnswer = ""
} else {
self.showAlert.toggle()
self.isAnswer = false
self.inputAnswer = ""
}
}
Divider()
.padding(.horizontal)
.padding(.vertical, -10)
Button(action: {
if randomWord.1 == inputAnswer {
self.showAlert.toggle()
self.isAnswer = true
self.inputAnswer = ""
} else {
self.showAlert.toggle()
self.isAnswer = false
self.inputAnswer = ""
}
}, label: {
Label("Check", systemImage: "checkmark.rectangle.fill")
.frame(maxWidth : .infinity)
.frame(height : 60)
.font(.headline)
.foregroundColor(.white)
.multilineTextAlignment(.center)
.background(Color.green)
.cornerRadius(10)
.shadow(color: .gray.opacity(0.4), radius: 3, x: 3, y: 3)
.padding()
})
.alert(isPresented : $showAlert) {
Alert(title: Text(isAnswer ? "Nice! that is answer!" : "Sorry, It was not answer.."), message: Text(isAnswer ? "You got an answer! Cool! 🥰" : "It's OK!, Keep studying! 😋"), dismissButton: .default(Text("OK")) {
makeNewCard()
})
}
.disabled(inputAnswer.count == 0)
} // vst
.padding()
.onAppear {
makeNewCard()
}
.navigationTitle("Flashcard Game 🎲")
}
}
extension FlashCardView {
func makeNewCard() {
if isGeneral == true {
randomWord = itemModel.makeRandomChildren(item: item)
} else {
randomWord = itemModel.makeRandomFavoriteChildren(item: item)
}
}
}

Add onEditingChanged to the keyboard and add a conditional to the navBar.
If the navBar doesn't hide when the user answers the question, add another toggle to onCommit.
import SwiftUI
struct ContentView: View {
#State var inputAnswer: String = ""
#State var isTyping: Bool = false
var body: some View {
NavigationView {
VStack(alignment: .center) {
Text("Hide navbar when user interacts with the textField")
.padding()
TextField("What is the answer?", text: $inputAnswer, onEditingChanged: {
self.isTyping = $0 // <= Toggle boolean if user interacts with the textField
})
.keyboardType(.default)
}
.navigationTitle("Home")
.navigationBarHidden(isTyping ? true : false) // <= hide on the condition of the boolean
}
}
}

Related

Can't sheet with button in ListView SwiftUI

I have a list. In the List there are 2 buttons.
I want to click on each button to present another view with Sheet.
When I first click it it works, but the second time or another tap button it doesn't present the view. Hope you can help me.
My code
My design
Read up on how to use Buttons and sheets. Typically Buttons triggering a sheet is used like this:
EDIT: with suggestion from Philip Dukhov, replace:
Button("Learning") {
}.sheet(isPresented: $isLearning, content: {
LearningView()
})
.onTapGesture {
self.isLearning = true
}
with:
Button(action: {isLearning = true}) {
Text("Learning")
}
.sheet(isPresented: $isLearning) {
LearningView()
}
and do the same for "Test" button, with "isTest" instead of "isLearning" and "TestViewCategory()" instead of "LearningView()".
EDIT 2:
Update "TestView" with:
struct TestView: View {
var title = ""
let models = modelItems
var body: some View {
ScrollView {
VStack {
ForEach(models) { model in
TopicList(model: model)
}
}
}
.navigationBarTitle(title, displayMode: .inline)
.onAppear {
UITableView.appearance().separatorStyle = .none
}
.animation(.spring())
}
}
EDIT 3: here is the test code that works for me:
import SwiftUI
#main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
TestView()
}
}
}
struct ButtonView: View {
#State var isLearning: Bool = false
#State var isTest: Bool = false
var body: some View {
HStack {
Button(action: {isLearning = true}) {
Text("Learning")
}
.sheet(isPresented: $isLearning) {
Text("LearningView")
}
.font(.system(size: 16))
.frame(width: 132 , height: 48)
.background(Color(.white))
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color(#colorLiteral(red: 0.9259920716, green: 0.9261471629, blue: 0.9259716272, alpha: 1)), lineWidth: 1)
)
Button(action: {isTest = true}) {
Text("Test")
}
.sheet(isPresented: $isTest) {
Text("TestViewCategory")
}
.font(.system(size: 16))
.frame(width: 132 , height: 48)
.background(Color(.white))
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color(#colorLiteral(red: 0.9259920716, green: 0.9261471629, blue: 0.9259716272, alpha: 1)), lineWidth: 1)
)
}
}
}
struct TopicList: View {
// for testing
let model: String
#State private var showSubItem = false
var body: some View {
VStack {
HStack {
Image(systemName: showSubItem ? "arrow.up.circle" : "arrow.down.circle")
.resizable()
.frame(width: 26, height: 26)
.onTapGesture {
withAnimation {
showSubItem.toggle()
}
}
VStack {
VStack(alignment: .leading) {
Text("title")
.font(.custom("Poppins-Regular", size: 24))
.padding(.top,9)
.padding(.bottom,4)
HStack {
Text("Open date")
.font(.custom("Poppins-Regular", size: 12))
Text("Open date")
.font(.custom("Poppins-Regular", size: 12))
Text("Due date")
.font(.custom("Poppins-Regular", size: 12))
Text("Due date")
.font(.custom("Poppins-Regular", size: 12))
}
}
.padding(.leading,17)
.frame(width: 320, height: 70)
.fixedSize(horizontal: false, vertical: true)
if showSubItem {
ButtonView()
.padding(.top,12)
.fixedSize(horizontal: false, vertical: true)
.transition(.opacity)
.transition(.slide)
.padding(.bottom,13)
}
}
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color(#colorLiteral(red: 0.9259920716, green: 0.9261471629, blue: 0.9259716272, alpha: 1)), lineWidth: 1)
)
}
}
}
}
struct TestView: View {
var title = "nav title"
let models = ["1","2","3"]
var body: some View {
ScrollView {
VStack {
ForEach(models, id: \.self) { model in
TopicList(model: model)
}
}
}
.navigationBarTitle(title, displayMode: .inline)
.onAppear {
UITableView.appearance().separatorStyle = .none
}
.animation(.spring())
}
}

SwiftUI Binding Data

trying to bring data from LeadDetailUI to formUI to be able to edit the data in formUI and for the life of me can't figure this out, not sure on way to go (Bindings or environmentObject). eighthor way can't get it to work. I tried with bindings couldn't get it to work. please help with example on how to do this.
struct LeadDetailUI: View {
#ObservedObject var viewModel: getCustomerData
#State var tbl11 = ""
#State var tbl12 = ""
#State var tbl13 = ""
#State var tbl14 = ""
#State var tbl15 = ""
#State var tbl16 = ""
#State var tbl17 = ""
#State var tbl21 = ""
#State var tbl22 = 0
#State var tbl23 = 0
#State var tbl24 = 0
#State var tbl25 = 0
#State var tbl26 = ""
#State var tbl27 = ""
#State var l11 = ""
#State var l12 = ""
#State var l13 = ""
#State var l14 = ""
#State var l15 = ""
#State var l16 = ""
#State var l17 = ""
#State var l21 = ""
#State var l22 = ""
#State var l23 = ""
#State var l24 = ""
#State var l25 = ""
#State var l26 = ""
#State var l27 = ""
var body: some View {
NavigationView {
VStack() {
ScrollView(self.height > 700 ? .init() : .vertical, showsIndicators: true) {
VStack(alignment: .trailing, spacing: 13) {
HStack {
TextField("Peter Balsamo", text: $name).font(.title)
.padding(.top, 3)
.padding(.leading, 20)
.padding(.bottom, -10)
//.redacted(reason: .placeholder)
Text("Following").font(.headline)
.padding(.top, 10)
Button(action: {
}) {
Image(systemName: "star.fill")
.resizable()
.frame(width: 20, height: 20)
.foregroundColor(Color.orange)
.padding(.top, 7)
.padding(.trailing, 15)
}
}
Divider()
VStack {
HStack {
VStack(alignment: .leading, spacing: 5, content: {
TextField("Amount", text: $amount).font(.largeTitle)
.offset(y: -3)
TextField("Address", text: $address).font(.title3)
TextField("City", text: $city).font(.title3)
TextField("Sale Date:", text: $l1datetext).font(.caption2)
.padding(.top, 15)
TextField("Date:", text: $date).font(.headline)
.padding(.top, -5)
})
.padding(.bottom, 0)
.padding(.leading, 15)
Spacer()
VStack(alignment: .trailing, spacing: 0, content: {
Image("taylor_swift_profile")
.resizable()
.frame(width: 115, height: 115)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 2))
.padding(.top, -25)
TextField("Lead#", text: $id).font(.caption2)
.multilineTextAlignment(.trailing)
.padding(.top, 15)
})
.frame(width: 120)
.padding(.trailing, 10)
Spacer()
}
HStack {
VStack(alignment: .leading, spacing: 0, content: {
HStack {
Toggle("", isOn: $showingSold.animation(.spring()))
.frame(width:80, height: 30)
.toggleStyle(SwitchToggleStyle(tint: .blue))
.clipShape(RoundedRectangle(cornerRadius: 10))
if showingSold {
Text("Priority").font(.headline)
.background(Color.red.cornerRadius(10))
.foregroundColor(.white)
.padding(.leading, 10)
}
}
})
Spacer()
Button(action: {
showFullscreen.toggle()
}) {
Text("Map")
.fontWeight(.bold)
.frame(width:115, height: 30)
.foregroundColor(.white)
.background(Color(.systemBlue))
.clipShape(RoundedRectangle(cornerRadius: 10))
}
.padding(.trailing, 20)
}
.padding(.bottom, 30)
}
.fullScreenCover(isPresented: $showFullscreen, content: {
HomeMap()
})
}
.foregroundColor(self.color == 0 ? Color.black : Color.white)
.background(self.color == 0 ? Color.yellow : Color.purple)
.clipShape(CustomShape(corner: .bottomLeft, radii: 55))
ScrollView(self.height > 800 ? .init() : .vertical, showsIndicators: false) {
let first = DataUI(name: tbl11, label: l11)
let second = DataUI(name: tbl12, label: l12)
let third = DataUI(name: tbl13, label: l13)
let fourth = DataUI(name: tbl14, label: l14)
let fifth = DataUI(name: tbl15, label: l15)
let sixth = DataUI(name: tbl16, label: l16)
let seventh = DataUI(name: tbl17, label: l17)
let eighth = DataUI(name: tbl21, label: l21)
let ninth = DataUI(name: "\(tbl22)", label: l22)
let tenth = DataUI(name: "\(tbl23)", label: l23)
let eleven = DataUI(name: "\(tbl24)", label: l24)
let twelve = DataUI(name: "\(tbl25)", label: l25)
let thirteen = DataUI(name: tbl26, label: l26)
let fourteen = DataUI(name: tbl27, label: l27)
let customers = [first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth, eleven, twelve,thirteen, fourteen]
List(customers) { customer in
CenterViewUI(formData: customer)
}
}
.edgesIgnoringSafeArea(.all)
.statusBar(hidden: true)
.animation(.default)
BottomViewUI(comments: self.$comments, lnewsTitle: self.$lnewsTitle, index: $index)
}
.shadow(color: Color.white.opacity(0.2), radius: 5, x: 0, y: 2)
}
.navigationTitle("Profile")
.navigationBarHidden(false)
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems (
leading:
Button(action: {
showActionSheet.toggle()
}) {
Image(systemName: "square.and.arrow.up")
.resizable()
.frame(width: 20, height: 20)
},
trailing:
//NavigationLink(destination: FormUI(frm11: $tbl11)) {
Button(action: {
showSheet.toggle()
}, label: {
Text("Edit")
.actionSheet(isPresented: $showActionSheet, content: getActionSheet)
.sheet(isPresented: $showSheet, content: {
FormUI()
})
.foregroundColor(self.color == 0 ? Color.yellow : Color.purple)
}
}
struct DataUI: Identifiable {
var id = UUID().uuidString
var name: String
var label : String
}
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
Group {
LeadDetailUI(viewModel: getCustomerData())
.preferredColorScheme(.dark)
}
}
}
public struct FormUI: View {
#Environment(\.presentationMode) var presentationMode
#EnvironmentObject var viewModel: getCustomerData
private var db = Firestore.firestore()
#State var frm11 = ""
#State var frm12 = ""
#State var frm13 = ""
#State var frm14 = ""
#State var frm15 = ""
#State var frm16 = ""
#State var frm17 = ""
#State var frm18 = ""
#State var frm19 = ""
public var body: some View {
NavigationView {
VStack {
ScrollView(self.height > 800 ? .init() : .vertical, showsIndicators: false) {
VStack {
//ForEach(self.viewModel.data) { i in
Form {
Section {
HStack{
VStack{
Image("taylor_swift_profile")
.resizable()
.frame(width: 75, height: 75)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 2))
.padding()
Button(action: {}, label: {
Text("Edit")
.font(.caption)
.padding(.top, -15)
.foregroundColor(self.color == 0 ? Color.purple : Color.red)
})
}
.padding(.leading, -30)
Divider()
Spacer()
VStack(spacing: 12) {
TextField("First", text: $frm11)
TextField("Last", text: $frm12)
Picker(selection: $selection, label:
TextField("Company", text: $callback)) {
ForEach(0 ..< pickContractor.count) {
Text(self.pickContractor[$0])
}
}
}
.font(.system(size: 20.0))
.multilineTextAlignment(.leading)
}
}
.font(.headline)
.padding(.leading, 18)
Section(header: Text("Customer Info")) {
HStack {
Text("Address:")
.formTextStyle()
Spacer()
TextField("address", text: $address)
.formStyle()
}
HStack {
Text("City:")
.formTextStyle()
Spacer()
TextField("city", text: $city)
.formStyle()
}
HStack {
Text("State:")
.formTextStyle()
.multilineTextAlignment(.leading)
Spacer()
TextField("state", text: $state)
.formStyle()
.frame(minWidth: 50, maxWidth: 60)
.autocapitalization(.allCharacters)
.multilineTextAlignment(.leading)
//.padding(.leading, )
Spacer()
Text("Zip:")
.formTextStyle()
TextField("zip", text: $zip)
.formStyle()
.frame(minWidth: 100, maxWidth: 145)
.keyboardType(.numberPad)
}
HStack {
Text("Phone:")
.formTextStyle()
Spacer()
TextField("phone", text: $phone)
.formStyle()
.keyboardType(.numberPad)
}
HStack {
Text("Amount:")
.formTextStyle()
Spacer()
Stepper(
onIncrement: {
stepperValue += 1000
},
onDecrement: {
stepperValue -= 1000
},
label: {
TextField("amount", text: $amount)
.formStyle()
})
}
HStack {
Text("Email:")
.formTextStyle()
Spacer()
TextField("email", text: $email)
.formStyle()
.keyboardType(.emailAddress)
}
}
Section {
HStack {
Text("Salesman:")
.formTextStyle()
Spacer()
TextField("salesman", text: $salesman)
}
HStack {
Text("Job:")
.formTextStyle()
Spacer()
TextField("job", text: $jobName)
.formStyle()
}
HStack {
Text("Product:")
.formTextStyle()
Spacer()
TextField("product", text: $adName)
.formStyle()
}
HStack {
Text("Quantity:")
.formTextStyle()
Spacer()
TextField("quantity", text: $frm25)
.formStyle()
.keyboardType(.numberPad)
}
HStack {
Text("Apt Date:")
.formTextStyle()
Spacer()
DatePicker(selection: $selDate, displayedComponents: .date) {
TextField("", text: $aptdate)
.formStyle()
}
}
HStack {
Text("Comments:")
.formTextStyle()
Spacer()
TextEditor(text: $comment)
}
}
Section(header: Text("Misc")) {
HStack {
Toggle(isOn: $isOn) {
Text("\(self.isOn == true ? "Active":"Not Active")")
.formTextStyle()
}
.toggleStyle(SwitchToggleStyle(tint: .purple))
}
HStack {
Text("Date")
.formTextStyle()
Spacer()
DatePicker(selection: $selDate, displayedComponents: .date, label: {
TextField("", text: $date)
})
}
HStack {
Text("Spouse")
.formTextStyle()
Spacer()
TextField("spouse", text: $spouse)
}
HStack {
Text("Called Back")
.formTextStyle()
Spacer()
Picker(selection: $selection, label:
TextField("", text: $callback)) {
ForEach(0 ..< callbackPicker.count) {
Text(self.callbackPicker[$0])
}
}
}
HStack {
Text("Rate")
.formTextStyle()
Spacer()
Picker(selection: $selection, label:
TextField("", text: $rate)) {
ForEach(0 ..< pickRate.count) {
Text(verbatim: self.pickRate[$0])
}
}
}
HStack {
Text("Photo")
.formTextStyle()
Spacer()
TextField("photo", text: $photo)
}
}
}
.font(.system(size: 20.0))
.padding(.top, -40)
}
}
}
.navigationTitle("Data Entry")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Image(systemName: "xmark.circle").font(.largeTitle)
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
//if !frm11.isEmpty && !frm12.isEmpty {
saveData()
resetTextFields()
self.alert.toggle()
}, label: {
Text("Save")
}
}
.alert(isPresented: $alert) {
Alert(title: Text("Upload Complete"), message: Text("Successfully updated the data"), dismissButton: .default(Text("Ok")))
}
}
.accentColor(self.color == 0 ? Color.purple : Color.red)
}
private func saveData() {
let uid = Auth.auth().currentUser!.uid
var ref: DocumentReference? = nil
ref = db.collection("Customers").addDocument(data: [
"active": frm30,
"custId": frm12,
"custNo": custNo,
"leadNo": leadNo,
"first": frm11,
"lastname": frm12,
"contractor": frm13,
"city": city,
"state": state,
"zip": zip,
"phone": phone,
"amount": Int(amount) as Any,
"email": email,
"rate": rate,
"salesNo": saleNo,
"jobNo": jobNo,
"adNo": adNo,
"quan": Int(frm25) as Any,
"start": NSNull(),
"completion": NSNull(),
"lastUpdate": Timestamp(date: Date()),
"creationDate": Timestamp(date: Date()),
"aptdate": aptdate,
"comments": comment,
"spouse": spouse,
"photo": photo,
"uid": uid,
]) { error in
if let error = error {
print("Error adding document: \(error)")
} else {
print("Document added with ID: \(ref!.documentID)")
}
}
}
func updateData() {
db.collection("Customer")
.document()
.setData(["active":self.frm30,"custId":self.frm12,"custNo":self.custNo,"leadNo":self.leadNo,"first":self.frm11,"lastname":self.frm12,"contractor":self.frm13,"city":self.city,"state":self.state,"zip":self.zip,"phone":self.phone,"amount":self.amount,"email":self.email,"rate":self.rate,"salesNo":self.saleNo,"jobNo":self.jobNo,"adNo":self.adNo,"start":self.start,"lastUpdate":Timestamp(date:Date()),"aptdate":self.aptdate,"comments":self.comment,"spouse":self.spouse,"photo":self.photo]) { (error) in
if error != nil{
print((error?.localizedDescription)!)
return
}
//self.presentation.wrappedValue.dismiss()
}
}
}
struct FormUI_Previews: PreviewProvider {
static var previews: some View {
FormUI()
.preferredColorScheme(.dark)
}
}

Pass to Another View after Success View Appears

After seeing the popup view that says your credit card saved successfully. I want to see this popup for 2-3 seconds then to pass another view called AddressView. Maybe it is irrelevant but I also added that popup view and the name is SuccessCardView.
#State private(set) var successAlert = false
ZStack {
HStack {
Button(action: {
self.isListTapped.toggle()
}, label: { CustomButton(title: "Listeden Sec", icon: .none, status: .enable, width: 150)})
Button(action: {
self.isSaved.toggle()
self.creditCards.append(self.creditCard)
print(self.creditCards[0].cardNumber)
if self.creditCards[0].cardNumber == "" {
self.showingAlert = true
} else if self.creditCards[0].cardNumber.count == 16 {
self.successAlert = true
}
}, label: { CustomButton(title: "Kaydet", icon: .none, status: .enable, width: 150)})
.alert(isPresented: $showingAlert) {
Alert(title: Text("Kart Bilgileri Hatali"), message: Text("Tekrar Kontrol Edin"), dismissButton: .default(Text("Got it!")))
}
}
SuccessCardView(isShown: $successAlert) // I want to show that view than jump to another view
}
struct SuccessCardView: View {
#Binding var isShown: Bool
#State var viewState = CGSize.zero
var body: some View {
VStack {
ZStack {
Rectangle()
.foregroundColor(Color(#colorLiteral(red: 0, green: 0.6588235294, blue: 0.5254901961, alpha: 1)))
.cornerRadius(10)
.frame(width: 355, height: 76)
HStack {
VStack(alignment: .leading) {
Text("Tebrikler!")
.font(Font.custom("SFCompactDisplay-Bold", size: 16))
.foregroundColor(.white)
Text("Kart Basariyla Eklendi")
.font(Font.custom("SFCompactDisplay", size: 14))
.foregroundColor(.white)
}
.offset(x: -70)
}
}
Spacer()
}
.offset(y: isShown ? .zero : -UIScreen.main.bounds.size.height)
.offset(y: viewState.height )
.animation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0))
.offset(y: -100)
}
}
It is not clear where/how is AddressView configured, but you can do the following
} else if self.creditCards[0].cardNumber.count == 16 {
self.successAlert = true
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.successAlert = false // hide popup
self.showAddressView = true // eg. activate navigation link
}
}

Tap gesture on buttons response randomly in SwiftUI

I have a My Profile form in my app. In the form I have some buttons. Among them 5 buttons are used to present custom drop down menus to select Sax, Blood, Nationality, and so on. However, when I tap these buttons sometime they response some time don't. For example, if I tap them 10 time they response 2 or 3 times. Some time they work for long tap. I have spent days on this matter, but could not identify any problem in my code. Is there anyone who faced this sort of problems? Could anyone figure out what is the actual problem. By the way, all other buttons in my app working absolutely fine.
This is the code for first 3 buttons in red rectangle in the picture
import SwiftUI
struct FormPartTwoView: View {
#Binding var gender: String
#Binding var blood: String
#Binding var nationality: String
#Binding var showingGenderPicker: Bool
#Binding var showingBloodGroupPicker: Bool
#Binding var showingNationalityPicker: Bool
#ObservedObject var userProfile = UserProfileViewModel()
#ObservedObject var userProfileUpdate = UserProfileUpdateViewModel()
var body: some View {
GeometryReader { geometry in
HStack {
Button(action: {
self.showingGenderPicker.toggle()
self.showingBloodGroupPicker = false
self.showingNationalityPicker = false
}) {
VStack {
TextField("Gender", text: self.$gender)
.padding(.horizontal)
.disabled(true)
}
.font(.system(size: 13))
.frame(height: 40)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(Color("Border2"), lineWidth: 1)
)
}
.buttonStyle(PlainButtonStyle())
Button(action: {
self.showingBloodGroupPicker.toggle()
self.showingGenderPicker = false
self.showingNationalityPicker = false
}) {
VStack {
TextField("Blood", text: self.$blood)
.padding(.horizontal)
.disabled(true)
}
.font(.system(size: 13))
.frame(height: 40)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(Color("Border2"), lineWidth: 1)
)
}
.buttonStyle(PlainButtonStyle())
Button(action: {
self.showingNationalityPicker.toggle()
self.showingGenderPicker = false
self.showingBloodGroupPicker = false
}) {
VStack {
TextField("Nationality", text: self.$nationality)
.padding(.horizontal)
.disabled(true)
}
.font(.system(size: 13))
.frame(height: 40)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(Color("Border2"), lineWidth: 1)
)
}
.buttonStyle(PlainButtonStyle())
}
.frame(width: geometry.size.width, height: 40)
}
}
}
struct FormPartTwoView_Previews: PreviewProvider {
static var previews: some View {
FormPartTwoView(gender: .constant(""), blood: .constant(""), nationality: .constant(""), showingGenderPicker: .constant(false), showingBloodGroupPicker: .constant(false), showingNationalityPicker: .constant(false))
}
}
This is the code for second tow Buttons:
import SwiftUI
struct FormPartFiveView: View {
#Binding var district: String
#Binding var upazila: String
#Binding var postcode: String
#Binding var showingUpazilaPicker: Bool
#Binding var showingDistrictPicker: Bool
#ObservedObject var userProfileUpdate = UserProfileUpdateViewModel()
var body: some View {
GeometryReader { geometry in
HStack {
Button(action: {
self.showingDistrictPicker.toggle()
self.showingUpazilaPicker = false
}) {
VStack {
Text("\(self.district == "" ? "District" : self.district)")
.foregroundColor(self.district == "" ? Color.gray : Color.black)
.padding(.horizontal)
}
.font(.system(size: 13))
.frame(width: geometry.size.width/3.2, height: 40)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(Color("Border2"), lineWidth: 1)
)
}
.buttonStyle(PlainButtonStyle())
Button(action: {
self.showingUpazilaPicker.toggle()
self.showingDistrictPicker = false
}) {
VStack {
Text("\(self.upazila == "" ? "Upazila" : self.upazila)")
.foregroundColor(self.upazila == "" ? Color.gray : Color.black)
.padding(.horizontal)
}
.font(.system(size: 13))
.frame(width: geometry.size.width/3.2, height: 40)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(Color("Border2"), lineWidth: 1)
)
}
.buttonStyle(PlainButtonStyle())
VStack {
TextField("Postcode", text: self.$postcode)
.padding(.horizontal)
}
.font(.system(size: 13))
.frame(width: 100, height: 40)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(Color("Border2"), lineWidth: 1)
)
}
.frame(width: geometry.size.width, height: 40)
}
}
}
struct FormPartFiveView_Previews: PreviewProvider {
static var previews: some View {
FormPartFiveView(district: .constant(""), upazila: .constant(""), postcode: .constant(""), showingUpazilaPicker: .constant(false), showingDistrictPicker: .constant(false))
}
}

SwiftUI multiline text always truncating at 1 line

I am trying to create a list of options for a user to choose from. The debug preview shows the general look and feel. My problem is that passing nil to .lineLimit in MultipleChoiceOption doesn't allow the text to grow beyond 1 line. How can I correct this?
struct Card<Content: View> : View {
private let content: () -> Content
init(content: #escaping () -> Content) {
self.content = content
}
private let shadowColor = Color(red: 69 / 255, green: 81 / 255, blue: 84 / 255, opacity: 0.1)
var body: some View {
ZStack {
self.content()
.padding()
.background(RoundedRectangle(cornerRadius: 22, style: .continuous)
.foregroundColor(.white)
.shadow(color: shadowColor, radius: 10, x: 0, y: 5)
)
}
.aspectRatio(0.544, contentMode: .fit)
.padding()
}
}
struct MultipleChoiceOption : View {
var option: String
#State var isSelected: Bool
var body: some View {
ZStack {
Rectangle()
.foregroundColor(self.isSelected ? .gray : .white)
.cornerRadius(6)
.border(Color.gray, width: 1, cornerRadius: 6)
Text(self.option)
.font(.body)
.foregroundColor(self.isSelected ? .white : .black)
.padding()
.multilineTextAlignment(.leading)
.lineLimit(nil)
}
}
}
struct MultipleChoice : View {
#State var selectedIndex = 1
var options: [String] = [
"Hello World",
"How are you?",
"This is a longer test This is a longer test This is a longer test This is a longer test This is a longer test This is a longer test"
]
var body: some View {
GeometryReader { geometry in
ScrollView {
VStack(alignment: .leading, spacing: 12) {
ForEach(self.options.indices) { i in
MultipleChoiceOption(option: self.options[i],
isSelected: i == self.selectedIndex)
.tapAction { self.selectedIndex = i }
}
}
.frame(width: geometry.size.width)
}
}
.padding()
}
}
struct MultipleChoiceCard : View {
var question: String = "Is this a question?"
var body: some View {
Card {
VStack(spacing: 30) {
Text(self.question)
MultipleChoice()
}
}
}
}
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
// NavigationView {
VStack {
MultipleChoiceCard()
Button(action: {
}) {
Text("Next")
.padding()
.foregroundColor(.white)
.background(Color.orange)
.cornerRadius(10)
}
}
.padding()
// .navigationBarTitle(Text("Hello"))
// }
}
}
#endif
Please see this answer for Xcode 11 GM:
https://stackoverflow.com/a/56604599/30602
Summary: add .fixedSize(horizontal: false, vertical: true) — this worked for me in my use case.
The modifier fixedSize() prevents the truncation of multiline text.
Inside HStack
Text("text").fixedSize(horizontal: false, vertical: true)
Inside VStack
Text("text").fixedSize(horizontal: true, vertical: false)
There is currently a bug in SwiftUI causing the nil lineLimit to not work.
If you MUST fix this now, you can wrap a UITextField:
https://icalvin.dev/post/403
I had the same problem and used this workaround:
Add the modifier:
.frame(idealHeight: .infinity)