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-25301]:iPhone X: Need to be able to control the Insets / Layout Margins #9475

Merged
merged 29 commits into from
Nov 14, 2017
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
312ee2a
[TIMOB-25301]:iPhone X: Need to be able to control the Insets / Layou…
vijaysingh-axway Sep 23, 2017
0080d45
[TIMOB-25301]:iPhone X Need to be able to control the Insets / Layout…
vijaysingh-axway Sep 25, 2017
5a12013
Update Window.yml
hansemannn Sep 25, 2017
b34604c
[TIMOB-25301]:Indentation fix
vijaysingh-axway Sep 25, 2017
3b5c1a5
Merge branch 'TIMOB-25301' of https://github.com/vijaysingh-axway/tit…
vijaysingh-axway Sep 25, 2017
7f48efa
[TIMOB-25301] : iPhone X Need to be able to control the Insets / Layo…
vijaysingh-axway Sep 29, 2017
25709d8
[TIMOB-25301] : iPhone X Need to be able to control the Insets / Layo…
vijaysingh-axway Sep 29, 2017
00c0262
[TIMOB-25301] : Update layout only when it needed.
vijaysingh-axway Oct 2, 2017
378c5c1
[TIMOB-25301]: iPhone X Need to be able to control the Insets / Layou…
vijaysingh-axway Oct 4, 2017
5d17368
[TIMOB-25301]: window property passed to safeAreaView
vijaysingh-axway Oct 5, 2017
8aa4c49
[TIMOB-25301]: Safe area layout calculated early
vijaysingh-axway Oct 6, 2017
73159dc
[TIMOB-25301]:Indentation fixed
vijaysingh-axway Oct 6, 2017
adeaeaa
Merge branch 'master' into TIMOB-25301
vijaysingh-axway Oct 6, 2017
e14f1a2
[TIMOB-25301] : early calculation of safe area for tab group’s window
vijaysingh-axway Oct 10, 2017
967bdaf
[TIMOB-25301]: Added safeAreaViewProxy after creating it
vijaysingh-axway Oct 11, 2017
7789988
[TIMOB-25301] : Support for split window
vijaysingh-axway Oct 11, 2017
1d9f24e
Merge branch 'master' into TIMOB-25301
hansemannn Oct 11, 2017
ecf5b94
Rephrase safe-area docs
hansemannn Oct 12, 2017
e087ac7
Update Window.yml
hansemannn Oct 12, 2017
34f9b7c
Merge branch 'master' into TIMOB-25301
ewieberappc Oct 31, 2017
7651eca
Merge branch 'master' into TIMOB-25301
mukherjee2 Nov 3, 2017
cbc8623
Merge branch 'master' into TIMOB-25301
ewieberappc Nov 6, 2017
179f75e
Merge branch 'master' into TIMOB-25301
vijaysingh-axway Nov 8, 2017
d6113d4
Merge branch 'master' into TIMOB-25301
vijaysingh-axway Nov 9, 2017
c5b9022
[TIMOB-25301] : Window.yml doc updated
vijaysingh-axway Nov 9, 2017
de5871c
Merge branch 'master' into TIMOB-25301
mukherjee2 Nov 10, 2017
7db933d
Update Window.yml
hansemannn Nov 10, 2017
74eed9b
Merge branch 'master' into TIMOB-25301
hansemannn Nov 10, 2017
6cd1e94
Merge branch 'master' into TIMOB-25301
mukherjee2 Nov 11, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions apidoc/Titanium/UI/Window.yml
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,28 @@ properties:
since: 3.1.3
osver: {ios: {min: "7.0"}}

- name: extendSafeArea
summary: |
Specifies whether the content (subviews) of the window will render inside the safe-area or not.
Only used in iOS 11.0 and later.
description: |
If the value is `true`, the content (subviews) of the window will not respect the safe-area, meaning that the content
will fill the whole screen available for rendering. If the value is `false`, the content of the
window will be rendered inside the safe-area.

