FloatingPanel icon indicating copy to clipboard operation
FloatingPanel copied to clipboard

iPad Rotation to Landscape - FloatingPanelSurfaceView height constraint not updated

Open MJFoxman opened this issue 6 years ago • 9 comments

Short description

On an iPad device, when rotating from portrait to landscape, the FloatingPanelLayout.updateHeight() method is not getting called. This results in an incorrect (based on portrait) height for the FloatingPanelSurfaceView.

Expected behavior

On any rotation on any device, the FloatingPanelSurfaceView's height constraint is updated

Actual behavior

On an iPad device, rotating from portrait to landscape, the FloatingPanelSurfaceView's height constraint is not updating, which can result in issues for the contentViewControllers view.

Steps to reproduce

Steps to Reproduce (using Maps example)

  1. update floatingPanel(_ vc:, layoutFor newCollection:) -> FloatingPanelLayout? (line 90) to always return the SearchPanelLandscapeLayout()
  2. in SearchPanelLandscapeLayout declaration: change the supportedPositions to .tip only and change the insetFor(position:) to return 330 for tip. Also comment out the prepareLayout(surfaceView:, in view:) -> [NSLayoutConstraint] method.
  3. Run the app on an iPad device in portrait mode
  4. Rotate the app and note the view no longer displays correctly
  5. If debugging, tap the "Debug View Hierarchy" button and note the height of the FloatingPanelSurfaceView is not large enough and the height constraint is still based off portrait calculation.

Environment

Library version 1.6.5 Installation method

  • [ ] CocoaPods
  • [x] Carthage
  • [ ] Git submodules

iOS version(s) 12.4 Xcode version 10.3

MJFoxman avatar Sep 05 '19 18:09 MJFoxman

I will investigate this issue. Thank you for your report.

scenee avatar Sep 07 '19 01:09 scenee

For now you are able to fix this as below.

  1. Create a subclass of FloatingPanelController
  2. override viewWillTransition(to size:with coordinator:) and call updateLayout() in the method.

And you need to returns a layout object for a transition size in floatingPanel(_:layoutFor:) delegate method.

I will consider this issue in v2.0 because this needs to update floatingPanel(_:layoutFor:) delegate method.

scenee avatar Sep 16 '19 06:09 scenee

updateLayout() must call in the DispatchQueue.main.async. Otherwise, problems still occur.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
  super.viewWillTransition(to: size, with: coordinator)
  DispatchQueue.main.async {
    self.updateLayout()
  }
}

powhu avatar May 05 '20 12:05 powhu

@SCENEE @powhu This code will not fix the issue , and iPad landscape layout still not updated and if you do not use DispatchQueue.main.async , even the iPhone layout breaked (the Portrait and Landscape reversed )

class FloatingPanelControllerFix:FloatingPanelController{
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
      super.viewWillTransition(to: size, with: coordinator)
      DispatchQueue.main.async {
       self.updateLayout()
      }
    }
}

And seems this func is not called in iPad after rotate the ipad

func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? {
    print("not print in ipad , but prints in iphone")
    print("in both ipad and iphone, this prints 2 times when first run")
    return ....
}

layout code in side class FloatingPanelLandscapeLayout: FloatingPanelLayout in iPad, the width is width of device not 200 , but works in iphone

public func prepareLayout(surfaceView: UIView, in view: UIView) -> [NSLayoutConstraint] {
        
        return [
            surfaceView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: 0.0),
            surfaceView.widthAnchor.constraint(equalToConstant: 200)
        ]
    }

FlashTang avatar May 22 '20 14:05 FlashTang

Since in iPad verticalSizeClass is the same , so willTransition(to newCollection not call for temporary fix : call this when create fpc , and in viewWillTransition(to size

func fixLandscapeLayout(coordinator:UIViewControllerTransitionCoordinator?){
        if let cd = coordinator {
           self.fpc.willTransition(to: UITraitCollection(verticalSizeClass: AppDelegate.isLandscape ? .compact : .regular), with: cd)
        }
    }
self.fpc.addPanel(toParent: self)
        self.fpc.hide()
        
        self.fixLandscapeLayout(coordinator: self.transitionCoordinator)
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        
        if UIDevice.current.userInterfaceIdiom == .pad {
            self.fixLandscapeLayout(coordinator: coordinator)
        }
        
    }

FlashTang avatar May 25 '20 07:05 FlashTang

@SCENEE Is this still an issue with version 2.x? This would be quiet a deal breaker for us...

reni99 avatar Nov 30 '20 08:11 reni99

No. I believe this was resolved in v2. Because v2 has floatingPanel(_: FloatingPanelController, layoutFor size: CGSize) delegate method and also since v2 a layout can be updated directly to assign it to FloatingPanelController.layout.

scenee avatar Nov 30 '20 12:11 scenee

Thank you @SCENEE. We are currently using v. 1.7.6 and have the issue that on iPad the child view controller added to the FloatingPanelSurfaceView is not layouted correctly on rotation changes. See image: image The red area is the FloatingPanelSurfaceViews contentView. This should all be covered by the child view controllers view. Do you have any hint on how to fix this @SCENEE? Also the proposed solution here by subclassing FloatingPanelController does not work. Thank you in advance :)

reni99 avatar Nov 30 '20 13:11 reni99

Hmm.. if the red area is FloatingPanelSurfaceView.contentView this looks an issue of the child view controllers 🤔

scenee avatar Dec 01 '20 10:12 scenee