wix / react-native-navigation

A complete native navigation solution for React Native
https://wix.github.io/react-native-navigation/
MIT License
13.03k stars 2.67k forks source link

Style the BottomTabs/TabBar at runtime #466

Closed brunolemos closed 5 years ago

brunolemos commented 7 years ago

Is there a way to change the tabbar style after the app being initialized?

Steps to Reproduce / Code Snippets / Screenshots


Environment

brunolemos commented 7 years ago

Unfortunately this prevents this lib from being used on apps that support themes, for example.

guyca commented 7 years ago

Hey @brunolemos Our guideline is that if something is possible and used in native - we should support it too. Dynamic styles should be supported, I hope it will make it for one of the next milestones.

Just my personal take of this: I previously worked on an native app that supported themes and style customization. We decided to implement this feature in two phases:

  1. Save the updated theme configuration in store (SharedPreferences, since it was native Android) and use some kind of StyleResolver whenever we needed to supply style params when the app was created. Each time the theme changed - we notified the user that the app needs to be restarted in order for the changed to take place.

  2. Support dynamic styles. User changes theme -> see result immediately.

At the end, Phase one worked fine, no users complained and we never had any incentive to work on the dynamic themes feature. A year or so after that the company closed down and the app faded 😄

I suggest, you try out what worked for us and notify the user the app needs to be restarted. then restart it programmatically by calling your startSingleScreenApp or startTabBasedApp

brunolemos commented 7 years ago

@guyca Thanks for your suggestion, but I'm already on phase 2.

I care a lot about User Experience, so a smooth theme transition like twitter does is really cool. After opening this issue I started using another tab lib (the one from exponent) that I could do it.

I just wish this one also supported it, because I would prefer to use it instead.

MrLoh commented 7 years ago

@brunolemos I have the same problem. I'm currently using react-navigation for the stack router and a custom bottom tab implementation. But the performance is unacceptable so I was thinking of switching to this library but I need styling support. How are you solving the problem today. What stack router are you using?

brunolemos commented 7 years ago

react-navigation too :( But I'll probably get back to wix on the next project

MrLoh commented 7 years ago

@brunolemos Are you also having problems with react-navigation performance?

brunolemos commented 7 years ago

I managed to fix most of the performance issues (it was caused by unnecessary rerenders, tweaks on my redux selectors made huge diff) but yes I'm not satisfied with a javascript navigator performance and ux

MrLoh commented 7 years ago

As a workaround you can simply hide the bottomtababr on every screen and build your own tab bar in js that is rendered on each screen. To handle the tab bar press actions use the deep link API. I just build this and it works quite fine.

danielang commented 6 years ago

Currently I have the same problem. I am writing a newsreader app with theme switching capabilities. I've used react-navigation, but the performance is very poor...

I've found a solution to change the TabBar-theme at runtime for android: BottomTabsLayout.java:223

@Override
public void updateScreenStyle(String screenInstanceId, Bundle styleParams) {
    for (int i = 0; i < bottomTabs.getItemsCount(); i++) {
        screenStacks[i].updateScreenStyle(screenInstanceId, styleParams);
    }

    // buttomtabs style update here
    StyleParams parsedStyleParams = new StyleParamsParser(styleParams).parse();
    bottomTabs.setStyleFromScreen(parsedStyleParams);
}

This code will update the bottom tabbar for each individual screen when you call:

this.props.navigator.setStyle({
    tabBarButtonColor: '#ff0000',
    tabBarBackgroundColor: '#0d0d0d'
});

I'll try to find a way for iOS... but I am very new to Objective C and I find the Syntax needs getting used to 😄

danielang commented 6 years ago

Ok... here is the iOS version for basic layout customization at runtime: RCCViewController.m:471

UITabBar *tabBar = viewController.tabBarController.tabBar;

NSNumber *tabBarHidden = self.navigatorStyle[@"tabBarHidden"];
BOOL tabBarHiddenBool = tabBarHidden ? [tabBarHidden boolValue] : NO;
if (tabBarHiddenBool) {
  // UITabBar *tabBar = viewController.tabBarController.tabBar;
  tabBar.transform = CGAffineTransformMakeTranslation(0, tabBar.frame.size.height);
}

// Custom Implementation begins here
NSString *tabBarButtonColor = self.navigatorStyle[@"tabBarButtonColor"];
if (tabBarButtonColor)
{
  UIColor *color = tabBarButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarButtonColor] : nil;
  tabBar.tintColor = color;
}
NSString *tabBarSelectedButtonColor = self.navigatorStyle[@"tabBarSelectedButtonColor"];
if (tabBarSelectedButtonColor)
{
  UIColor *color = tabBarSelectedButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarSelectedButtonColor] : nil;
  tabBar.tintColor = color;
}
NSString *tabBarBackgroundColor = self.navigatorStyle[@"tabBarBackgroundColor"];
if (tabBarBackgroundColor)
{
  UIColor *color = tabBarBackgroundColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarBackgroundColor] : nil;
  tabBar.barTintColor = color;
}
// Custom Implementation ends here

