Achieving Apple Maps style child floating panels
Description
How do I add a child panel which makes the root panel invisible underneath a la Apple Maps.
Expected behavior
I expected a child VC to behave like Apple Maps, where only one panel is ever visible.
Actual behavior
Adding a child FloatingPanel to a FloatingPanelController results in a stack where both floating panels are visible, whereas in Apple Maps, only one panel is ever visible at any one time.
Steps to reproduce
Full Example Code
class ViewController: UIViewController, FloatingPanelControllerDelegate {
var fpc: FloatingPanelController!
override func viewDidLoad() {
super.viewDidLoad()
fpc = FloatingPanelController()
var rootVc = RandomTables()
fpc.delegate = self // Optional
fpc.set(contentViewController: rootVc)
fpc.track(scrollView: rootVc.tableView)
fpc.addPanel(toParent: self)
let addButton = UIButton(type: .system)
addButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(addButton)
addButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
addButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: -200).isActive = true
addButton.setTitle("Test", for: .normal)
addButton.addTarget(self, action: #selector(addChildVC), for: .touchUpInside)
}
@objc func addChildVC() {
let newVC = RandomTables()
let floating = FloatingPanelController()
floating.set(contentViewController: newVC)
floating.track(scrollView: newVC.tableView)
floating.addPanel(toParent: self.fpc, animated: true)
floating.delegate = self
}
}
class RandomTables: UIViewController, UITableViewDataSource {
var tableView = UITableView()
override func viewDidLoad() {
view.addSubview(tableView)
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
tableView.topAnchor.constraint(equalTo: self.view.topAnchor),
tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
])
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1000
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = String(describing: indexPath)
return cell
}
}
How do you display panel(s)?
- Add as child view controllers
- Present modally
How many panels do you displays?
- 2+
Environment
Library version
Latest at writing
Installation method
- Swift Package Manager
iOS version(s)
16.1
Xcode version
14.1v3
Actually, you are able to handle 2 panels by yourself to achieve this behavior. For example, the underneath panel hides after a detail panel shows and then the underneath panel shows again without its animation when a close button in the detail panel is tapped. Note that you need to keep an instance of FloatingPanelController for the underneath panel even when it's hiding and a detail panel is showing.