New in SwiftUI 3: New in SwiftUI 3: Toolbar on Keyboard in SwiftUI 3, iOS 15

DevTechie Inc
Apr 6, 2022

SwiftUI introduced ToolbarItem with iOS 14. ToolbarItem represents an item which can be placed in navigation baror toolbar . Starting iOS 15 ToolbarItem can attach item on top. of keyboard. This gives us ability to add views above the keyboard.

Let’s look at a simple example

struct KeyboardToolbar: View {
    
    @State private var message = ""
    
    var body: some View {
        VStack {
            List(0..<50) { idx in
                Text("Item #\(idx)")
            }
            TextField("Message", text: $message, prompt: Text("Enter message here..."))
                .textFieldStyle(.roundedBorder)
                .padding()
                .toolbar {
                    ToolbarItem(placement: .keyboard) {
                        Button("Done") {
                            print("Done pressed!")
                        }
                    }
                }
        }
    }
}
Notice “Done” button placed on top of keyboard. At this point, it doesn’t do much and prints a message in output window. Let’s make it more useful by dismissing keyboard when “Done” is pressed.

In order to dismiss keyboard, we will leverage new FocusState property wrapper. (If you want to learn more about property wrappers check out here)

struct KeyboardToolbar: View {
    
    @State private var message = ""
    @FocusState private var dismiss: Bool
    
    var body: some View {
        VStack {
            List(0..<50) { idx in
                Text("Item #\(idx)")
            }
            TextField("Message", text: $message, prompt: Text("Enter message here..."))
                .textFieldStyle(.roundedBorder)
                .focused($dismiss)
                .padding()
                .toolbar {
                    ToolbarItem(placement: .keyboard) {
                        Button("Done") {
                            dismiss.toggle()
                        }
                    }
                }
        }
    }
}
Output:

When used with ToolbarItem, our button will appear in center. If we want to move it on one side then we will use ToolbarItemGroup

struct KeyboardToolbar: View {
    
    @State private var message = ""
    @FocusState private var dismiss: Bool
    
    var body: some View {
        VStack {
            List(0..<50) { idx in
                Text("Item #\(idx)")
            }
            TextField("Message", text: $message, prompt: Text("Enter message here..."))
                .textFieldStyle(.roundedBorder)
                .focused($dismiss)
                .padding()
                .toolbar {
                    ToolbarItemGroup(placement: .keyboard) {
                        Spacer()
                        
                        Button("Done") {
                            dismiss.toggle()
                        }
                    }
                }
        }
    }
}
Much better 😍

Let’s create slightly complex UI. We will try to create “New Tweet” UI from twitter app:

struct TwitterTweetScreen: View {
    
    @State private var newTweet = "Tween will go here"
    
    var body: some View {
        NavigationView {
            TextEditor(text: $newTweet)
                .navigationBarTitleDisplayMode(.inline)
                .padding()
                .toolbar {
                    ToolbarItemGroup(placement: .navigationBarLeading) {
                        Button("Cancel")
                        {
                            print("Cancel pressed")
                        }
                        
                    }
                    
                    ToolbarItemGroup(placement: .navigationBarTrailing) {
                        Button{
                            print("Tweet tweet")
                        } label: {
                            Text("Tweet")
                                .bold()
                                .font(.title3)
                                .foregroundColor(.white)
                            
                        }
                        .padding(.horizontal)
                        .background(RoundedRectangle(cornerRadius: 10).fill(.blue.opacity(0.7)))
                    }
                    
                    ToolbarItemGroup(placement: .keyboard) {
                        Button {} label: {
                            Image(systemName: "photo")
                        }
                        .tint(Color.blue.opacity(0.7))
                        
                        Button {} label: {
                            Image(systemName: "livephoto")
                        }
                        .tint(Color.blue.opacity(0.7))
                        
                        Button {} label: {
                            Image(systemName: "chart.bar")
                        }
                        .tint(Color.blue.opacity(0.7))
                        
                        Button {} label: {
                            Image(systemName: "mappin.circle.fill")
                        }
                        .tint(Color.blue.opacity(0.7))
                        
                        Spacer()
                        
                        Button {} label: {
                            Image(systemName: "paperplane")
                        }
                        .tint(Color.blue.opacity(0.7))
                    }
                }
        }
    }
}
Output:


With that, we have reached the end of this article. Thank you once again for reading, if you liked it, don’t forget to subscribe our newsletter.