How can I force focus to change to a specific view in tvOS?

I am implementing custom code to handle a click on the Menu button on the Siri Remote. How can I force focus to change to my custom menu when pressing the menu button?

Upvotes: 14

Views: 23964

Answers (6)

vikas prajapati
vikas prajapati

Reputation: 1956

For ios 10 you should use preferredFocusEnvironments instead of preferredFocusedView .

In below example if you want to focus on button then see below code.

@IBOutlet weak var button: UIButton!

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

override func viewDidLoad() {
    super.viewDidLoad()

    setNeedsFocusUpdate()
    updateFocusIfNeeded()
}

Upvotes: 23

Slayter
Slayter

Reputation: 1170

Finally figured it out myself. You have to override the preferredFocusedView property of your UIView or UIViewController.

In Swift it works like this:

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

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

I can't quite remember how to override getters in Objective-C so if someone want to post that I'll edit the answer.

Upvotes: 19

Wiingaard
Wiingaard

Reputation: 4302

Here's a nice little Swift 2 copy / paste snippet:

var myPreferredFocusedView: UIView?
override var preferredFocusedView: UIView? {
    return myPreferredFocusedView
}
func updateFocus(to view: UIView) {
    myPreferredFocusedView = napDoneView
    setNeedsFocusUpdate()
    updateFocusIfNeeded()
}

Use it like this:

updateFocus(to: someAwesomeView)

Upvotes: 2

Jenel Ejercito Myers
Jenel Ejercito Myers

Reputation: 2713

@elu5ion 's answer, but in objective-c first declare:

@property (nonatomic) UIView *preferredView;

Set these methods:

-(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;
}

Upvotes: 0

Brandon Gill
Brandon Gill

Reputation: 161

Here is another implementation based on Slayters answer above. Its slightly more elegant I think than using the conditional booleans.

Put this in your viewcontroller

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;
    }
}

Then to use it in your code

viewToFocus = myUIView;

Upvotes: 16

Jenel Ejercito Myers
Jenel Ejercito Myers

Reputation: 2713

here is the 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;

}

in your viewDidLoad or view did appear do something like this:

    UIFocusGuide *focusGuide = [[UIFocusGuide alloc]init];
    focusGuide.preferredFocusedView = [self preferredFocusedView];
    [self.view addLayoutGuide:focusGuide];

if you want to do it when it first launches

Upvotes: 6

Related Questions