简体   繁体   中英

Android sensor orientation problems with edge-to-edge insets

In edge-to-edge mode it is often useful to check various insets (status bar, navigation bar, etc) in order to make adjustments to your UI. Unfortunately when a device is in a sensor supported orientation (say sensorLandscape) - the Activity is not recreated when changed from landscape to reverse landscape. Reverse landscape insets are different than landscape insets. This leads to problems of knowing when to readjust your UI around the updated insets.

Handling the orientation changes yourself also does not trigger onConfigurationChanged callback between landscape and reverse landscape transitions. An OrientationListener only tells you the current orientation degrees which would be hard to 'time' exactly against when the phone does the reverse flip. Most phones do not support reverse portrait and some do not support reverse landscape, so it'd also be difficult to know if the phone actually did flip to reverse landscape (polling the requestedOrientation in an OrientationListener only shows it as sensorLandscape and not what it currently is).

Is there any way to get landscape -> reverse landscape Activity recreations or at least detect or be notified when the Activity is flipped to a reverse orientation?

The only working solution I've found requires polling and is a little complicated;

1) Determine the natural orientation of the device. This is done by comparing the current orientation (which will only be landscape or portrait) against the displays current rotation.

  • Portrait with 0 or 180 rotation is naturally portrait
  • Portrait with 90 or 270 rotation is naturally landscape
  • Landscape with 0 or 180 rotation is naturally landscape
  • Landscape with 90 or 270 rotation is naturally portrait

Naturally portrait means that when the display is portrait the rotation is 0 and likewise naturally landscape means that when the display is landscape the rotation is 0.

NOTE : While a corner case - this needs to be done while not rotating as the current orientation and display rotation are briefly out of sync. If you poll it a few times to debounce it you can ensure you didn't catch it mid-rotation.

2) Now that you know the natural orientation you can poll the current display rotation any time and determine your current true orientation.

For a naturally portrait display:

  • 0 is portrait
  • 90 is landscape
  • 180 is reverse portrait
  • 270 is reverse landscape

For a naturally landscape display:

  • 0 is landscape
  • 90 is reverse portrait
  • 180 is reverse landscape
  • 270 is portrait

Finally I set up a shared coroutine channelFlow that polls the display rotation with a 250ms delay in a loop while subscribed and spits out the current orientation + deltas as they are discovered. So now I can subscribe for updates and know when orientation changed to any orientation OR reverse orientation and can re-adjust as necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM