You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -104,6 +104,7 @@ Before upgrading, resolve any deprecation warnings from `0.9.11` — `HFlowLegac
104
104
- `WidgetSize.minimumSize` and `maximumSize` are now derived from the frame tables instead of being listed separately, so a new measurement widens the range without a second edit. Maintained by hand they drifted out of step twice, and every measurement added during this release left them further behind: `.extraLargePortrait` reported a 338x450 maximum while the measured frames reached 378x611.33, and `.accessoryInline` reported 257x26 while iPad measures 374x36. Corrected values are `.small` minimum 141x141 to 133x133, `.accessoryCircular` minimum 68x68 to 53x53, `.accessoryRectangular` minimum 153x68 to 133x53.5, `.accessoryInline` maximum 257x26 to 374x36, and `.extraLargePortrait` 338x450 to a 305.5x470 minimum and a 378x611.33 maximum. The corrected visionOS frames then moved two more on their own, which is the derivation doing its job: `.accessoryRectangular` maximum is now the 208x79 Vision Pro frame rather than the 191x81.5 Apple Watch one, and `.extraLarge` minimum the 634.5x305.5 iPad canvas rather than the visionOS frame. The rule is unchanged: the smallest and largest frame across every device that supports the size, using the iPad design canvas rather than the Home Screen frame, choosing by area where no candidate wins on both axes.
105
105
-`AutoRotatingView` sometimes animated a 90 degree orientation change as a 270 degree rotation the other way. The angle is now accumulated, always taking the shortest path.
106
106
- `AutoRotatingView` gave its content a frame with a safe area that jumped the moment a rotation began. SwiftUI stops expanding a view into the safe area once a `rotationEffect` is applied to it, so animating content that uses `ignoresSafeArea()` would cause it to jump to a new position before animating. The content is now laid out in the full space including the safe area, with the container's own safe area, read outside the rotation where it is still correct, re-created inside it. Content that ignores the safe area is edge to edge in every orientation and content that respects it stays clear of the real unsafe regions, which lie along the content's left and right edges when it is rotated a quarter turn. Through a rotation the size of that safe area and the insets around it move directly from the values they rest at before it to the ones they rest at after it, so a half turn leaves them alone entirely and nothing grows and shrinks on the way. Content sits centred in the safe area, and moving it directly rather than turning it leaves its centre short of where the rotation puts it part way through, so the frame is positioned to make up the difference and the content stays on the axis of rotation for the whole turn. All of it follows the animated angle frame by frame rather than each value being interpolated on its own.
107
+
- `AutoRotatingView` content that ignores the safe area flickered through a rotation, and on a device whose screen is an odd number of points wide, such as a 393 point iPhone, it stopped expanding altogether once the rotation settled and left that part of the screen unpainted. SwiftUI does not treat a frame as touching the edges of its container when the frame's own edges fall between whole points, and content cannot expand into a safe area it is not touching. A rotation puts the frame between points on almost every frame of the animation, which is the flicker, and on an odd width it lands between points at rest as well, which is the part that stayed. The frame's edges are now rounded onto whole points. Rounding on its own makes the frame sit still for several frames and then jump a whole point, because the correction it rounds moves only a fraction of a point per frame, so the remainder is put back as an offset while the content is turning. That offset is not part of layout and fades to nothing as the rotation settles, leaving a resting frame exactly on whole points.
107
108
- The example app's `ContentView` did not build on visionOS.
Text("A fullscreen AutoRotatingView gives its content the whole screen in every orientation. The gradient ignores the safe area so it goes edge to edge, the dashed frame and the labels respect it, and the content turns around the centre of the screen without stepping or drifting.")
96
+
Text("A fullscreen AutoRotatingView gives its content the whole screen in every orientation. The background ignores the safe area so it goes edge to edge, the dashed frame and the labels respect it, and the content turns around the centre of the screen without stepping or drifting.")
96
97
97
98
Text("Rotate the device to an orientation the app does not support to see the view rotate on its own. Changing the allowed orientations rotates it without moving the device, which is the only way to see this in a simulator.")
/// Where to put the centre of the frame so the safe area keeps the centre the rotation gives it, rounded so the frame's edges land on whole points.
76
+
/// Where to put the centre of the frame so the safe area keeps the centre the rotation gives it.
76
77
///
77
-
/// The centre of the safe area moves directly along with its insets, so part way through a turn it is not where turning it would have put it. Moving the frame by the difference puts it back. Rounding then moves it by up to half a point, which is far less than the drift it is correcting.
78
-
varposition:CGPoint{
78
+
/// The centre of the safe area moves directly along with its insets, so part way through a turn it is not where turning it would have put it. This puts it back.
79
+
privatevarexactPosition:CGPoint{
79
80
/// Where the centre of the safe area lands once the rotation is applied, and where it needs to land.
/// Positioning is by centre, so the centre is moved to wherever puts the frame's edges on whole points.
88
+
}
89
+
90
+
/// ``exactPosition``, moved to wherever puts the frame's edges on whole points. Positioning is by centre, so it is the edges that are rounded rather than the centre itself.
/// The half point or less that rounding moved the frame by, put back after layout while the content is turning.
100
+
///
101
+
/// Rounding the position on its own makes the frame sit still for several frames and then jump a whole point, because the correction it rounds only moves a fraction of a point per frame. Offsetting by the remainder smooths that out.
102
+
///
103
+
/// It only exists to smooth motion, so it fades out as the rotation settles and is nothing at all at a quarter turn. A resting frame is left exactly where rounding put it, on whole points, which is where content that ignores the safe area needs it to be able to expand.
104
+
varpositionOffset:CGSize{
105
+
/// How far past the nearest quarter turn the content is, from 0 at rest to 1 once it is two degrees past.
0 commit comments