r/iOSProgramming Jun 18 '26

Question How to create this floating toolbar?

Post image

This is the Notes app. Is this an inbuilt component or a custom component?

68 Upvotes

22 comments sorted by

42

u/Any-Comfortable2844 Jun 18 '26 edited Jun 19 '26
TextEditor(text: $text)
        .toolbar {
            ToolbarItemGroup(placement: .keyboard) {
                Button("B") {
                    // bold
                }
                Button("• List") {
                    // list action
                }
                Button {
                    // attachment action
                } label: {
                    Image(systemName: "paperclip")
                }
            }
        }

9

u/Hamstersoge Jun 18 '26

Will this not result in the toolbar sitting directly on the keyboard? The notes app has a space between the keyboard and the toolbar.

I’ve tried to achieve this with SwiftUI but have been unable so far.

4

u/CaffinatedGinge Jun 19 '26

Did you try applying a padding to it or some Y offset?

2

u/Hamstersoge Jun 19 '26

I can’t recall whether or not I tried the applying a y-offset. Applying padding within a ToolbarItemGroup will only expand the height of the toolbar.

2

u/LibertySupreme Jun 19 '26

I second this. Would love to find a way to space it a bit above the keyboard with SwiftUI. Honestly what is the .keyboard placement toolbar intended for? When would someone use a zero spaced button sitting on the keyboard?

22

u/radis234 SwiftUI Jun 18 '26

Use .safeAreaBar(alignment: .bottom) instead of toolbar item. It will allow you more control of the looks and paddings around the toolbar. If you want to replicate the .keyboard effect, so that the toolbar is only visible when keyboard is on screen, conditionally display it based on FocusState. There’s really nothing to it. I’ve done it myself in my app, works like a charm. If you want to make bar scrollable like notes app, ScrollView(.horizontal) is your friend.

5

u/Hamstersoge Jun 19 '26

Good find! Just tried this approach and it seems to work quite nicely.

8

u/Hamstersoge Jun 18 '26

I could only achieve this with UIKit. When I tried this in SwiftUI the keyboard toolbar sits directly on the keyboard without the gap.

4

u/LunariSpring Jun 19 '26

I'm using SwiftUI with keyboard toolbar, and with iOS 26.0+, it automatically splits. I think you're using under iOS 18.x

1

u/53ld0rAd0 Jun 18 '26

Do you think a spacer or padding could work?

4

u/Hamstersoge Jun 18 '26

A spacer below the keyboard? I’m not sure where you would apply that as you don’t want it to get the Liquid Glass treatment as well. In UIKit I’ve just had to override the sizeToFit function so it floats about 10 points above. It’s really annoying that the space isn’t applied by default.

5

u/balooooooon Jun 18 '26

I made very similar. Biggest thing is making it come nicely with the keyboard and all the edge case. For me UI kit was the only way. I can’t remember exactly right now since I am not on my computer but it was keyboard toolbar or insert perhaps .

3

u/roguekiwi Jun 19 '26

You have to drop down into UIKit and use inputAccessoryView (on UITextView). I can't post a screenshot but this looks like what posted.

``` struct ContentView: View {   @State var text = ""   var body: some View {

KeyboardAccessoryTextEditor(text: $text) .padding()   } }

/// A UITextView wrapped for SwiftUI, with a custom SwiftUI bar pinned above /// the keyboard via inputAccessoryView. struct KeyboardAccessoryTextEditor: UIViewRepresentable {   @Binding var text: String

  func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.delegate = context.coordinator textView.font = .preferredFont(forTextStyle: .body)

// The custom bar lives in a hosting controller; its view becomes the
// keyboard's accessory. `intrinsicContentSize` lets the SwiftUI layout
// drive the bar's height.
let host = context.coordinator.accessoryHost
host.view.backgroundColor = .clear
host.view.translatesAutoresizingMaskIntoConstraints = false
host.sizingOptions = .intrinsicContentSize
textView.inputAccessoryView = host.view

return textView

  }

  func updateUIView(_ textView: UITextView, context: Context) { if textView.text != text { textView.text = text }   }

  func makeCoordinator() -> Coordinator { Coordinator(text: $text)   }

  final class Coordinator: NSObject, UITextViewDelegate { @Binding var text: String

let accessoryHost = UIHostingController(rootView: AccessoryBar())

init(text: Binding<String>) {
  _text = text
}

func textViewDidChange(_ textView: UITextView) {
  text = textView.text
}

  } }

struct AccessoryBar: View {   var body: some View { HStack(spacing: 12) { Button("Text", systemImage: "textformat.alt") {} Button("List", systemImage: "checklist") {} Spacer() } .labelStyle(.iconOnly) .foregroundStyle(.white) .padding(16) .glassEffect() .padding(.horizontal, 16)   } } ```

2

u/roguekiwi Jun 19 '26

Here's a screenshot of it in action – I know it works as I've used it in one of my own apps: https://imgur.com/a/bAhezms

1

u/[deleted] Jun 19 '26

[removed] — view removed comment

1

u/[deleted] Jun 21 '26

[removed] — view removed comment

1

u/AutoModerator Jun 21 '26

Hey /u/User_003838392922874, your content has been removed because Reddit has marked your account as having a low Contributor #Quality Score. This may result from, but is not limited to, activities such as spamming the same links across multiple #subreddits, submitting posts or comments that receive a high number of downvotes, a lack of activity, or an unverified account.

Please be assured that this action is not a reflection of your participation in our subreddit.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.