Skip to content

Rotation on iOS does not look right #16322

Closed
flutter-team-archive/engine
#40730

Description

@DaveShuckerow

Internal: b/77275812

From an internal user trying out Flutter on the external flow for iOS:

I'm trying out flutter for the first time to gauge the quality of the 'native look and feel' to see if it's a platform I should invest my time in learning.

Using the example hellowworld app from https://flutter.io/get-started/test-drive/#terminal

See video. I've slowed it down to show more clearly.

The layout flashes, the text stretches.

Activity

  1. tvolkert commented on Apr 6, 2018

    @tvolkert
    Contributor

    bff

  2. added
    engineflutter/engine related. See also e: labels.
    a: fidelityMatching the OEM platforms better
    and removed
    a: first hourThe first hour of using Flutter
    on Apr 6, 2018
  3. tvolkert commented on Apr 6, 2018

    @tvolkert
    Contributor

    Cross-posting from #13300 and consolidating on this issue:

    Rotate iOS device running flutter from portrait to landscape and back. Today we use the default behaviour, which results in the view repainting contents for the new orientation before the rotation starts, then transforming the view (rotation, scale) to the new orientation.

    Alternatives include Safari's rotation behaviour or allowing some degree of developer control.

  4. tvolkert commented on Apr 6, 2018

    @tvolkert
    Contributor
  5. added this to the milestone on Apr 6, 2018
  6. tvolkert commented on Apr 6, 2018

    @tvolkert
    Contributor

    the stretching of the aspect ratio is what looks worst here. We could potentially also cross-fade from a fixed rotated background so that we don't incur the black edges.

  7. tvolkert commented on Apr 6, 2018

    @tvolkert
    Contributor

    /cc @cbracken as the creator of #13300

  8. tvolkert commented on Oct 23, 2018

    @tvolkert
    Contributor

    Per @cbracken in #6995

    Looks like we need to expose better support for viewWillTransitionToSize:withTransitionCoordinator: in FlutterViewController.

  9. adriancmurray commented on Sep 10, 2019

    @adriancmurray

    @tvolkert

    Alternatives include ... allowing some degree of developer control.

    I would love some control here. Specifically it would be nice to allow for the device to rotate without utilizing SystemChrome.setPreferredOrientations but not forcing the main widget to repaint/size. I could see instead passing a callback to the WidgetsApp with an orientation change. From a developer's perspective this callback could be passed to something like a ChangeNotifierProvider and allow us to have very granule control of this process. Similar to how the Camera app functions on iOS where the main view doesn't actually switch between states but instead the icons rotate to their appropriate view. This skewing is really really annoying from a UX point of view.

  10. tvolkert commented on Sep 10, 2019

    @tvolkert
    Contributor
  11. 73 remaining items

  12. b3nni97 commented on Apr 5, 2023

    @b3nni97

    @hellohuanlin Couldn't we take a screenshot at the start of the rotation where height and width have already changed and then fade it in?
    That's what native iOS does anyway, so the jump in the middle is no longer really noticeable.

  13. hellohuanlin commented on Apr 5, 2023

    @hellohuanlin
    Contributor

    @b3nni97

    Couldn't we take a screenshot at the start of the rotation where height and width have already changed and then fade it in?

    When you take a screenshot where height and width already changed, the screenshot itself has the max distortion. So the result won't look good.

    That's what native iOS does anyway, so the jump in the middle is no longer really noticeable.

    Nope. The native iOS actually does size interpolation.

  14. b3nni97 commented on Apr 5, 2023

    @b3nni97

    @hellohuanlin
    Ok maybe I don't understand something correctly but,

    in a native iOS app, it doesn't look to me like the size is interpolated.

    IMG_1427 (1)

    This screenshot was taken at the beginning of a screen rotation. You can see 2 "screenshots" one of the state before the rotation, and one of the state after the rotation, with the exception that the end state didn't just change width / height, but the height remains (so that the complete height can be filled during the fade in).
    During the animation, the width of the clipped part becomes smaller and smaller, but the lower part is clipped.

    IMG_1428 (1)
    This screenshot was taken shortly before the rotation is finished. Here you can see that the end state is now almost completely visible.

    I hope you understand what I mean.

    Here is the full video of the rotation

    RPReplay_Final1680721048.MP4
  15. hellohuanlin commented on Apr 5, 2023

    @hellohuanlin
    Contributor

    @b3nni97 I don't think apple is taking a screenshot (otherwise there would be distortion of the screenshot when the window's aspect ratio changes).

    It's impossible to take a screenshot of what the screen will look like after the rotation is complete, at the time before the rotation even starts (if that's what you want) - the screenshot shows exactly what the current screen is when the screenshot is taken.

    Your particular example is interesting - it changes the entire layout to a split view, in which case I'm not sure what apple is doing under the hood. Without layout change, apple's behavior is size interpolation, as shown below:

    swiftui.mp4
  16. b3nni97 commented on Apr 5, 2023

    @b3nni97

    @hellohuanlin
    Ok then this problem is more complex than thought.

    It's impossible to take a screenshot of what the screen will look like after the rotation is complete, at the time before the rotation even starts (if that's what you want) - the screenshot shows exactly what the current screen is when the screenshot is taken.

    Hmm, I know too little about the engine, I thought it would be possible to do a complete rebuild with the new width and height, and then display this as a "screenshot".

  17. hellohuanlin commented on Apr 5, 2023

    @hellohuanlin
    Contributor

    Hmm, I know too little about the engine, I thought it would be possible to do a complete rebuild with the new width and height, and then display this as a "screenshot".

    The screenshot is not flutter-related tho. It's just UIKit API to take a screenshot of the current screen. So once the end state is displayed, you can't "blend it in", as it's already on the screen.

  18. tvolkert commented on Apr 6, 2023

    @tvolkert
    Contributor

    I think @b3nni97 may be suggesting we could build a new tree with the new width & height and paint it to a buffer rather than the screen.

  19. hellohuanlin commented on Apr 6, 2023

    @hellohuanlin
    Contributor

    @tvolkert Gotcha. That likely requires big changes in both framework and engine. However, a new idea came to me that fading in end-state snapshot should have similar result to fading out begin-state snapshot. The latter is much easier to do, so I did a quick experiment (and I call this "approach 5"):

    Approach 5

    Fade out begin-state snapshot during the rotation. Here's the result:

    100.fade.mp4

    This doesn't look at good as the original approach 2 when I tried it on device, because:

    1. it still has max distortion in the beginning, just not fully opaque compared with the existing behavior.
    2. the overlapping of the 2 states looks bad

    There's another approach that combines approach 2 and 5, and I call this approach 6.

    Approach 6:

    Show the begin-state snapshot for 40% of rotation, then fade out for 20% of rotation, then show end-state real screen for 40% of rotation (code here, number adjustable, I just find 40%-20%-40% result in the smoothest transition). Here's the result:

    20.fade.mp4

    Approach 6 is smoother than approach 2. I think it has the best result among approaches 1, 2, 5 and 6.

    However, I still think approach 4 is better than any snapshot tricks, since it works for dynamic contents (videos & animations).

  20. tvolkert commented on Apr 6, 2023

    @tvolkert
    Contributor

    Yeah I think approach 4 still looks the best.

  21. github-actions commented on May 2, 2023

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  22. locked as resolved and limited conversation to collaborators on May 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: fidelityMatching the OEM platforms bettera: layoutSystemChrome and Framework's Layout Issuescustomer: crowdAffects or could affect many people, though not necessarily a specific customer.customer: googleVarious Google teamscustomer: splashbulbengineflutter/engine related. See also e: labels.found in release: 3.3Found to occur in 3.3found in release: 3.7Found to occur in 3.7frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-iosiOS applications specificallyr: fixedIssue is closed as already fixed in a newer version

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions