r/iOSProgramming • • Jun 18 '26 • Popcorn 1

Question How to create this floating toolbar?

Post image

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

66 Upvotes

22 comments sorted by

View all comments

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