mirror of
https://github.com/status-im/react-native.git
synced 2025-02-04 13:44:04 +00:00
Apple TV: RCTTabBar selection controlled by native after render (fix #15081)
Summary: **Motivation** Fix flickering in TabBarIOS on Apple TV... issue #15081 After this change, on Apple TV, TabBarIOS item selections will be controlled purely from the native side after initial render with the `selected` prop. This is necessary because the `UITabBar` implementation in tvOS moves the selection before calling `shouldSelectViewController:`; this issue does not occur on iOS. **Test plan** Existing CI should still pass. Issue is resolved when testing the example code in #15081 . Closes https://github.com/facebook/react-native/pull/15220 Differential Revision: D5601671 Pulled By: javache fbshipit-source-id: c18e7d3482d6c07d534ff40a443a6f642d4267bb
This commit is contained in:
parent
3a031cc93a
commit
0e7375ae36
@ -115,9 +115,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
|||||||
[tab.barItem setTitleTextAttributes:@{NSForegroundColorAttributeName: self.tintColor} forState:UIControlStateSelected];
|
[tab.barItem setTitleTextAttributes:@{NSForegroundColorAttributeName: self.tintColor} forState:UIControlStateSelected];
|
||||||
|
|
||||||
controller.tabBarItem = tab.barItem;
|
controller.tabBarItem = tab.barItem;
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
// On Apple TV, disable JS control of selection after initial render
|
||||||
|
if (tab.selected && !tab.wasSelectedInJS) {
|
||||||
|
self->_tabController.selectedViewController = controller;
|
||||||
|
}
|
||||||
|
tab.wasSelectedInJS = YES;
|
||||||
|
#else
|
||||||
if (tab.selected) {
|
if (tab.selected) {
|
||||||
self->_tabController.selectedViewController = controller;
|
self->_tabController.selectedViewController = controller;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +183,18 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
|||||||
|
|
||||||
#pragma mark - UITabBarControllerDelegate
|
#pragma mark - UITabBarControllerDelegate
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
|
||||||
|
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(nonnull UIViewController *)viewController
|
||||||
|
{
|
||||||
|
NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController];
|
||||||
|
RCTTabBarItem *tab = (RCTTabBarItem *)self.reactSubviews[index];
|
||||||
|
if (tab.onPress) tab.onPress(nil);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
|
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
|
||||||
{
|
{
|
||||||
NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController];
|
NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController];
|
||||||
@ -183,6 +203,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if TARGET_OS_TV
|
#if TARGET_OS_TV
|
||||||
|
|
||||||
- (BOOL)isUserInteractionEnabled
|
- (BOOL)isUserInteractionEnabled
|
||||||
|
@ -29,4 +29,8 @@
|
|||||||
@property (nonatomic, readonly) UITabBarItem *barItem;
|
@property (nonatomic, readonly) UITabBarItem *barItem;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onPress;
|
@property (nonatomic, copy) RCTBubblingEventBlock onPress;
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
@property (nonatomic, assign) BOOL wasSelectedInJS;
|
||||||
|
#endif
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -42,6 +42,9 @@ RCT_ENUM_CONVERTER(UITabBarSystemItem, (@{
|
|||||||
{
|
{
|
||||||
if ((self = [super initWithFrame:frame])) {
|
if ((self = [super initWithFrame:frame])) {
|
||||||
_systemIcon = NSNotFound;
|
_systemIcon = NSNotFound;
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
_wasSelectedInJS = NO;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -118,4 +121,16 @@ RCT_ENUM_CONVERTER(UITabBarSystemItem, (@{
|
|||||||
return self.superview.reactViewController;
|
return self.superview.reactViewController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
|
||||||
|
// On Apple TV, we let native control the tab bar selection after initial render
|
||||||
|
- (void)setSelected:(BOOL)selected
|
||||||
|
{
|
||||||
|
if (!_wasSelectedInJS) {
|
||||||
|
_selected = selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -89,6 +89,8 @@ class Game2048 extends React.Component {
|
|||||||
|
|
||||||
- *Back navigation with the TV remote menu button*: The `BackHandler` component, originally written to support the Android back button, now also supports back navigation on the Apple TV using the menu button on the TV remote.
|
- *Back navigation with the TV remote menu button*: The `BackHandler` component, originally written to support the Android back button, now also supports back navigation on the Apple TV using the menu button on the TV remote.
|
||||||
|
|
||||||
|
- *TabBarIOS behavior*: The `TabBarIOS` component wraps the native `UITabBar` API, which works differently on Apple TV. To avoid jittery rerendering of the tab bar in tvOS (see [this issue](https://github.com/facebook/react-native/issues/15081)), the selected tab bar item can only be set from Javascript on initial render, and is controlled after that by the user through native code.
|
||||||
|
|
||||||
- *Known issues*:
|
- *Known issues*:
|
||||||
|
|
||||||
- [ListView scrolling](https://github.com/facebook/react-native/issues/12793). The issue can be easily worked around by setting `removeClippedSubviews` to false in ListView and similar components. For more discussion of this issue, see [this PR](https://github.com/facebook/react-native/pull/12944).
|
- [ListView scrolling](https://github.com/facebook/react-native/issues/12793). The issue can be easily worked around by setting `removeClippedSubviews` to false in ListView and similar components. For more discussion of this issue, see [this PR](https://github.com/facebook/react-native/pull/12944).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user