@brunolemos & @guyca should I continue the development? For better support there must be more changes of cause 😉

brunolemos commented 6 years ago

@danielang looks great! what more changes do you mean?

danielang commented 6 years ago

This is just a 'hack' that works... Perhaps wix will do a good integration by themselves.

In version 1.1.260 the implementation has already been changed for iOS - RCCViewController.m:703

// Custom Implementation
UITabBar *tabBar = self.tabBarController.tabBar;

NSString *tabBarButtonColor = self.navigatorStyle[@"tabBarButtonColor"];
if (tabBarButtonColor)
{
  UIColor *color = tabBarButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarButtonColor] : nil;
  tabBar.tintColor = color;
}
NSString *tabBarSelectedButtonColor = self.navigatorStyle[@"tabBarSelectedButtonColor"];
if (tabBarSelectedButtonColor)
{
  UIColor *color = tabBarSelectedButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarSelectedButtonColor] : nil;
  tabBar.tintColor = color;
}
NSString *tabBarBackgroundColor = self.navigatorStyle[@"tabBarBackgroundColor"];
if (tabBarBackgroundColor)
{
  UIColor *color = tabBarBackgroundColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarBackgroundColor] : nil;
  tabBar.barTintColor = color;
}

Also it would be great if every parameter could be changed.

danielang commented 6 years ago

If #2224 will be accepted/merged, this issue should be solved.

arryanggaputra commented 6 years ago

@danielang cool

danielang commented 6 years ago

The PR is now merged into the master branch of this repository. So the functionality is now available for Android and iOS. Exampe:

this.props.navigator.setStyle({
        tabBarButtonColor: '#0d0d0d',
        tabBarSelectedButtonColor: '#ff6c33',
        tabBarBackgroundColor: '#ffffff',
        navigationBarColor: '#ffffff',
});

@guyca Thank you for your support! I think we can close this issue now.

CC: @brunolemos @arryanggaputra

brunolemos commented 6 years ago

@danielang that's awesome, thank you :)

arryanggaputra commented 6 years ago

@danielang I just modify the RCCViewController.m to able to do this, what do you think?

screen shot 2017-12-01 at 2 45 03 pm

witalobenicio commented 6 years ago

@danielang which version of 'react-native-navigation' is this supported?

danielang commented 6 years ago

Hey @witalobenicio currently only my fork here: https://github.com/danielang/react-native-navigation . We had some problems with overriden custom navbars after the merge. Original message from @guyca:

I had to revert the pr as it caused some issues on both platforms. BottomTabs styles weren't applied correctly and on screens where we exepected the tabbs to be hidden they were visible. It also broke navBarCustomView, apparently going back to screen with navBarCustomView - the custom view is missing :confused:

In the same time my Mac was broken; so I couldn't check my improvements in iOS, until yesterday...

It seems that my improvements work & I hope they will be remerged soon 😄 @guyca

witalobenicio commented 6 years ago

@danielanf There is a way I can use your repo via npm while @guyca does not merge it?

danielang commented 6 years ago

@witalobenicio of cause: npm i --save https://github.com/danielang/react-native-navigation

witalobenicio commented 6 years ago

@danielang I tried to get your fork the way you write there...but I'm still not able to change tabBar colors.

danielang commented 6 years ago

@witalobenicio pls show me some code 🙂 I've PMed you on Facebook.

reinvanimschoot commented 6 years ago

@danielang I tried your fork and it works fine on iOS but now Android does not start up anymore. I started from a fresh project, installing your fork and its exactly the same thing. Is there any way around this? This is really extremely inconvenient since I need this feature for theming purposes.

jason-shen commented 6 years ago

@arryanggaputra would you able to show the code for that mod you done cheers

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe the issue is still relevant, please test on the latest version and report back. Thank you for your contributions.

stale[bot] commented 6 years ago

The issue has been closed for inactivity.

guyca commented 5 years ago

fixed in 2.0.2594