TvOS UITabBarController begins to focus

I have a simple tvOS application starting with UITabBarController and I want the main view to be focused when the application starts, and not the tab bar.

I tried playing with self.tabBarController.tabBar.userInteractionEnabled to temporarily remove focus, but in vain. (Also, I don't like this kind of workaround)

Any clue?

Thanks in advance.

+7
tvos uitabbarcontroller focus uitabbar
source share
6 answers

This approach basically works, but does not allow you to select a tab bar item with a click, since it returns a tabBar when it should return the selected item. Here is an improved version that solves this by returning [super preferredViewController] instead of tabBar in the usual case. This version also hides the tab bar with alpha at startup, so that it does not flicker. Most likely, there are more elegant ways to hide.

 @interface MWTabBarController () @property (nonatomic, assign) BOOL firstTime; @end @implementation MWTabBarController - (void)viewDidLoad { [super viewDidLoad]; self.firstTime = YES; self.tabBar.alpha = 0; [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(unAlphaTabBar) userInfo:nil repeats:NO]; } - (void) unAlphaTabBar { self.tabBar.alpha = 1; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (UIView *)preferredFocusedView { if (self.firstTime) { self.firstTime = NO; return self.selectedViewController.preferredFocusedView; } else { return [super preferredFocusedView]; } } 
+3
source share

My original solution no longer works on tvOS 9.3, so I found a new one with a subclass of UITabBarController :

 @interface TVTabBarController : UITabBarController @property (nonatomic) BOOL useDefaultFocusBehavior; @end @implementation TVTabBarController - (UIView *)preferredFocusedView { return self.useDefaultFocusBehavior ? [super preferredFocusedView] : self.selectedViewController.preferredFocusedView; } - (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator { [super didUpdateFocusInContext:context withAnimationCoordinator:coordinator]; self.useDefaultFocusBehavior = YES; } @end ... - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.tabBarController.tabBar.hidden = YES; // or do it in storyboard } 

If you are using a storyboard to initially set up your user interface, be sure to set your own TVTabBarController class in your tab bar controller.


Original solution:

The proposed approach with inheritance from UITabBarController did not work for me, because actually -preferredFocusedView is called twice at startup, so I had to add a counter to return self.selectedViewController.preferredFocusedView for the first 2 calls. But this is really a hacker decision, and there is no guarantee that it will not break in the future.

So, I found a much better solution: update focus in appdelegate -applicationDidBecomeActive: on the first call.

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.tabBarController.tabBar.hidden = YES; } - (void)applicationDidBecomeActive:(UIApplication *)application { static BOOL forceFocusToFirstTab = YES; if (forceFocusToFirstTab) { forceFocusToFirstTab = NO; [self.tabBarController.selectedViewController updateFocusIfNeeded]; } } 
+6
source share

I found a solution, so if anyone is interested, you just need to subclass UITabBarController and override preferredFocusedView :

 @interface ZTWTabBarController () @property (nonatomic, assign) BOOL firstTime; @end @implementation ZTWTabBarController - (void)viewDidLoad { [super viewDidLoad]; self.firstTime = YES; } - (UIView *)preferredFocusedView { if (self.firstTime) { self.firstTime = NO; return self.selectedViewController.preferredFocusedView; } else { return [super preferredFocusedView]; } } @end 
+2
source share

This is the simplest and cleanest solution in my opinion:

 override var preferredFocusedView: UIView? { if tabBar.hidden { return selectedViewController?.preferredFocusedView } return super.preferredFocusedView } 
0
source share

I was able to achieve this effect very simply using the isHidden property of UITabBar .

 override func viewDidLoad() { super.viewDidLoad() self.tabBar.isHidden = true } 

When the user scrolls to display the tab bar, the UITabBarController display it automatically.

0
source share

Since preferredFocusedView deprecated in tvOS, you should override the preferredFocusEnvironments property instead

Swift 4.0

 override var preferredFocusEnvironments: [UIFocusEnvironment] { if firsTime, let enviroments = selectedViewController?.preferredFocusEnvironments { firsTime = false return enviroments } return super.preferredFocusEnvironments } 
0
source share

All Articles