Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-26246] Android: Added Ti.UI.Window "extendSafeArea", "safeAreaPadding", and inset/notch support #10383

Merged
merged 9 commits into from Oct 25, 2018

Conversation

jquick-axway
Copy link
Contributor

@jquick-axway jquick-axway commented Oct 18, 2018

JIRA:

Summary:

  • TIMOB-26246 Added handling of Android P insets/notches/cutouts.
    • Added Ti.UI.Window property "extendSafeArea" to render content beneath insets.
    • Unlike iOS, this property is false by default on Android. This is because insets can be of any size and on side, making it more problematic.
  • TIMOB-26427 Added new Ti.UI.Window property "safeAreaPadding".
    • Applies to Android 4.4 and newer OS versions when "extendSafeArea" is true.
    • Needed to detect size of insets for translucent StatusBar/NavBar and Android P notches.
    • Padding will be all zeros if "extendSafeArea" is false.
  • TIMOB-26459 Added Android 4.4 constants for Ti.UI.Window property "windowFlags":
    • Ti.UI.Android.FLAG_TRANSLUCENT_NAVIGATION
    • Ti.UI.Android.FLAG_TRANSLUCENT_STATUS
  • TIMOB-25810 Fixed bug where ActionBar height won't resize upon orientation changes.
  • TIMOB-26460 Fixed bug where Toolbar height set to Ti.UI.SIZE won't resize upon orientation change.
  • TIMOB-26442 Fixed bug where Toolbar with "extendBackground" to true is too tall if both status bar and nav bar are translucent.
  • Modified DrawerLayout XML to not fit its "center" view under top insets:
    • The XML setting was wrong. It was intended to place left/right drawers under top inset, but it was only doing it main center view instead.
    • Better solution is to allow left/center/right layouts to overlap insets (like gmail app) and use a Toolbar with "extendBackground" true to position itself beneath top inset.

Test Prerequisite:
You must obtain an Android P device with a notch before doing the below tests.
If the device doesn't have a notch, then you can simulate it as follows:

  1. Go to the Android P device's "Settings" screen.
  2. Tap on "Systems" from the list.
  3. Tap on "Advanced".
  4. Tap on "Developer Options".
  5. Tap on "Simulate a display with cutouts" to display a dialog.
  6. Select "Double display cutout". (Will simulate notch on top and bottom.)

Toolbar Test:

  1. Build and run test code attached to TIMOB-26442 on Android 4.4 or higher.
  2. Verify that there is no extra padding below the Toolbar. (See TIMOB-26442 screenshots.)
  3. Rotate the device to landscape.
  4. Verify that the Toolbar height and font size shrinks. (This tests TIMOB-26460.)
  5. Continue holding the device in landscape and back out of the app.
  6. Relaunch the app in landscape.
  7. Rotate the device to portrait.
  8. Verify that the Toolbar height and font size increase in portrait.

ActionBar Test:

  1. Create a default ClassicApp test project.
  2. Hold an Android device in portrait form.
  3. Build and run the app on that Android device.
  4. Rotate the device to landscape.
  5. Verify that the titlebar height and font size shrinks. (This tests [TIMOB-25810].)
  6. Continue holding the device in landscape and back out of the app.
  7. Relaunch the app in landscape.
  8. Rotate the device to portrait.
  9. Verify that the titlebar height and font size increases in size.

Translucent StatusBar and NavBar Test:

  1. Build and run the code attached to TIMOB-26459 on Android 4.4 or higher.
  2. Verify that screen looks like what's shown in that ticket. App window with green border should fill the screen and top status bar and bottom nav bar should be overlaid on top.

Note that Android 4.4 will show an opaque navigation bar when displayed landscape. This is a limitation on Google's end.


Extend Safe-Area Window Test:

  1. Build and run ExtendSafeAreaContainerTest.js attached to TIMOB-26427.
  2. Hold the device portrait.
  3. Verify that a green rectangle with a blue border is between all insets/notches. (See: image)
  4. Rotate device to landscape where navigation bar is on the right side.
  5. Verify that the green rectangle is still between the insets. (See: image)
  6. Rotate device to the other landscape orientation without rotating to portrait. (Do a barrel roll!)
  7. Verify that the green rectangle is still between the insets. (See: image)

