如何在tvOS中强制将焦点更改为特定视图?

14

我正在实现自定义代码来处理Siri远程控制器上菜单按钮的点击事件。当按下菜单按钮时,如何强制将焦点切换到我的自定义菜单?


这个问题涉及到一个常见的tvOS焦点问题 [直接查看]: https://dev59.com/YvX1s4cB2Jgan1znZdVy#52251007 - abhimuralidharan
6个回答

23

对于 iOS 10,您应该使用 preferredFocusEnvironments 而不是 preferredFocusedView。

在下面的示例中,如果您想要聚焦于按钮,则请参见下面的代码。

@IBOutlet weak var button: UIButton!

override var preferredFocusEnvironments: [UIFocusEnvironment] {
    return [button]
}

override func viewDidLoad() {
    super.viewDidLoad()

    setNeedsFocusUpdate()
    updateFocusIfNeeded()
}

3
由于 preferredFocusedView 已被弃用,因此现在应该接受这个答案。 - Reza Shirazian

19

最后我自己弄明白了。你需要重写你的UIViewUIViewControllerpreferredFocusedView属性。

在Swift中,它的工作方式如下:

func myClickHandler() {
    someCondition = true
    self.setNeedsFocusUpdate()
    self.updateFocusIfNeeded()
    someCondition = false
}

override weak var preferredFocusedView: UIView? {
    if someCondition {
        return theViewYouWant
    } else {
        return defaultView
    }
}

我不太记得如何在Objective-C中覆盖getter方法,所以如果有人想发布的话,我会编辑这个答案。


谢谢。我本来考虑这样做,但是把所有这些“someConditions”到处都放置起来看起来太乱了。如果你能直接设置setPreferredFocusedView,那就简单多了... - Simen Øian Gjermundsen
但是,等等。当我想要将焦点更改到另一个视图控制器时,这该怎么办? - Simen Øian Gjermundsen
2
我同意。希望他们能添加它。此外,为了避免所有的“someCondition”,我在我的视图控制器中添加了一个名为viewToFocusUIView属性。然后在getter方法中,我检查该视图是否不为nil并返回它。否则将返回默认视图。 - Slayter
1
关于您的viewController问题,如果viewControllers视图是父viewController层次结构的一部分(我想这就是您的意思),那么请在父viewController的preferredFocusedView getter中返回viewController的视图。 - Slayter

16

这里是基于Slayter之前答案的另一种实现方式。我认为这比使用条件布尔值稍微更加优雅。

将以下内容放置在您的视图控制器中。

var viewToFocus: UIView? = nil {
    didSet {
        if viewToFocus != nil {
            self.setNeedsFocusUpdate();
            self.updateFocusIfNeeded();
        }
    }
}

override weak var preferredFocusedView: UIView? {
    if viewToFocus != nil {
        return viewToFocus;
    } else {
        return super.preferredFocusedView;
    }
}

然后在您的代码中使用它

viewToFocus = myUIView;

1
这在iOS 10中已被弃用。建议使用preferredFocusEnvironments。 - nyxee

6
这里是Objective C。
- (UIView *)preferredFocusedView
{
    if (someCondition) {
      // this is if your menu is a tableview
        NSIndexPath *ip = [NSIndexPath indexPathForRow:2 inSection:0];
        UITableViewCell * cell = [self.categoryTableView cellForRowAtIndexPath:ip];

        return cell;
    }

    return self.view.preferredFocusedView;

}

在你的viewDidLoad或viewDidAppear方法中,可以像下面这样做一些事情:
    UIFocusGuide *focusGuide = [[UIFocusGuide alloc]init];
    focusGuide.preferredFocusedView = [self preferredFocusedView];
    [self.view addLayoutGuide:focusGuide];

如果您想在首次启动时进行操作


我在使用集合视图而不是表格视图时,单元格返回了空值。你有什么想法为什么会是空值吗? - IamDev

1
这是一个简单的Swift 2复制/粘贴代码片段:
var myPreferredFocusedView: UIView?
override var preferredFocusedView: UIView? {
    return myPreferredFocusedView
}
func updateFocus(to view: UIView) {
    myPreferredFocusedView = napDoneView
    setNeedsFocusUpdate()
    updateFocusIfNeeded()
}

像这样使用它:
updateFocus(to: someAwesomeView)

0

@elu5ion的回答,但是用Objective-C实现 首先声明:

@property (nonatomic) UIView *preferredView;

设置这些方法:

-(void)setPreferredView:(UIView *)preferredView{
      if (preferredView != nil) {
         _preferredView = nil;
         UIFocusGuide *focusGuide = [[UIFocusGuide alloc]init];
         [self.view addLayoutGuide:focusGuide];
         focusGuide.preferredFocusedView = [self preferredFocusedView];
         [self setNeedsFocusUpdate];
         [self updateFocusIfNeeded];
    }
    _preferredView = preferredView;
 }


 - (UIView *)preferredFocusedView {
     if (_preferredView) {
          return _preferredView;
     }
     return self.view.preferredFocusedView;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接