tvOS UITabBarController 开始不专心
tvOS UITabBarController start unfocused
我有一个以 UITabBarController
开头的简单 tvOS 应用程序,我希望主视图在应用程序启动时获得焦点,而不是标签栏。
我试过使用 self.tabBarController.tabBar.userInteractionEnabled
暂时移除焦点,但没有成功。 (此外,我不喜欢那种解决方法)
有线索吗?
提前致谢。
我找到了解决方案,所以如果有人感兴趣,您只需继承 UITabBarController
并覆盖 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
上述方法大部分都有效,但不允许您 select 标签栏项目点击 return tabBar 在这种情况下应该 return selectedItem.这是一个改进的版本,它通过 returning [super preferredViewController] 而不是正常情况下的 tabBar 来解决这个问题。这个版本还在启动时用 alpha 隐藏了标签栏,这样它就不会闪烁。可能有更优雅的方法来隐藏。
@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];
}
}
我原来的解决方案不再适用于 tvOS 9.3,所以我找到了一个带有 subclassing 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
}
如果您使用 Storyboard 进行初始 UI 设置,请不要忘记为您的标签栏控制器设置自定义 class TVTabBarController
。
原解:
从 UITabBarController
继承的建议方法对我不起作用,因为实际上 -preferredFocusedView
在启动时被调用了两次,所以我不得不向 return 添加一个计数器 self.selectedViewController.preferredFocusedView
用于前 2 个调用。但这是一个非常 hacky 的解决方案,不能保证它将来不会崩溃。
所以我找到了一个更好的解决方案:在第一次调用时在 appdelegate 的 -applicationDidBecomeActive:
中强制更新焦点。
- (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];
}
}
这是我认为最简单、最干净的解决方案:
override var preferredFocusedView: UIView? {
if tabBar.hidden {
return selectedViewController?.preferredFocusedView
}
return super.preferredFocusedView
}
我可以通过 UITabBar
的 isHidden
属性 非常简单地实现这种效果。
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.isHidden = true
}
当用户向上滚动以显示标签栏时,UITabBarController
会自动取消隐藏。
由于 preferredFocusedView
在 tvOS 中已弃用,您应该改写 preferredFocusEnvironments
属性
Swift 4.0
override var preferredFocusEnvironments: [UIFocusEnvironment] {
if firsTime, let enviroments = selectedViewController?.preferredFocusEnvironments {
firsTime = false
return enviroments
}
return super.preferredFocusEnvironments
}
我有一个以 UITabBarController
开头的简单 tvOS 应用程序,我希望主视图在应用程序启动时获得焦点,而不是标签栏。
我试过使用 self.tabBarController.tabBar.userInteractionEnabled
暂时移除焦点,但没有成功。 (此外,我不喜欢那种解决方法)
有线索吗?
提前致谢。
我找到了解决方案,所以如果有人感兴趣,您只需继承 UITabBarController
并覆盖 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
上述方法大部分都有效,但不允许您 select 标签栏项目点击 return tabBar 在这种情况下应该 return selectedItem.这是一个改进的版本,它通过 returning [super preferredViewController] 而不是正常情况下的 tabBar 来解决这个问题。这个版本还在启动时用 alpha 隐藏了标签栏,这样它就不会闪烁。可能有更优雅的方法来隐藏。
@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];
}
}
我原来的解决方案不再适用于 tvOS 9.3,所以我找到了一个带有 subclassing 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
}
如果您使用 Storyboard 进行初始 UI 设置,请不要忘记为您的标签栏控制器设置自定义 class TVTabBarController
。
原解:
从 UITabBarController
继承的建议方法对我不起作用,因为实际上 -preferredFocusedView
在启动时被调用了两次,所以我不得不向 return 添加一个计数器 self.selectedViewController.preferredFocusedView
用于前 2 个调用。但这是一个非常 hacky 的解决方案,不能保证它将来不会崩溃。
所以我找到了一个更好的解决方案:在第一次调用时在 appdelegate 的 -applicationDidBecomeActive:
中强制更新焦点。
- (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];
}
}
这是我认为最简单、最干净的解决方案:
override var preferredFocusedView: UIView? {
if tabBar.hidden {
return selectedViewController?.preferredFocusedView
}
return super.preferredFocusedView
}
我可以通过 UITabBar
的 isHidden
属性 非常简单地实现这种效果。
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.isHidden = true
}
当用户向上滚动以显示标签栏时,UITabBarController
会自动取消隐藏。
由于 preferredFocusedView
在 tvOS 中已弃用,您应该改写 preferredFocusEnvironments
属性
Swift 4.0
override var preferredFocusEnvironments: [UIFocusEnvironment] {
if firsTime, let enviroments = selectedViewController?.preferredFocusEnvironments {
firsTime = false
return enviroments
}
return super.preferredFocusEnvironments
}