Skip to content

Commit

Permalink
Merge pull request #9485 from vijaysingh-axway/TIMOB-25301_6_3_X
Browse files Browse the repository at this point in the history
[TIMOB-25301] (6_3_X):iPhone X Need to be able to control the Insets / Layout Margins
  • Loading branch information
ewieberappc committed Oct 13, 2017
2 parents cafa601 + 0578792 commit 4402139
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 17 deletions.
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 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 (including then status-bar, iPhone X home-indicator & iPhone X notch).
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-are for backward compatibility. In Titanium SDK 7.0.0
and later, this property will be `false` by default to automatically adjust the layout. This will be a breaking
change for windows without a navigation-bar, as the status-bar is part of the safe-area, so subviews that are positioned
relatively to the status-bar do not need to include the height of the status-bar (20px) in the margins anymore.
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
9 changes: 8 additions & 1 deletion iphone/Classes/TiUITabProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,11 @@ -(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 @@ -371,6 +375,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 @@ -29,6 +29,10 @@
-(void)updateNavBar;
-(void)boot:(BOOL)timeout args:(id)args;

#if IS_XCODE_9
@property (nonatomic, assign) TiViewProxy *safeAreaViewProxy;
@property (nonatomic) BOOL shouldExtendSafeArea;
#endif
@end

#endif
103 changes: 99 additions & 4 deletions iphone/Classes/TiUIWindowProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,11 @@ -(NSString*)apiName

-(void)dealloc
{
RELEASE_TO_NIL(barImageView);
[super dealloc];
#if IS_XCODE_9
self.safeAreaViewProxy = nil;
#endif
RELEASE_TO_NIL(barImageView);
[super dealloc];
}

-(void)boot:(BOOL)timeout args:args
Expand Down Expand Up @@ -256,8 +259,14 @@ -(BOOL)_handleClose:(id)args

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

- (void)systemLayoutFittingSizeDidChangeForChildContentContainer:(id <UIContentContainer>)container
Expand Down Expand Up @@ -1010,6 +1019,92 @@ -(void)cleanupWindowDecorations
[barImageView removeFromSuperview];
}
}

#if IS_XCODE_9

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

- (void)processForSafeArea
{
// 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 @@ -210,6 +210,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
13 changes: 12 additions & 1 deletion iphone/Classes/TiUIiOSSplitWindow.m
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,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 @@ -268,7 +274,12 @@ -(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
5 changes: 4 additions & 1 deletion iphone/Classes/TiViewProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ 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;
pthread_rwlock_t childrenLock;
Expand Down
108 changes: 99 additions & 9 deletions iphone/Classes/TiViewProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#import <QuartzCore/QuartzCore.h>
#import <libkern/OSAtomic.h>
#import <pthread.h>
#if IS_XCODE_9
#import "TiUIViewProxy.h"
#import "TiUIWindowProxy.h"
#endif


#define IGNORE_IF_NOT_OPENED if (!windowOpened||[self viewAttached]==NO) return;
Expand Down Expand Up @@ -169,15 +173,32 @@ -(BOOL) belongsToContext:(id<TiEvaluator>) context

-(void)add:(id)arg
{
// 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];
}
return;
}
#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) {
#if IS_XCODE_9
if (windowProxy.safeAreaViewProxy) {
[windowProxy.safeAreaViewProxy add:a];
} else {
#endif
[self add:a];
#if IS_XCODE_9
}
#endif
}
return;
}

int position = -1;
TiViewProxy *childView = nil;
Expand All @@ -188,6 +209,12 @@ -(void)add:(id)arg
if (nativeObjSel == nil) 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 +304,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 +327,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);


Expand Down Expand Up @@ -351,6 +398,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 @@ -1502,8 +1559,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

0 comments on commit 4402139

Please sign in to comment.