iOS 13 SwiftUI 中的 UIToolbar?

UIToolbar in iOS 13 SwiftUI?

我正在尝试将 UIToolbar 改编为 UIViewRepresentable 以在 SwiftUI 中使用它。我需要支持 iOS 13,否则我将在 iOS 14.

中使用 Apple 的新工具栏

到目前为止,我有在屏幕上显示工具栏的代码,但是对于没有主页按钮的设备,它不会扩展到屏幕底部的安全区域。

有人对 SwiftUI 中的完整 UIToolbar 实现有任何建议或参考吗?

图片:

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

我的代码:

// 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
        }
    }
}

任何UIViewRepresentable在SwiftUI 视图层级的上下文中只是一个视图,所以它应该由SwiftUI instruments 布局

这是固定部分(w/o 可表示的变化)

测试 Xcode 11.4 / iOS 13.4

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)
    }
}