tvOS UITabBarController начать расфокусированный

у меня есть простое приложение tvOS, начинающееся с UITabBarController и я хочу, чтобы основной вид имел Фокус при запуске приложения, а не панель вкладок.

Я пробовал играть с self.tabBarController.tabBar.userInteractionEnabled временно удалить фокус, но напрасно. (Кроме того, мне не нравится такой обходной путь)

любой ключ?

спасибо заранее.

6 ответов


вышеуказанный подход в основном работает, но не позволяет выбрать элемент панели вкладок с помощью щелчка, поскольку он возвращает панель вкладок в том случае, когда он должен вернуть selectedItem. Вот улучшенная версия, которая решает это, возвращая [super preferredViewController] вместо tabBar в обычном случае. Эта версия также скрывает панель вкладок с Альфой при запуске, чтобы она не мерцала. Вероятно, есть более изящные способы прятаться.

@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, поэтому я нашел новый с подклассами 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
}

если вы используете раскадровки для начальной настройки пользовательского интерфейса, не забудьте установить пользовательский класс TVTabBarController к контроллеру панели вкладок там.


оригинальное решение:

предлагаемый подход с наследованием от UITabBarController не работает для меня, потому что на самом деле -preferredFocusedView вызывается дважды при запуске, поэтому мне пришлось добавить счетчик, чтобы вернуться self.selectedViewController.preferredFocusedView для первого 2 звонков. Но это действительно хакерское решение, и нет никакой гарантии, что оно не сломается в будущем.

поэтому я нашел гораздо лучшее решение: обновление Force focus в 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];
    }
}

Я нашел решение, поэтому, если кто-то заинтересован, вам просто нужно подкласс 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

Это самое простое и чистое решение, на мой взгляд:

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

я смог достичь этого эффекта очень просто с помощью isHidden свойства UITabBar.

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
    }