Read more about the safe-area layout-guide in the [Human Interface Guidelines](https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/).

Note: The default value is `true`, so content will extend the safe-area for backward compatibility.
Please note that status-bar, which have height (20pt), is outside safe-area. So any view added on window with
this property 'true', will start rendering below to status-bar. In other words, subviews that are positioned
relatively to the status-bar do not need to include the height of the status-bar (20pt) in the margins anymore.
Copy link
Contributor

Choose a reason for hiding this comment

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

The above description has grammar issues. How about we rewrite it to the following?...


description:
If set true (the default), then the content of the window will be extended to fill the whole screen and under the system's UI elements (such as the top status-bar) and physical obstructions (such as the iPhone X rounded corners and top sensor housing). In this case, it is the app developer's responsibility to position views so that they're unobstructed.

If set false, then the window's content will be laid out within the safe-area and its child views will be unobstructed. For example, you will not need to position a view below the top status-bar.

Read more about the safe-area layout-guide in the Human Interface Guidelines.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks Josh! We should consider having a grammar review for all docs changes due to an international team 🙂.

Copy link
Contributor

Choose a reason for hiding this comment

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

Happy to help! :)
And my grammar isn't perfect either. I just made a couple edits to my text above just now.

platforms: [iphone, ipad]
type: Boolean
default: true
since: 6.3.0
availability: creation
osver: {ios: {min: "11.0"}}

- name: fullscreen
summary: Boolean value indicating if the window is fullscreen.
description: |
Expand Down
7 changes: 7 additions & 0 deletions iphone/Classes/TiUITabProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,10 @@ - (void)openWindow:(NSArray *)args
TiWindowProxy *window = [args objectAtIndex:0];
ENSURE_TYPE(window, TiWindowProxy);

#if IS_XCODE_9
[window processForSafeArea];
#endif

if (window == rootWindow) {
[rootWindow windowWillOpen];
[rootWindow windowDidOpen];
Expand Down Expand Up @@ -364,6 +368,9 @@ - (void)handleWillShowViewController:(UIViewController *)viewController animated
}
}
TiWindowProxy *theWindow = (TiWindowProxy *)[(TiViewController *)viewController proxy];
#if IS_XCODE_9
[theWindow processForSafeArea];
#endif
if (theWindow == rootWindow) {
//This is probably too late for the root view controller.
//Figure out how to call open before this callback
Expand Down
4 changes: 4 additions & 0 deletions iphone/Classes/TiUIWindowProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
- (void)updateNavBar;
- (void)boot:(BOOL)timeout args:(id)args;

#if IS_XCODE_9
@property (nonatomic, assign) TiViewProxy *safeAreaViewProxy;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add one tmpty line for readability. Also ensure to format everything with our clang-format

@property (nonatomic) BOOL shouldExtendSafeArea;
#endif
@end

#endif
97 changes: 96 additions & 1 deletion iphone/Classes/TiUIWindowProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ - (NSString *)apiName

- (void)dealloc
{
#if IS_XCODE_9
self.safeAreaViewProxy = nil;
#endif
RELEASE_TO_NIL(barImageView);
[super dealloc];
}
Expand Down Expand Up @@ -246,7 +249,13 @@ - (BOOL)_handleClose:(id)args

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
#if IS_XCODE_9
[self performSelector:@selector(processForSafeArea)
withObject:nil
afterDelay:[[UIApplication sharedApplication] statusBarOrientationAnimationDuration]];
#endif
[super viewWillTransitionToSize:size
withTransitionCoordinator:coordinator];
[self willChangeSize];
}

Expand Down Expand Up @@ -971,6 +980,92 @@ - (void)cleanupWindowDecorations
[barImageView removeFromSuperview];
}
}

#if IS_XCODE_9

- (TiViewProxy *)safeAreaView
{
return self.safeAreaViewProxy;
}

- (void)processForSafeArea
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be compiled out by #if IS_XCODE_9 to decrease the code-size for Xcode < 9.