Extend Safe-Area ScrollView Test:

  1. Build and run ExtendSafeAreaScrollViewTest.js attached to TIMOB-26427.
  2. Hold the device in portrait.
  3. Scroll to the very top, if not already.
  4. Verify that top-most view is not overlapped by the top status bar as seen here.
  5. Scroll to the very bottom.
  6. Very bottom-most view is not overlapped by the bottom navigation bar as seen here.
  7. Rotate to landscape where navigation bar is on the right side of the screen.
  8. Scroll to the very top while landscape.
  9. Verify that all rows are not overlapped by insets on the top/left/right sides as seen here.
  10. Rotate device to the other landscape orientation without going to portrait. (Do a barrel roll!)
  11. Scroll to the very top.
  12. Verify that all rows are not overlapped by insets on the top/left/right sides as seen here.
  13. Scroll to the very bottom while landscape.
  14. Verify that "Row 20" is shown without overlap at the bottom. Only top-most rows are overlapped by the top status bar as seen here.

Extend Safe-Area TabGroup Test:

  1. Build and run ExtendSafeAreaTabsTest.js attached to TIMOB-26427.
  2. Hold the device in portrait form and tap "Tab 1".
  3. Verify that a green rectangle is displayed between the top tab bar and the bottom translucent navigation bar without overlap... and a red background fills the translucent areas as seen here.
  4. Tap "Tab 2" while portrait.
  5. Verify Tab 2 display a green rectangle between the top tab bar and bottom navigation bar too... and an orange background fills the rest of the translucent area as shown here.
  6. Rotate device to landscape where navigation bar is on the right side.
  7. Tap "Tab 1" while landscape.
  8. Verify green rectangle is between all insets and the top tab bar as seen here.
  9. Rotate device to the other landscape without going to portrait. (Do a barrel roll!)
  10. Verify green rectangle is between all insets and the top tab bar as seen here.
  11. Tap "Tab 2" and verify green rectangle is between all insets and top tab bar.

Extend Safe-Area DrawerLayout Test:

  1. Build and run ExtendSafeAreaDrawerTest.js attached to TIMOB-26427.
  2. Hold the device portrait.
  3. Verify that the top toolbar's title is below the status bar, but the toolbar's red background extends under the top status bar as seen here.
  4. Tap the hamburger button in the top-left corner to open the drawer.
  5. Verify that the drawer's top blue toolbar's title is below the status bar, but the blue toolbar's background is extended under the status bar as seen here.
  6. Rotate device to landscape.
  7. Verify title is still below top status bar and shifted to the right if there is an Android P notch on the left side as seen here.
  8. Press the back button to close the drawer.
  9. Verify that main window's top red toolbar title is still below the status bar and shifted to the right if there is an Android P notch on the left side of the screen as seen here.

…Padding", and inset/notch support

- [TIMOB-26246] Added handling of Android P inset/notch/cutout.
  * Added Ti.UI.Window property "extendSafeArea" to render content beneath insets.
- [TIMOB-26427] Added Ti.UI.Window property "safeAreaPadding".
  * Applies to Android 4.4 and newer OS versions when "extendSafeArea" is true.
  * Needed to detect size of insets for translucent StatusBar/NavBar and Android P notches.
- [TIMOB-26459] Added constants for Ti.UI.Window property "windowFlags".
  * Ti.UI.Android.FLAG_TRANSLUCENT_NAVIGATION
  * Ti.UI.Android.FLAG_TRANSLUCENT_STATUS
- [TIMOB-25810] Fixed bug where ActionBar height won't resize upon orientation changes.
- [TIMOB-26460] Fixed bug where Toolbar height set to Ti.UI.SIZE won't resize upon orientation change.
- [TIMOB-26442] Fixed bug where Toolbar with "extendBackground" to true is too tall if both status bar and nav bar are translucent.
- Modified DrawerLayout XML to not fit its "center" view under top insets.
  * The XML setting was wrong. It was intended to place left/right drawers under top inset, but it wasn't doing that.
  * Better solution is to allow left/center/right layouts to overlap insets and use a Toolbar with "extendBackground" true to position itself beneath inset.
@@ -39,6 +41,9 @@
import android.util.Pair;
import android.view.Display;
import android.view.View;
import android.view.ViewParent;
import android.view.Window;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import.

}

