2

I'm attempting to adapt UIToolbar to UIViewRepresentable to use it within SwiftUI. I'm required to support iOS 13, otherwise I would be using Apple's new toolbar in iOS 14.

So far I have code that displays the toolbar on the screen, however it doesn't extend to the safe area at the bottom of the screen for devices with no home button.

Does anyone have any suggestions or references for complete UIToolbar implementations in SwiftUI?

Image:

https://i.stack.imgur.com/Weutp.png

My code:

// TestView.swift
var body: some View {
  VStack {
    Toolbar(items: [
      UIBarButtonItem(
         title: "Done",
         style: .plain,
         target: nil,
         action: nil
    ])
  }
}

// Toolbar.swift
import SwiftUI
import UIKit
import Foundation

struct Toolbar: UIViewRepresentable {
    typealias UIViewType = UIToolbar
    var items: [UIBarButtonItem]
    var toolbar: UIToolbar
    
    init(items: [UIBarButtonItem]) {
        self.toolbar = UIToolbar()
        self.items = items
    }

    func makeUIView(context: UIViewRepresentableContext<Toolbar>) -> UIToolbar {
        toolbar.setItems(self.items, animated: true)
        toolbar.barStyle = UIBarStyle.default
        toolbar.sizeToFit()
        return toolbar
    }
    
    func updateUIView(_ uiView: UIToolbar, context: UIViewRepresentableContext<Toolbar>) {
    }
    
    func makeCoordinator() -> Toolbar.Coordinator {
        Coordinator(self)
    }
    
    final class Coordinator: NSObject, UIToolbarDelegate, UIBarPositioning {
        var toolbar: Toolbar
        var barPosition: UIBarPosition
        
        init(_ toolbar: Toolbar) {
            self.toolbar = toolbar
            self.barPosition = .bottom
        }
        
        private func position(for: UIToolbar) -> UIBarPosition {
            return .bottom
        }
    }
}

1 Answers1

1

Any UIViewRepresentable in context of SwiftUI view hierarchy is just a view, so it should be layout by SwiftUI instruments

Here is fixed part (w/o changes in your representable)

Tested with Xcode 11.4 / iOS 13.4

demo

struct DemoToolbarView: View {
    var body: some View {
        VStack {
            Toolbar(items: [
                UIBarButtonItem(
                    title: "Done",
                    style: .plain,
                    target: nil,
                    action: nil)
            ])
        }.frame(maxHeight: .infinity, alignment: .bottom)
        .edgesIgnoringSafeArea(.bottom)
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • This is great, thank you! Do you have any suggestions on how to increase the height of the toolbar to not be too close to the bottom swipe up indicator? I've tried specifying the min height on the SwiftUI frame but nothing seems to affect it – Swift Enthusiast Jul 01 '20 at 19:08
  • @SwiftEnthusiast I believe the best way to do that would be to remove the `. edgesIgnoringSafeArea(.bottom)` from the above. – bplattenburg Jul 01 '20 at 20:12