{
// TO DO : Refactor this method
if (self.shouldExtendSafeArea || ![TiUtils isIOS11OrGreater]) {
return;
}
float left = 0.0;
float right = 0.0;
float top = 0.0;
float bottom = 0.0;
UIViewController<TiControllerContainment> *topContainerController = [[[TiApp app] controller] topContainerController];
UIEdgeInsets safeAreaInset = [[topContainerController hostingView] safeAreaInsets];
if (self.tabGroup) {
TiWindowProxy *windowProxy = nil;
if ([self.tabGroup isKindOfClass:[TiWindowProxy class]]) {
windowProxy = (TiWindowProxy *)self.tabGroup;
}
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (!UIInterfaceOrientationIsPortrait(orientation)) {
if (windowProxy.isMasterWindow) {
left = safeAreaInset.left;
} else if (windowProxy.isDetailWindow) {
right = safeAreaInset.right;
} else {
left = safeAreaInset.left;
right = safeAreaInset.right;
}
}
} else if (self.tab) {
TiWindowProxy *windowProxy = nil;
if ([self.tab isKindOfClass:[TiWindowProxy class]]) {
windowProxy = (TiWindowProxy *)self.tab;
}
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (!UIInterfaceOrientationIsPortrait(orientation)) {
if (windowProxy.isMasterWindow) {
left = safeAreaInset.left;
} else if (windowProxy.isDetailWindow) {
right = safeAreaInset.right;
} else {
left = safeAreaInset.left;
right = safeAreaInset.right;
}
}
bottom = safeAreaInset.bottom;
} else {
if (self.isMasterWindow) {
left = safeAreaInset.left;
} else if (self.isDetailWindow) {
right = safeAreaInset.right;
} else {
left = safeAreaInset.left;
right = safeAreaInset.right;
}
bottom = safeAreaInset.bottom;
top = safeAreaInset.top;
}
TiViewProxy *safeAreaProxy = [self safeAreaViewProxy];
float oldTop = [[safeAreaProxy valueForKey:@"top"] floatValue];
float oldLeft = [[safeAreaProxy valueForKey:@"left"] floatValue];
float oldRight = [[safeAreaProxy valueForKey:@"right"] floatValue];
float oldBottom = [[safeAreaProxy valueForKey:@"bottom"] floatValue];

if (oldTop != top) {
[safeAreaProxy setTop:NUMFLOAT(top)];
}
if (oldBottom != bottom) {
[safeAreaProxy setBottom:NUMFLOAT(bottom)];
}
if (oldLeft != left) {
[safeAreaProxy setLeft:NUMFLOAT(left)];
}
if (oldRight != right) {
[safeAreaProxy setRight:NUMFLOAT(right)];
}
}
#endif

@end

#endif
3 changes: 3 additions & 0 deletions iphone/Classes/TiUIiOSNavWindowProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ - (void)navigationController:(UINavigationController *)navigationController will
}
}
TiWindowProxy *theWindow = (TiWindowProxy *)[(TiViewController *)viewController proxy];
#if IS_XCODE_9
[theWindow processForSafeArea];
#endif
if ((theWindow != rootWindow) && [theWindow opening]) {
[theWindow windowWillOpen];
[theWindow windowDidOpen];
Expand Down
11 changes: 11 additions & 0 deletions iphone/Classes/TiUIiOSSplitWindow.m
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ - (void)setMasterView_:(id)args
}
RELEASE_TO_NIL(masterProxy);
masterProxy = [args retain];

#if IS_XCODE_9
TiWindowProxy *masterWindowProxy = (TiWindowProxy *)masterProxy;
masterWindowProxy.isMasterWindow = YES;
#endif

if (viewsInitialized) {
[self initProxy:masterProxy withWrapper:masterViewWrapper];
}
Expand All @@ -267,6 +273,11 @@ - (void)setDetailView_:(id)args
RELEASE_TO_NIL(detailProxy);
detailProxy = [args retain];

