Skip to content

Commit

Permalink
Fix header config when navigating back gets cancelled. (#171)
Browse files Browse the repository at this point in the history
This change fixes the problem when header would update to the previous screen configuration as a result of starting swipe back gesture but never restore to the original one in case swipe back gets cancelled (e.g. user didn't swipe far enough). The problem was that as a result of swipe back we'd apply header config changes but after cancel there was no trigger to reset header to the previous state.
  • Loading branch information
kmagiera committed Oct 3, 2019
1 parent a229904 commit 7620c54
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 34 deletions.
8 changes: 8 additions & 0 deletions ios/RNSScreen.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#import "RNSScreen.h"
#import "RNSScreenContainer.h"
#import "RNSScreenStackHeaderConfig.h"

#import <React/RCTUIManager.h>
#import <React/RCTShadowView.h>
Expand Down Expand Up @@ -127,6 +128,13 @@ - (UIView *)reactSuperview
return _reactSuperview;
}

- (void)addSubview:(UIView *)view
{
if (![view isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
[super addSubview:view];
}
}

- (void)notifyFinishTransitioning
{
[_controller notifyFinishTransitioning];
Expand Down
4 changes: 3 additions & 1 deletion ios/RNSScreenStack.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ - (instancetype)initWithManager:(RNSScreenStackManager*)manager
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
UIView *view = viewController.view;
RNSScreenStackHeaderConfig *config = nil;
for (UIView *subview in view.reactSubviews) {
if ([subview isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
[((RNSScreenStackHeaderConfig*) subview) willShowViewController:viewController];
config = (RNSScreenStackHeaderConfig*) subview;
break;
}
}
[RNSScreenStackHeaderConfig willShowViewController:viewController withConfig:config];
}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
Expand Down
2 changes: 1 addition & 1 deletion ios/RNSScreenStackHeaderConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@property (nonatomic) BOOL translucent;
@property (nonatomic) BOOL gestureEnabled;

- (void)willShowViewController:(UIViewController *)vc;
+ (void)willShowViewController:(UIViewController *)vc withConfig:(RNSScreenStackHeaderConfig*)config;

@end

Expand Down
70 changes: 38 additions & 32 deletions ios/RNSScreenStackHeaderConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,32 +75,32 @@ - (UIViewController*)screen
return nil;
}

- (void)setAnimatedConfig:(UIViewController *)vc
+ (void)setAnimatedConfig:(UIViewController *)vc withConfig:(RNSScreenStackHeaderConfig *)config
{
UINavigationBar *navbar = ((UINavigationController *)vc.parentViewController).navigationBar;
BOOL hideShadow = _hideShadow;
[navbar setTintColor:_color];
if (_backgroundColor && CGColorGetAlpha(_backgroundColor.CGColor) == 0.) {
BOOL hideShadow = config.hideShadow;
[navbar setTintColor:config.color];
if (config.backgroundColor && CGColorGetAlpha(config.backgroundColor.CGColor) == 0.) {
[navbar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[navbar setBarTintColor:[UIColor clearColor]];
hideShadow = YES;
} else {
[navbar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[navbar setBarTintColor:_backgroundColor];
[navbar setBarTintColor:config.backgroundColor];
}
[navbar setTranslucent:_translucent];
[navbar setTranslucent:config.translucent];
[navbar setValue:@(hideShadow ? YES : NO) forKey:@"hidesShadow"];

if (_titleFontFamily || _titleFontSize || _titleColor) {
if (config.titleFontFamily || config.titleFontSize || config.titleColor) {
NSMutableDictionary *attrs = [NSMutableDictionary new];

if (_titleColor) {
attrs[NSForegroundColorAttributeName] = _titleColor;
if (config.titleColor) {
attrs[NSForegroundColorAttributeName] = config.titleColor;
}

CGFloat size = _titleFontSize ? [_titleFontSize floatValue] : 17;
if (_titleFontFamily) {
attrs[NSFontAttributeName] = [UIFont fontWithName:_titleFontFamily size:size];
CGFloat size = config.titleFontSize ? [config.titleFontSize floatValue] : 17;
if (config.titleFontFamily) {
attrs[NSFontAttributeName] = [UIFont fontWithName:config.titleFontFamily size:size];
} else {
attrs[NSFontAttributeName] = [UIFont boldSystemFontOfSize:size];
}
Expand All @@ -109,7 +109,7 @@ - (void)setAnimatedConfig:(UIViewController *)vc

}

- (void)setTitleAttibutes:(NSDictionary *)attrs forButton:(UIBarButtonItem *)button
+ (void)setTitleAttibutes:(NSDictionary *)attrs forButton:(UIBarButtonItem *)button
{
[button setTitleTextAttributes:attrs forState:UIControlStateNormal];
[button setTitleTextAttributes:attrs forState:UIControlStateHighlighted];
Expand All @@ -120,7 +120,7 @@ - (void)setTitleAttibutes:(NSDictionary *)attrs forButton:(UIBarButtonItem *)but
}
}

- (void)willShowViewController:(UIViewController *)vc
+ (void)willShowViewController:(UIViewController *)vc withConfig:(RNSScreenStackHeaderConfig *)config
{
UINavigationItem *navitem = vc.navigationItem;
UINavigationController *navctr = (UINavigationController *)vc.parentViewController;
Expand All @@ -129,26 +129,30 @@ - (void)willShowViewController:(UIViewController *)vc
UINavigationItem *prevItem = currentIndex > 0 ? [navctr.viewControllers objectAtIndex:currentIndex - 1].navigationItem : nil;

BOOL wasHidden = navctr.navigationBarHidden;

[navctr setNavigationBarHidden:_hide animated:YES];
navctr.interactivePopGestureRecognizer.enabled = _gestureEnabled;
if (_hide) {
BOOL shouldHide = config == nil || config.hide;

[navctr setNavigationBarHidden:shouldHide animated:YES];
navctr.interactivePopGestureRecognizer.enabled = config.gestureEnabled;
#ifdef __IPHONE_13_0
vc.modalInPresentation = !config.gestureEnabled;
#endif
if (shouldHide) {
return;
}

navitem.title = _title;
navitem.hidesBackButton = _hideBackButton;
if (_backTitle != nil) {
navitem.title = config.title;
navitem.hidesBackButton = config.hideBackButton;
if (config.backTitle != nil) {
prevItem.backBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:_backTitle
initWithTitle:config.backTitle
style:UIBarButtonItemStylePlain
target:nil
action:nil];
if (_backTitleFontFamily || _backTitleFontSize) {
if (config.backTitleFontFamily || config.backTitleFontSize) {
NSMutableDictionary *attrs = [NSMutableDictionary new];
CGFloat size = _backTitleFontSize ? [_backTitleFontSize floatValue] : 17;
if (_backTitleFontFamily) {
attrs[NSFontAttributeName] = [UIFont fontWithName:_backTitleFontFamily size:size];
CGFloat size = config.backTitleFontSize ? [config.backTitleFontSize floatValue] : 17;
if (config.backTitleFontFamily) {
attrs[NSFontAttributeName] = [UIFont fontWithName:config.backTitleFontFamily size:size];
} else {
attrs[NSFontAttributeName] = [UIFont boldSystemFontOfSize:size];
}
Expand All @@ -159,13 +163,13 @@ - (void)willShowViewController:(UIViewController *)vc
}

if (@available(iOS 11.0, *)) {
if (self.largeTitle) {
if (config.largeTitle) {
navctr.navigationBar.prefersLargeTitles = YES;
}
navitem.largeTitleDisplayMode = self.largeTitle ? UINavigationItemLargeTitleDisplayModeAlways : UINavigationItemLargeTitleDisplayModeNever;
navitem.largeTitleDisplayMode = config.largeTitle ? UINavigationItemLargeTitleDisplayModeAlways : UINavigationItemLargeTitleDisplayModeNever;
}

for (RNSScreenStackHeaderSubview *subview in _reactSubviews) {
for (RNSScreenStackHeaderSubview *subview in config.reactSubviews) {
switch (subview.type) {
case RNSScreenStackHeaderSubviewTypeLeft: {
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithCustomView:subview];
Expand All @@ -191,20 +195,22 @@ - (void)willShowViewController:(UIViewController *)vc

} completion:nil];
[vc.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
[self setAnimatedConfig:vc];
[self setAnimatedConfig:vc withConfig:config];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
if ([context isCancelled]) {
UIViewController* fromVC = [context viewControllerForKey:UITransitionContextFromViewControllerKey];
RNSScreenStackHeaderConfig* config = nil;
for (UIView *subview in fromVC.view.reactSubviews) {
if ([subview isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
[((RNSScreenStackHeaderConfig*) subview) setAnimatedConfig:fromVC];
config = (RNSScreenStackHeaderConfig*) subview;
break;
}
}
[self setAnimatedConfig:fromVC withConfig:config];
}
}];
} else {
[self setAnimatedConfig:vc];
[self setAnimatedConfig:vc withConfig:config];
}
}

Expand Down

0 comments on commit 7620c54

Please sign in to comment.