FloatingPanel icon indicating copy to clipboard operation
FloatingPanel copied to clipboard

Animating new constraints for layout guide using FloatingPanelAdaptiveLayout

Open AlvaroFranco opened this issue 4 years ago • 1 comments

I've been using Floating Panel for a while with great results, but now I'm trying to implement a navigation controller inside of it, and I'm struggling using the adaptive layout to resize the panel height on every transition

Description

When using FloatingPanelAdaptiveLayoutAnchor, a layout guide is provided to adjust the panel height. If I try to update the constraints of the provided layout guide, the panel will resize without animation. In my case, I update the constraints to the current view controller in the navigation controller, so the panel always fits the current view controller

Expected behavior

The panel should animate the height changes when the layout guide constraints are updated, or at least having the option to enable/disable animations

Actual behavior

The panel doesn't animate the layout guide updates

Steps to reproduce

Implement a custom navigation controller subclass to store layout guide:

class CustomNavigationController: UINavigationController {

    var mainSpace = UILayoutGuide()
}

Create a regular floating panel with adaptive layout:

let customNavigationController = CustomNavigationController(rootViewController: firstVC)
customNavigationController.view.addLayoutGuide(customNavigationController.mainSpace)
floatingPanel.set(contentViewController: customNavigationController)
floatingPanel.isRemovalInteractionEnabled = true
floatingPanel.layout = CustomFloatingPanelAdaptiveLayout(targetGuide: customNavigationController.mainSpace)
            
self.present(floatingPanel, animated: true, completion: nil)

Then from each view controller update the layout guide:

(self.navigationController as? CustomNavigationController)?.mainSpace.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
(self.navigationController as? CustomNavigationController)?.mainSpace.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
(self.navigationController as? CustomNavigationController)?.mainSpace.bottomAnchor.constraint(equalTo: lastItem.bottomAnchor, constant: 20).isActive = true

I hacked it a little bit by calling layoutIfNeeded on floating controller view when the layout guide is updated (between navigation controller transitions) but it was very tricky to get right playing around with the view controller lifecycle.

Anyway, even I got it right, I'm getting [Assert] Internal NSLayoutConstraint clean-up problem after view moved leafward in the hierarchy: UIView:0x10df7d6a0: <UIView: 0x10df7d6a0; frame = (0 0; 414 930); autoresize = W+H; layer = <CALayer: 0x283cb5600>> on every update. I wasn't able to find references of that assert

Would be great to have this feature built in and working out of the box

How do you display panel(s)?

  • Present modally

How many panels do you displays?

  • 1

Environment

Library version

2.4.0

Installation method

  • CocoaPods

iOS version(s)

14.5.1

Xcode version

12.5

AlvaroFranco avatar Jun 16 '21 13:06 AlvaroFranco

How about calling FloatingPanelController.invalidateLayout() alongside layout updates in an animation block?

UIView.animate(...) {
    // update the layout guide...

   fpc.invalidateLayout()
}

scenee avatar Jul 03 '21 07:07 scenee