#if IS_XCODE_9
TiWindowProxy *detailWindowProxy = (TiWindowProxy *)detailProxy;
detailWindowProxy.isDetailWindow = YES;
#endif

if (viewsInitialized) {
[self initProxy:detailProxy withWrapper:detailViewWrapper];
}
Expand Down
3 changes: 3 additions & 0 deletions iphone/Classes/TiViewProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ enum {
int vzIndex;
BOOL hidden; //This is the boolean version of ![TiUtils boolValue:visible def:yes]
//And has nothing to do with whether or not it's onscreen or
#if IS_XCODE_9
BOOL safeAreaProxyAdded;
#endif

#pragma mark Parent/Children relationships
TiViewProxy *parent;
Expand Down
95 changes: 94 additions & 1 deletion iphone/Classes/TiViewProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#import <QuartzCore/QuartzCore.h>
#import <libkern/OSAtomic.h>
#import <pthread.h>
#if IS_XCODE_9
#import "TiUIViewProxy.h"
#import "TiUIWindowProxy.h"
#endif

Copy link
Collaborator

Choose a reason for hiding this comment

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

Compile out for Xcode < 9

#define IGNORE_IF_NOT_OPENED \
if (!windowOpened || [self viewAttached] == NO) \
Expand Down Expand Up @@ -167,10 +171,29 @@ - (BOOL)belongsToContext:(id<TiEvaluator>)context

- (void)add:(id)arg
{
#if IS_XCODE_9
TiUIWindowProxy *windowProxy = nil;
if ([self isKindOfClass:[TiUIWindowProxy class]] && [TiUtils isIOS11OrGreater]) {
windowProxy = (TiUIWindowProxy *)self;
if (arg == windowProxy.safeAreaViewProxy) {
// If adding the safeAreaViewProxy, it need to be add on window.
windowProxy = nil;
}
}
#endif

// allow either an array of arrays or an array of single proxy
if ([arg isKindOfClass:[NSArray class]]) {
for (id a in arg) {
[self add:a];
#if IS_XCODE_9
if (windowProxy.safeAreaViewProxy) {
[windowProxy.safeAreaViewProxy add:a];
} else {
#endif
[self add:a];
#if IS_XCODE_9
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where does this bracket belong to? Maybe this is more readable (untested!):

  // allow either an array of arrays or an array of single proxy
  if ([arg isKindOfClass:[NSArray class]]) {
    for (id a in arg) {
#if IS_XCODE_9
      if (windowProxy.safeAreaViewProxy) {
        [windowProxy.safeAreaViewProxy add:a];
	continue;
      }
#endif
      [self add:a];
    }
    return;
  }

}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Compile out for Xcode < 9, change the access of safeAreaViewProxy as well.

#endif
}
return;
}
Expand All @@ -185,6 +208,12 @@ - (void)add:(id)arg
nativeObjSel = NSSelectorFromString([NSString stringWithFormat:@"%@%@", @"native", @"Object"]);
#endif
if ([arg isKindOfClass:[NSDictionary class]]) {
#if IS_XCODE_9
if (windowProxy.safeAreaViewProxy) {
[windowProxy.safeAreaViewProxy add:arg];
return;
}
#endif
childView = [arg objectForKey:@"view"];
position = [TiUtils intValue:[arg objectForKey:@"position"] def:-1];
} else if ([arg isKindOfClass:[TiViewProxy class]]) {
Expand Down Expand Up @@ -277,6 +306,16 @@ - (void)insertAt:(id)args

- (void)replaceAt:(id)args
{
#if IS_XCODE_9
if ([self isKindOfClass:[TiUIWindowProxy class]] && [TiUtils isIOS11OrGreater]) {
TiUIWindowProxy *windowProxy = (TiUIWindowProxy *)self;
if (windowProxy.safeAreaViewProxy) {
[windowProxy.safeAreaViewProxy replaceAt:args];
return;
}
}
#endif

ENSURE_SINGLE_ARG(args, NSDictionary);
NSInteger position = [TiUtils intValue:[args objectForKey:@"position"] def:-1];
NSArray *childrenArray = [self children];
Expand All @@ -290,6 +329,16 @@ - (void)replaceAt:(id)args

- (void)remove:(id)arg
{
#if IS_XCODE_9
if ([self isKindOfClass:[TiUIWindowProxy class]] && [TiUtils isIOS11OrGreater]) {
TiUIWindowProxy *windowProxy = (TiUIWindowProxy *)self;
if (windowProxy.safeAreaViewProxy) {
[windowProxy.safeAreaViewProxy remove:arg];
return;
}
}
#endif

ENSURE_UI_THREAD_1_ARG(arg);

#ifdef HYPERLOOP
Expand Down Expand Up @@ -351,6 +400,16 @@ - (void)remove:(id)arg

- (void)removeAllChildren:(id)arg
{
#if IS_XCODE_9
if ([self isKindOfClass:[TiUIWindowProxy class]] && [TiUtils isIOS11OrGreater]) {
TiUIWindowProxy *windowProxy = (TiUIWindowProxy *)self;
if (windowProxy.safeAreaViewProxy) {
[windowProxy.safeAreaViewProxy removeAllChildren:arg];
return;
}
}
#endif

ENSURE_UI_THREAD_1_ARG(arg);
pthread_rwlock_wrlock(&childrenLock);
NSMutableArray *childrenCopy = [children mutableCopy];
Expand Down Expand Up @@ -1429,7 +1488,41 @@ - (void)_initWithProperties:(NSDictionary *)properties
allowLayoutUpdate = YES;
[self processTempProperties:nil];
allowLayoutUpdate = NO;

#if IS_XCODE_9
[self createSafeAreaViewProxyForWindowProperties:properties];
#endif
}

#if IS_XCODE_9
- (void)createSafeAreaViewProxyForWindowProperties:(NSDictionary *)properties
{
if ([self isKindOfClass:[TiUIWindowProxy class]] && [TiUtils isIOS11OrGreater]) {
/*
Added a transparent safeAreaViewProxy above window for safe area layouts if shouldExtendSafeArea is false. All views added on window will be added on safeAreaViewProxy. Layouts of safeAreaViewProxy is getting modified wherever required.
*/
TiUIWindowProxy *windowProxy = (TiUIWindowProxy *)self;
windowProxy.shouldExtendSafeArea = [TiUtils boolValue:[self valueForUndefinedKey:@"extendSafeArea"] def:YES];
if (!windowProxy.safeAreaViewProxy && !windowProxy.shouldExtendSafeArea) {
NSMutableDictionary *safeAreaProperties = [NSMutableDictionary dictionary];

id layout = [self valueForUndefinedKey:@"layout"];
if (layout) {
safeAreaProperties[@"layout"] = layout;
}

id horizontalWrap = [self valueForUndefinedKey:@"horizontalWrap"];
if (horizontalWrap) {
safeAreaProperties[@"horizontalWrap"] = horizontalWrap;
}

windowProxy.safeAreaViewProxy = [[[TiUIViewProxy alloc] _initWithPageContext:[self pageContext] args:@[ safeAreaProperties ]] autorelease];
[windowProxy processForSafeArea];
[self add:windowProxy.safeAreaViewProxy];
}
}
}
#endif

- (void)dealloc
{
Expand Down
5 changes: 5 additions & 0 deletions iphone/Classes/TiWindowProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@

@property (nonatomic, readwrite, assign) TiViewProxy<TiTab> *tab;
@property (nonatomic, readonly) TiProxy *tabGroup;
#if IS_XCODE_9
@property (nonatomic) BOOL isMasterWindow;
@property (nonatomic) BOOL isDetailWindow;
- (void)processForSafeArea;
#endif

- (UIViewController *)windowHoldingController;

Expand Down