Skip to content

Conversation

@0x1306a94
Copy link
Contributor

When the panel is already at a boundary position, floating-point precision errors on some devices can cause unexpected offset resets in the position calculation.

By applying floor() to the position calculations for top, left, bottom, and right edges in FloatingPanelLayoutAnchor, we ensure integer values are returned, preventing layout issues caused by floating-point precision errors.

#626

FloatingPanelSample.zip

2026-01-13.09.56.34_compressed.mp4

…ndary positions

When the panel is already at a boundary position, floating-point precision
errors on some devices can cause unexpected offset resets in the position
calculation.

By applying floor() to the position calculations for top, left, bottom, and
right edges in FloatingPanelLayoutAnchor, we ensure integer values are
returned, preventing layout issues caused by floating-point precision errors.
@0x1306a94
Copy link
Contributor Author

0x1306a94 commented Jan 13, 2026

The code implementation plan has been adjusted and fixed, and all local unit tests have passed.

2026-01-13.16.48.33_compressed.mp4

@scenee
Copy link
Owner

scenee commented Jan 15, 2026

Hi, thank you so much for the patch and the sample project! The sample project is incredibly helpful for reproducing the issue. I definitely want to get this fixed.

Regarding the current patch, I have one concern: while using floor() works well for FloatingPanelLayout.position = .bottom, it might not function correctly for other positions like .top or .left. Since this library supports various layouts beyond just the bottom sheet, we need to ensure the fix is universal across all positions.

I noticed you updated the patch to fix the unit tests, but your previous approach to LayoutAdapter.position(for:) was also spot on regarding the floating point error.

Based on your contribution, I’m thinking of refining the fix as follows. What do you think?

@@ -306,7 +306,7 @@ class LayoutAdapter {
     }
 
     func surfaceLocation(for state: FloatingPanelState) -> CGPoint {
-        let pos = position(for: state).rounded(by: surfaceView.fp_displayScale)
+        let pos = position(for: state)
         switch layout.position {
         case .top, .bottom:
             return CGPoint(x: 0.0, y: pos)
@@ -316,6 +316,10 @@ class LayoutAdapter {
     }
 
     func position(for state: FloatingPanelState) -> CGFloat {
+        return _position(for: state).rounded(by: surfaceView.fp_displayScale)
+    }
+
+    private func _position(for state: FloatingPanelState) -> CGFloat {
         let bounds = vc.view.bounds
         let anchor = layout.anchors[state] ?? self.hiddenAnchor

@0x1306a94
Copy link
Contributor Author

@scenee

Because my projects all pop up from the bottom, I haven't noticed other directions. It would be great if you could provide a better solution. You can simply close this PR.

I will update it as soon as you fix it.

Thank you so much for developing this library.

@0x1306a94 0x1306a94 closed this Jan 15, 2026
@scenee
Copy link
Owner

scenee commented Jan 15, 2026

Thank you for your understanding and for the quick reply!

Please don't feel like you need to close it just yet — your contribution has been invaluable. Thanks to your sample project and your initial insight into the floating-point error, I now have a very clear path to the fix.

I will take it from here and apply a universal fix based on your findings. I’ll make sure to credit your contribution in the commit and release note.

Thank you again for your support and for using the library!

scenee added a commit that referenced this pull request Jan 15, 2026
When the panel is already at a boundary position, floating-point
precision errors on some devices (like iPhone 17 Pro Max) can cause
unexpected offset resets in the position calculation.

This commit addresses the layout issue where fractional values caused
incorrect position evaluation. Based on the initial fix and sample
project provided by @0x1306a94.

Co-authored-by: 0x1306a94 <onyxes_accent_0a@icloud.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants