scenee/FloatingPanel

Achieving Apple Maps style child floating panels

WillBishop opened this issue · 1 comments

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.