/**
* To be called by the owner when the activity's overriden onConfigurationChanged() method has been called.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in "overridden".

/**
* To be called by the owner when the activity's overriden onConfigurationChanged() method has been called.
* Updates the ActionBar's height and font size base on the given configuration.
* @param newConfig The udpated configuration applied to the activity.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in "updated".

toolbarStyleHandler = new TiToolbarStyleHandler((Toolbar) view);
}
} catch (Exception ex) {
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe logging a warning or a debug level message here ? To make it easier for troubleshooting at some point if a problem comes from failing this try block. ( I am not a fan of empty catch blocks )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Done.


// Calculate the safe-area, which is the region between the insets.
// Note: We must dynamically add ActionBar height here (if enabled) since its
// visbility and height changes can only be detected via an onLayoutChange() event.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in "visibility".

}

/**
* To be called by the owner when the activity/view's overriden onConfigurationChanged() method has been called.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in "overridden".

/**
* To be called by the owner when the activity/view's overriden onConfigurationChanged() method has been called.
* Updates the toolbar's height and font size base on the given configuration.
* @param newConfig The udpated configuration applied to the activity/view.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in "updated".

* Updates the toolbar's height and font size base on the given configuration.
* @param newConfig The udpated configuration applied to the activity/view.
*/
public void onConfigurationChanged(Configuration newConfig)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The newConfig parameter seems to not be used in the method. It is used when the method is called from:
https://github.com/appcelerator/titanium_mobile/pull/10383/files#diff-9ea98253bfde40055a91a9df7a25cb33R52
and
https://github.com/appcelerator/titanium_mobile/pull/10383/files#diff-9ce4241f5edf3cb3a0918ec183f9f59bR83
Maybe the former one may allow us to remove the parameter from the definition in TiActionBarStyleHandler too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made it this way to make it clear that this method should be called when the Activity/View object's onConfigurationChanged() method has been called. That's also partly why I decided to name the class a "handler" because it's like an event handler.

Also, I was originally thinking about optimizing this by only updating the ActionBar/Toolbar when the given configuration object indicated that the orientation changed. But onConfigurationChanged() is actually rarely called. So, I didn't think it was worth it.

Are you getting a compiler warning? I may need to add a @SuppressWarnings("unused").

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just saw it was unused. I am OK to leave it as is, matching the declaration makes sense for it being more clear what is happening.

Copy link
Contributor

@ypbnv ypbnv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome PR! Besides a few minor things I have commented on it looks good!

@jquick-axway
Copy link
Contributor Author

Thanks for the review @ypbnv . :)

I suspect the following may not work with your refactored TabGroup changes. This is where I'm fetching the container view in the TabGroup which hosts the fragments. I need this to add additional padding to the returned by our new safeAreaPadding property. I can't use the fragment's current position in the ViewPager because unselected tabs are actually placed offscreen. I need to use the container's rectangle instead. I suspect I'll need a follow-up PR if that's the case.
https://github.com/appcelerator/titanium_mobile/pull/10383/files#diff-0b6ca69ce950b64a6498bbeba8edf89dR475

…tend their background

- Fixed issue where if multiple toolbars had "extendBackground" true, it would only apply to 1st one.
  * Had to override default behavior to prevent insets from being consumed.
- Fixed regression where toolbar "extendBackground" true would no longer work unless window "extendSafeArea" was also true.
  * Caused by root Titanium view calling setFitsSystemWindows(true) on startup, instead of default false setting.
@jquick-axway
Copy link
Contributor Author

jquick-axway commented Oct 23, 2018

Updated PR:

  • Fixed regression caused by this PR where toolbar "extendBackground" set to true would be ignored if window's "extendSafeArea" was also not set to true.
    • Caused by root Titanium view now calling setFitsSystemWindows(true) by default now.
    • The TiToolbar code was modified to call root view's setFitsSystemWindows(false) now, making it backward compatible.
  • Fixed issue where if multiple toolbars set "extendBackground" to true, it would only be applied to the 1st toolbar.
    • Had to modify Google's default behavior to prevent insets from being consumed by toolbars in this case. Allows insets to be propagated to other view.
    • This is needed by apps which use a DrawerLayout and want to use a toolbar for the main window and in the drawer panel.
  • Modified Toolbar to support "extendBackground" on Android 4.4.
    • Was only supported on Android 5.0 and above.
    • Needed since this PR supports translucent status bars on 4.4.

type: Boolean
default: true
since: 6.3.0
default: `true` on iOS. `false` on Android.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is causing the docgen validation to error out as it's a string (which fails the parsing of Window.yml, throwing all the other parse errors)
It's super easy to allow the validation script to allow us to set {android: false, ios: true} here, but I have no idea how this then plays into the generation of the various templates (html, jdsuck, typescript etc.). @jawa9000 do you know how I can check the output?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I'll give it a go.

@longton95 longton95 self-requested a review October 25, 2018 13:59
Copy link
Contributor

@longton95 longton95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FR Passed

Verified using the test cases above, extendSafeArea and safeAreaPadding work as expected with the notch supports

ENV

Pixel 2 XL (9.0)
Emulator (9.0, 6.0, 4.4.2)
Appc NPM: 4.2.13
Appc CLI: 7.0.7-9
Ti CLI: 5.1.1
Node: 8.12.0
NPM: 6.4.1

@build
Copy link
Contributor

build commented Oct 25, 2018

Messages
📖

💾 Here's the generated SDK zipfile.

Generated by 🚫 dangerJS

@longton95 longton95 merged commit f45bb2c into tidev:master Oct 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants