scenee / FloatingPanel

A clean and easy-to-use floating panel UI component for iOS
MIT License
5.61k stars 510 forks source link

Floating Panel continues dragging for magic numbers #574

Open iOSDias opened 2 years ago

iOSDias commented 2 years ago

Description

I have bottom FloatingPanelPosition, tip FloatingPanelState and anchors return [ .tip: FloatingPanelAdaptiveLayoutAnchor(absoluteOffset: 0, contentLayout: targetGuide, referenceGuide: .safeArea) ], for prevent dragging up and down from current position I add code as in example func floatingPanelDidMove(_ vc: FloatingPanelController) { if vc.isAttracting == false { let loc = vc.surfaceLocation print(loc) let minY = vc.surfaceLocation(for: .full).y print(minY) let maxY = vc.surfaceLocation(for: .tip).y print(maxY) vc.surfaceLocation = CGPoint(x: loc.x, y: min(max(loc.y, minY), maxY)) print(vc.surfaceLocation) } } For one of my cases, when I have two objects in dynamic height tableView with multiline label, floating panel continues dragging When I am printing a values of surfaceLocations I have a periodic decimals (0.0, 532.3333384195963) // let loc = vc.surfaceLocation 944.0 // let minY = vc.surfaceLocation(for: .full).y 548.6666666666666 // let maxY = vc.surfaceLocation(for: .tip).y (0.0, 548.6666666666666) // vc.surfaceLocation = CGPoint(x: loc.x, y: min(max(loc.y, minY), maxY))

private lazy var surfaceAppearance: SurfaceAppearance = {
    let appearance = SurfaceAppearance()
    appearance.backgroundColor = Colors.backgroundView
    appearance.cornerRadius = 14.0
    return appearance
}()

private lazy var floatingPanel: FloatingPanelController = {
    let controller = FloatingPanelController()
    controller.backdropView.dismissalTapGestureRecognizer.isEnabled = false
    controller.contentInsetAdjustmentBehavior = .never
    controller.contentMode = .static
    controller.isRemovalInteractionEnabled = false
    controller.surfaceView.appearance = surfaceAppearance
    controller.surfaceView.grabberHandle.isHidden = true
    return controller
}()

func setupFloatingPanel() {
    floatingPanel.delegate = self
    floatingPanel.set(contentViewController: restaurantsViewController)
    floatingPanel.track(scrollView: restaurantsViewController.contentView.tableView)
    floatingPanel.addPanel(toParent: self)
}

I display 1 panel Library version: last 2.5.2 Installation method: CocoaPods testing device iOS version: 15.6 Xcode version: Version 13.2.1 (13C100)

Screenshot of this floating panel case IMG_1397

iOSDias commented 2 years ago

for this values also not working (0.0, 577.6666615804037) vc.surfaceLocation 944.0 minY 519.3333333333334 maxY (0.0, 519.3333333333334)

iOSDias commented 2 years ago

I tried to change lineSpacing and font of dynamic label let attributedString = NSMutableAttributedString(string: cellModel.address) let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 4 attributedString.addAttributes([ .paragraphStyle: paragraphStyle, .font: UIFont.medium(24), .foregroundColor: Colors.basicWhite ], range: NSRange(location: 0, length: attributedString.length)) addressLabel.attributedText = attributedString It gets for FloatingPabel surfaceLocation this values: (0.0, 392.99999491373705) 944.0 478.6666666666667 (0.0, 478.6666666666667) and it works perfectly without dragging, but I can not use this properties because of design In my case label does not have linespacing and another font private lazy var addressLabel: UILabel = { let label = UILabel() label.font = .regular(14) label.numberOfLines = 0 label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) label.setContentHuggingPriority(.defaultLow, for: .vertical) label.textColor = Colors.basicWhite return label }()

Also I notice 

floatingPanel.surfaceView.frame.height = 304.6666666666667 it works floatingPanel.surfaceView.frame.height = 259.3333333333333 - fails

scenee commented 2 years ago

It looks FloatingPanelAdaptiveLayoutAnchor's issue, but I don't understand the reason why this line is not working.

 vc.surfaceLocation = CGPoint(x: loc.x, y: min(max(loc.y, minY), maxY))

I guess a possible reason why the content size of the panel changes while dragging by Auto Layout configurations.

If you would give me a simple sample code or project to reproduce this issue, I will be able to dive deep into it.

(I'm also pleased to be format your description and comment by fenced code blocks)

iOSDias commented 2 years ago

@scenee when floatingPanel.surfaceView.frame.height has periodic decimals like 304.666666666666 || 304.(6) or 259.3333333333333 259.(3) it breaks but for complete decimals like 304.6666666666667 works perfectly, I solve it by making my tableView has only integer value of height, but I think it is a bug which must be solved

scenee commented 2 years ago

I think so too. The root cause seems to be the floating point error handling. But I have no idea why vc.surfaceLocation becomes (0, 532.333338419596) though the surface location(vc.surfaceLocation) is set to (0.0, 548.6666666666666).

(0.0, 532.3333384195963) // let loc = vc.surfaceLocation
944.0 // let minY = vc.surfaceLocation(for: .full).y
548.6666666666666 // let maxY = vc.surfaceLocation(for: .tip).y
(0.0, 548.6666666666666) // vc.surfaceLocation = CGPoint(x: loc.x, y: min(max(loc.y, minY), maxY))
scenee commented 2 years ago

I tried to reproduce this issue, but I've not done that. I pushed iss-574 branch. I've used "Show Adaptive Panel (Custom Layout Guide)" in Samples app. Its surface height is 620.6666666666666 on iPhone 13 Pro(iOS 15.6.1), but it works well(I also tested some simulators.)

iOSDias commented 2 years ago

@scenee Ok, I try to write demo project soon with this bug example

scenee commented 1 year ago

These commits might fix this issue. They gonna be released in v2.8.0.