简体   繁体   中英

SwiftUI: Toolbar that covers bottom safeArea

I would like to implement a bottom toolbar that covers the bottom safeArea so that my bannerView can sit nicely above the toolbar without having my listView content peeking through. In UIKit, I can easily implement this by creating a UIToolbar and set the top and bottom anchors to view.safeAreaLayoutGuide.bottomAnchor and view.bottomAnchor .

How do I implement the same for SwiftUI?

Current SwiftUI implementation:

struct ListView: View {
    var body: some View {
        NavigationView {
            ZStack {
                List {
                    ForEach (0..<30) { i in
                        Text("Row \(i)")
                    }
                }
                
                VStack {
                    Spacer()
                    Rectangle()
                        .foregroundColor(Color.red)
                        .frame(height: 50)
                    //Toolbar??
                }
            }
            .navigationBarTitleDisplayMode(.inline)
            .listStyle(InsetGroupedListStyle())
            .toolbar {
                //Setting empty toolbar doesn't work
            }
        }
    }
}

UIKit equivalent implementation:

let toolbar: UIToolbar = {
    let tb = UIToolbar()
    tb.translatesAutoresizingMaskIntoConstraints = false
    return tb
}()

let bannerView: UIView = {
    let v = UIView()
    v.translatesAutoresizingMaskIntoConstraints = false
    v.backgroundColor = .systemRed
    return v
}()

override func viewDidLoad() {
    super.viewDidLoad()
    tableView = UITableView(frame: .zero, style: .insetGrouped)
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    
    view.addSubview(toolbar)
    view.addSubview(bannerView)
    toolbar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    toolbar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    toolbar.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    toolbar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
    
    bannerView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    bannerView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    bannerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
    bannerView.heightAnchor.constraint(equalToConstant: 50).isActive = true
}

SwiftUI results:

在此处输入图像描述

Desired results:

在此处输入图像描述

This is how it looks after adding ToolbarItemGroup in the toolbar and bottom padding to the list:

在此处输入图片说明

struct ContentView: View {

    @State var date: Date = Date()
    
    var body: some View {
           NavigationView {
               ZStack {
                   List {
                       ForEach (0..<30) { i in
                           Text("Row \(i)")
                       }
                   }.padding(.bottom, 20)
                   
                   VStack {
                       Spacer()
                       Rectangle()
                           .foregroundColor(Color.red)
                           .frame(height: 50)
                       //Toolbar??
                   }
               }
               .navigationBarTitleDisplayMode(.inline)
               .listStyle(InsetGroupedListStyle())
               .toolbar {
                ToolbarItemGroup(placement: .bottomBar) {}
               }
           }
       }
}

Your requirement isn't possible.

SwiftUI will show toolbar only if there is the item in it. Strictly speaking that is the proper behavior, the toolbar is meant for showing items, not for creating a background for something.

So you will have to use some alternative. I don't see why you wouldn't be able to use just a white rectangle that goes into the safe area but I don't know the rest of your app and I assume that there is some reason for that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM