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-25560] : iOS extendSafeArea property not behave properly if tabBarHidden = true or navBarHidden = true #9638

Merged
merged 9 commits into from
Dec 15, 2017
148 changes: 90 additions & 58 deletions iphone/Classes/TiUIWindowProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,9 @@ - (void)setTabBarHidden:(id)value
TiThreadPerformOnMainThread(^{
if (controller != nil) {
[controller setHidesBottomBarWhenPushed:[TiUtils boolValue:value]];
#if IS_XCODE_9
[self processForSafeArea];
#endif
}
},
NO);
Expand Down Expand Up @@ -990,79 +993,108 @@ - (TiViewProxy *)safeAreaView

- (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;

UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
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;
}
}
edgeInsets = [self tabGroupEdgeInsetsForSafeAreaInset:safeAreaInset];
} 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;
edgeInsets = [self navigationGroupEdgeInsetsForSafeAreaInset:safeAreaInset];
} 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;
edgeInsets = [self defaultEdgeInsetsForSafeAreaInset:safeAreaInset];
}

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];
CGFloat oldTop = [[safeAreaProxy valueForKey:@"top"] floatValue];
CGFloat oldLeft = [[safeAreaProxy valueForKey:@"left"] floatValue];
CGFloat oldRight = [[safeAreaProxy valueForKey:@"right"] floatValue];
CGFloat oldBottom = [[safeAreaProxy valueForKey:@"bottom"] floatValue];

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

- (UIEdgeInsets)tabGroupEdgeInsetsForSafeAreaInset:(UIEdgeInsets)safeAreaInset
{
UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
TiWindowProxy *windowProxy = nil;
if ([self.tabGroup isKindOfClass:[TiWindowProxy class]]) {
windowProxy = (TiWindowProxy *)self.tabGroup;
}
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (!UIInterfaceOrientationIsPortrait(orientation)) {
if (windowProxy.isMasterWindow) {
edgeInsets.left = safeAreaInset.left;
} else if (windowProxy.isDetailWindow) {
edgeInsets.right = safeAreaInset.right;
} else {
edgeInsets.left = safeAreaInset.left;
edgeInsets.right = safeAreaInset.right;
}
}
if ([TiUtils boolValue:[self valueForUndefinedKey:@"navBarHidden"] def:NO]) {
edgeInsets.top = safeAreaInset.top;
}
if ([TiUtils boolValue:[self valueForUndefinedKey:@"tabBarHidden"] def:NO]) {
edgeInsets.bottom = safeAreaInset.bottom;
}
return edgeInsets;
}

- (UIEdgeInsets)navigationGroupEdgeInsetsForSafeAreaInset:(UIEdgeInsets)safeAreaInset
{
UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
TiWindowProxy *windowProxy = nil;
if ([self.tab isKindOfClass:[TiWindowProxy class]]) {
windowProxy = (TiWindowProxy *)self.tab;
}
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (!UIInterfaceOrientationIsPortrait(orientation)) {
if (windowProxy.isMasterWindow) {
edgeInsets.left = safeAreaInset.left;
} else if (windowProxy.isDetailWindow) {
edgeInsets.right = safeAreaInset.right;
} else {
edgeInsets.left = safeAreaInset.left;
edgeInsets.right = safeAreaInset.right;
}
}
if ([TiUtils boolValue:[self valueForUndefinedKey:@"navBarHidden"] def:NO]) {
edgeInsets.top = safeAreaInset.top;
}
edgeInsets.bottom = safeAreaInset.bottom;
return edgeInsets;
}

- (UIEdgeInsets)defaultEdgeInsetsForSafeAreaInset:(UIEdgeInsets)safeAreaInset
{
UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
if (self.isMasterWindow) {
edgeInsets.left = safeAreaInset.left;
} else if (self.isDetailWindow) {
edgeInsets.right = safeAreaInset.right;
} else {
edgeInsets.left = safeAreaInset.left;
edgeInsets.right = safeAreaInset.right;
}
edgeInsets.bottom = safeAreaInset.bottom;
edgeInsets.top = safeAreaInset.top;
return edgeInsets;
}
#endif

Expand Down
6 changes: 6 additions & 0 deletions iphone/Classes/TiWindowProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,9 @@ - (void)showNavBar:(NSArray *)args
id properties = (args != nil && [args count] > 0) ? [args objectAtIndex:0] : nil;
BOOL animated = [TiUtils boolValue:@"animated" properties:properties def:YES];
[[controller navigationController] setNavigationBarHidden:NO animated:animated];
#if IS_XCODE_9
[self processForSafeArea];
#endif
}
}

Expand All @@ -629,6 +632,9 @@ - (void)hideNavBar:(NSArray *)args
id properties = (args != nil && [args count] > 0) ? [args objectAtIndex:0] : nil;
BOOL animated = [TiUtils boolValue:@"animated" properties:properties def:YES];
[[controller navigationController] setNavigationBarHidden:YES animated:animated];
#if IS_XCODE_9
[self processForSafeArea];
#endif
//TODO: need to fix height
}
}
Expand Down
38 changes: 38 additions & 0 deletions tests/Resources/ti.ui.window.addontest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Appcelerator Titanium Mobile
* Copyright (c) 2011-Present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
/* eslint-env mocha */
/* global Ti */
/* eslint no-unused-expressions: "off" */
'use strict';
var should = require('./utilities/assertions'),
utilities = require('./utilities/utilities');

describe('Titanium.UI.Window', function () {
it.ios('#ExtendSafeArea (safeAreaView exists)', function (finish) {
// TO DO: Add more unit tests related to top, bottom, left, right margins of win.safeAreaView.
var win = Ti.UI.createWindow({
backgroundColor: 'gray',
extendSafeArea: false
});

win.addEventListener('focus', function () {
try {
var error;
should(win.safeAreaView).be.a.Object;
} catch (err) {
error = err;
}

setTimeout(function () {
win.close();
finish(error);
}, 1000);
});

win.open();
});
});