UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Dismiss Keyboard Activityview Toolbar with unexpected? behavior

Forums > SwiftUI

Hi all,

this is a follow up of my previous post regarding the toolbar added to dismiss a keyboard.

I followed the instrucions on the post to build a "helper view", which looks like this:

import SwiftUI

struct DismissKeyboard: ToolbarContent {

    let done: () -> Void

    var body: some ToolbarContent {

        ToolbarItemGroup(placement: .keyboard) {
            Spacer()
            Button("Done", action: done)
        }
    }

}

I tested it on a Textfield and it works great.

Then I prepared a "TextInputRow" view, which is just a Text and a TextField win an spacer in between. Added to the textField view is the toolbar view. The TextInputRow looks like this:

import SwiftUI

struct TextInputRow: View {

    var labelText: String
    var textFieldPlaceholder: String
    @State private var textFieldContent: String = ""
    @FocusState private var inputIsActive: Bool 

    var body: some View {

        HStack {
            Text("\(labelText) : ").bold()
            Spacer()
            TextField(textFieldPlaceholder, text: $textFieldContent).keyboardType(.decimalPad)
                .focused($inputIsActive)
                .toolbar {DismissKeyboard(done: doneAction)}
        }
        .padding()
        .onTapGesture { inputIsActive = false }
    }

    func doneAction ()-> Void {
        inputIsActive = false
    }

}

Now that I had both views, I build my actual view, which is a list of three TextInputView(s) (the App is sort of a calculator). However, nor the keyboard toolbar doesn't do what I expected. It build a "Done" button for each of the textFields, and each of the buttons works only for one of the texFields.

Any ideas? Thanks in advance!

2      

One idea is that you are passing a variable inputIsActive from your TextInputRow struct into a DismissKeyboard struct.

To Swift, these are two completely independent vars.

I am inclined to think you want to construct a binding to solve this.

See Apple's Binding Documentation

In Apple's documenations, notice how the data from one struct is passed into the second struct. In the second struct, the data is received in a variable that is annotated with an @Binding property wrapper. Per the documentation, this creates a two-way connection between a property that stores data, and a view that displays and changes the data.

I really don't know if this will solve your problem. But you asked for ideas, and this is where my brain led me.

2      

Thanks @Obelix for your input. I am not passing any var here and there. The only thing I am passing from "DismissKeyboard" to "TexInputRow" is an empty func, so that "TextInputRow" (or any other view witha textField) can implement whatever method to dismiss the keyboard. To put it simply, the var "inputIsActive" only lives within "TextInputRow" and it is even declared private...

2      

well, I did a little bit of progress... I replicated the original article I found on this very site, but I added a second TextField. I did this in order to to mess up my actual project with just tests... It looks like this:

import SwiftUI

struct ContentView: View {

    @State private var name = "Taylor Swift"
    @FocusState var isInputActive: Bool

    var body: some View {

        NavigationView {
            VStack {
                TextField("Enter your name", text: $name)
                    .textFieldStyle(.roundedBorder)
                    .focused($isInputActive)
                    .toolbar {
                        ToolbarItemGroup(placement: .keyboard) {
                            Spacer()

                            Button("Done") {
                                isInputActive = false
                            }
                        }
                    }
                    .padding()

               TextField("Enter your other name", text: $name)
                   .textFieldStyle(.roundedBorder)
                   .focused($isInputActive)
                   .toolbar {
                       ToolbarItemGroup(placement: .keyboard) {
                           Spacer()

                           Button("Done") {
                               isInputActive = false
                           }
                       }
                   }
                   .padding()
            }
         }
    }
}

If you copy-paste it into a new Xcode project, you will see this code also shows a duplicated "Done" button on the Keyboard Toolbar.

Now, on one of the TextFields I commented out one of the .toolbar{...} calls. So that it looks like this:

import SwiftUI

struct ContentView: View {

    @State private var name = "Taylor Swift"
    @FocusState var isInputActive: Bool

    var body: some View {

        NavigationView {
            VStack {
                TextField("Enter your name", text: $name)
                    .textFieldStyle(.roundedBorder)
                    .focused($isInputActive)
                    .toolbar {
                        ToolbarItemGroup(placement: .keyboard) {
                            Spacer()

                            Button("Done") {
                                isInputActive = false
                            }
                        }
                    }
                    .padding()

               TextField("Enter your other name", text: $name)
                   .textFieldStyle(.roundedBorder)
                   .focused($isInputActive)
//                   .toolbar {
//                       ToolbarItemGroup(placement: .keyboard) {
//                           Spacer()
//
//                           Button("Done") {
//                               isInputActive = false
//                           }
//                       }
//                   }
                   .padding()
            }
         }
    }
}

And this does indeed work. So it seems that, it has to be called once... Now the challange is to try to implement it on reusable views such as the "InputTextRow"...

Any help is welcomed, I am just starting with Swift and I am mostly doing trial-and-error here...

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.