[TIMOB-26348] Android: Galaxy S9 DisplayCaps.platformHeight specifies "safe area" not true display height
GitHub Issue | n/a |
Type | Bug |
Priority | Critical |
Status | Reopened |
Resolution | Unresolved |
Affected Version/s | n/a |
Fix Version/s | n/a |
Components | Android |
Labels | android, engSchedule |
Reporter | Joe Falcone |
Assignee | Joshua Quick |
Created | 2018-08-31T19:30:46.000+0000 |
Updated | 2019-06-08T00:10:32.000+0000 |
Description
The Galaxy S9 (and Note 9) is similar to the iPhone X in that the display curves at each corner.
The display resolution is 2960 but DisplayCaps.platformHeight returns 2768. We think this is delineating the "safe area" for display. It is possible that the native Display.getRealSize might actually return 2960 but we haven't tried this. This is if you "Tap here to fill entire screen" which hides the bottom bar containing the home and back buttons and expands the app to full screen.
If you create a Window with no dimensions specified, you do get a full height 2960 window. But this is where the problems begin - if you then try to place items on this Window, since platformHeight reports 2768, you are going to have problems with layout. The full screen screenshot shows this problem - because we don't know that we are on a 2960 screen, the display elements aren't scaled correctly so there is a gap at the bottom.
If you create the Window with property height 2768, it does center it in the display but now you've got the black bands above and below (the 2768 screenshot does not capture the rounded area - the actual black bands are much bigger) and you might as well be on an S8 since you aren't taking full advantage of the display
The problem, just as it was for the iPhone X, is to detect that we've got a Galaxy S9, Note 9 or similar phone with this feature.
We would like to be able to use the full display but because we can't determine whether one not we've got this situation, the workaround is to just use the platformHeight for the Window height and live with the black bands.
BTW, there is no Galaxy S9 emulator in Genymotion so you'll have to go find someone with a phone and see for yourself.
Test code is trivial - just createWindow with no dimension and then place a label with bottom at platformHeight and you'll see that it is not at the bottom of the window.
Attachments
Quick note: TIMOB-26246 is planned for 7.5.0 to handle the "cut-out" (aka safe-area) on Android, exposing the parity API. This still seems to be an own ticket to be handled.
This is not a bug. Since Titanium built apps do not "target" Android P yet, they'll be put into backward compatibility mode on Android P devices. Because of this, they can't take full advantage of the screen on devices that have a notch and will display this letterbox effect. This is a good thing because it prevents the notch from overlapping your app's content. As [~hknoechel] has mentioned, we plan on targeting Android P in Titanium 7.5.0. By then, your app will be able to take full advantage of the screen and we'll provide access to a new API
Window.extendSafeArea
that'll allow you to optionally control if the window will extend under the notch like iOS. All in due time. We'll get there. :)We're observing this on Android 8 so what you're saying is that there is nothing in Android 8 that allows a workaround for this problem (other than just using platformHeight and living with the black bands) and we have to wait for a combination of Android P and at least SDK 7.5.
If we're talking about the top notch on Android P devices (similar to iPhone X), then you cannot access the full size of the screen unless you "target" Android P (aka: API Level 28). Android P will letterbox the apps that target a lower API Level and Google's Java APIs will return a shorter height. You can target API Level 28 now in your "tiapp.xml", but I don't recommend it since we haven't addressed all of Android P's breaking changes yet... which we plan on doing in Titanium 7.5.0. Although, you can try targeting API Level 28 for testing purposes. We allow you to do so at your own risk.
This is not true. You do not have to target API Level 28 to use the rounded corner areas of the screen (including the status area). We target API Level 26 and, if you tap to allow full screen view, your app gets to use the whole screen, rounded corners and all. This is running Android 8 on a Galaxy S9. There is even a settings area under Display for Full screen apps and our apps built with SDK 7.3 targeting API 26 qualify for this. You guys have to get your hands on an S9 or a Note 9 to see this for yourselves.
BTW this is not a display cutout or notch issue. This is platformHeight property returning a value that is smaller than the screen size which causes banding. I've attached some new screen shots taken by another phone in full screen view and non-full-screen-view modes so you can see the difference.
[Full Screen Apps](https://ibb.co/j56Hxz) [Banded App View](https://ibb.co/knsqHz) [Full Screen View](https://ibb.co/d1mZcz)
And I think you can see that the Banded App View actually clips the ad view and the bottom bar. It's not a good solution.
Okay. Right, I think we are talking about 2 different things. I'm going to remove the Android P label from this ticket, because it has nothing to do with notch handling. Titanium's
DisplayCaps.platformHeight
on Android does not return the height of the screen. It returns the "visible" height of the app window and titlebar relative to the app's orientation (not device orientation). It does not include the height of the top status bar and bottom navigation bar (ie: the system decor) unless they've been set up to be translucent. This is by Google's design. If it were to return the actual screen height, then it would be a problem for split-screen mode apps. https://developer.android.com/reference/android/view/Display.html#getMetrics(android.util.DisplayMetrics) Now, if the behavior you're seeing doesn't match the above description, then you might be running into a bug on the Samsung device. Samsung does make their own fork of the Android OS after-all and bugs on their end have been known to happen. We have a Nexus 6P which has rounded corners (made by Huawei, not Samsung). I don't recall our Nexus 6P having the issues you've mentioned, but we can re-test it later this week. I do suspect this may be a bug on Samsung's end and a work-around would have to be found. Such as a different window setting/theme that doesn't have this issue. Unfortunately, Android is the wild-west of operating systems and not all devices follow the rules so-to-speak.The S9 has a drag up bottom navigation bar (so its not translucent, it's not there at all) when you are in full-screen mode so take that out of the equation. Takes some getting used to if you are accustomed to always having the list, home and back buttons always visible. And then if you turn off the status bar, that goes away as well. So then you have a platformHeight that bears no relationship to the display area which is the entire 2960 screen except you have no way of knowing that it is a 2960 screen. And that's the issue... how do you program for full-screen mode when you don't know how big the full-screen is???
I've already found one bug in 7.5.0 RC so I'm waiting on the GA to do further testing and will evaluate the extendSafeArea features then. Presumably someone has tested this with an S9 which has rounded corners but does NOT have iPhone X-like notches...
I still don't believe that it is consistent to return a value for Ti.Platform.displayCaps.height that is NOT the actual height of the display. Here's the problem. On the S9, on the latest 7.5 RC with Target SDK 28, Platform.displayCaps.height still returns 2768 while the actual display height is 2960. By using a NoTitle theme with *extendSafeArea = false*, I can 1. create a fullscreen=true Window that reports its size as 2960 2. create a fullscreen=false Window that reports its size as 2864 because status bar is visible In both cases, the Window size.height is LARGER than the displayCaps.height which to me is inconsistent. If you view the display as the ultimate container for views, then you should not be able to create a view that is BIGGER than the reported display size. The extendSafeArea prop is irrelevant (I get same results whether it is true or false) as the S9 doesn't have notches, it just has rounded corners. The bottom line is that displayCaps.height is not reporting the correct value for the Galaxy S9. It should report height as 2960, not 2768.
Test program that I used... also will need theme to set NO_TITLE from https://docs.appcelerator.com/platform/latest/#!/guide/Android_Action_Bar
Let me make a suggestion here. Don't use
displayCaps
to layout your UI. The reason is because your UI will be constrained to the bounds of theWindow
. This is your UI container. The device/OS controls whether or not your window completely fills the screen/display and you want to avoid making false assumptions. The window's dimensions correctly resizes/positions itself for all screen decorations such as the status bar, nav bar, copy/paste clipboard bar, insets/notches, etc. It would be best to leverage this. We'll re-test it to see ifdisplayCaps
is shorter than the window height. If so, we'll write it up as a separate ticket since this ticket is causing confusion amongst the team here (which is why it was being ignored). Having a short concise issue description is key to getting quicker results. Also, I should repeat that you should *never* usedisplayCaps
for layout purposes. Personally, the native equivalent on Android isn't that useful either. The only useful thing I've used it for natively on Android is identify if my app is being shown "portrait" while the device is held "landscape" in split-screen mode... and vice-versa.Actually we don't use it for layout but when our Windows on the S9 were being letterboxed, we were wondering what was going on and that's when we discovered that displayCaps was returning a screen height that was shorter than the S9 spec. This was also before 7.5 so we were still on API 26 which may or may not have been part of the problem. FYI 7.5 with 28 and 7.4 with 26 return the same incorrect screen height.
We have one Samsung device with rounded corners, but it never letterboxes the app. Nor does the device give us any insets natively to calculate a safe-area. I don't think all devices follow the rules so-to-speak. Would you mind doing a quick test for me please? Run the below using 7.5.0 on your device and tell me what the results are.
Our new 7.5.0 "safeAreaPadding" will provide the system insets relative to the window. These are the insets reported to us by the OS. Also, I do know that an Android P device with notches will still letterbox an app set up for fullscreen mode... unless you set the translucent flags as shown above. So, even if you hide the top status bar, it'll still letterbox it unless you also set up the top status bar as translucent too, even though it's not there. It's one of those Android quirks/gotchas that you have to watch out for. In 7.5.0, we've modified our internal code to set this translucent flag automatically for you for fullscreen apps as can be seen here... https://github.com/appcelerator/titanium_mobile/pull/10383/files#diff-034a9360d01584987d9c951c0a215f65R544 I'm curious if you're being burned by the same translucent flag issue. I know your device wasn't Android P before, but it could be a similar issue. If you're not willing to upgrade to 7.5.0 yet, then you can set this flag manually as shown below...
On Galaxy S9 with Android 8.0 with SDK 7.5.0.v20181106170019 (S9 does not have notches, but does have rounded corners) [INFO] : ### safeAreaPadding: {"right":0,"top":0,"left":0,"bottom":0} [INFO] : ### windowSize: {"x":0,"width":360,"y":0,"height":740} x 4 = 1440 x 2960 [INFO] : ### displayCaps.height: 2768 These are in fact the settings that we're using on our apps.
This is parenthetical but do you guys realize that the test code above returns {} for window.size on iOS on a postlayout handler! This is not documented. I'm just looking for a way to do platform-independent layout and this causes more heartburn if the properties of window are not symmetrical with respect to Android and iOS.