I have a UICollectionView which contains 12-13 UICollectionViewCells. I can easily focus on the UICollectionViewCells and everything works. There is a UIButton outside the U
Swift 3.0
Jess Bower's answer was huge help to me & saved a lot of time.
Here's what worked with Swift 3 & tvOS 10. One now has to use preferredFocusEnvironments
. In ViewDidLoad()
self.view.addLayoutGuide(focusGuide)
self.focusGuide.topAnchor.constraint(equalTo: self.buttonAbove.topAnchor).isActive = true
self.focusGuide.bottomAnchor.constraint(equalTo: self.CollectionView.topAnchor).isActive = true
self.focusGuide.leadingAnchor.constraint(equalTo: self.CollectionView.leadingAnchor).isActive = true
self.focusGuide.widthAnchor.constraint(equalTo: self.CollectionView.widthAnchor).isActive = true
self.focusGuide.preferredFocusEnvironments = [self.buttonAbove]
You should use a UIFocusGuide that encompasses the UIButton you want to focus. Make the UIFocusGuide as wide as the collectionView and tall enough to cover the button. Make the preferredFocusView the button.
UIFocusGuide *topButtonFocusGuide = [[UIFocusGuide alloc] init];
topButtonFocusGuide.preferredFocusedView = myButton;
[self.view addLayoutGuide:topButtonFocusGuide];
[self.view addConstraints:@[
[topButtonFocusGuide.topAnchor constraintEqualToAnchor:myButton.topAnchor],
[topButtonFocusGuide.bottomAnchor constraintEqualToAnchor:myCollectionView.topAnchor],
[topButtonFocusGuide.leadingAnchor constraintEqualToAnchor:myCollectionView.leadingAnchor],
[topButtonFocusGuide.widthAnchor constraintEqualToAnchor:myCollectionView.widthAnchor],
]];
Jess Bowers solution is almost there but Xcode says UIButton
s doesn't have topAnchor
property and the solution given by Jess doesn't work for me.
For me, the solution was to create a huge view with the same width as the UICollectionView
on top of it. See picture.
The code will be this:
UIFocusGuide *topButtonFocusGuide = [[UIFocusGuide alloc] init];
topButtonFocusGuide.preferredFocusedView = myButton;
[self.view addLayoutGuide:topButtonFocusGuide];
[self.view addConstraints:@[
[topButtonFocusGuide.topAnchor constraintEqualToAnchor:transparentView.topAnchor],
[topButtonFocusGuide.bottomAnchor constraintEqualToAnchor:transparentView.bottomAnchor],
[topButtonFocusGuide.leadingAnchor constraintEqualToAnchor:transparentView.leadingAnchor],
[topButtonFocusGuide.widthAnchor constraintEqualToAnchor:transparentView.widthAnchor],
]];
Use :
override weak var preferredFocusedView: UIView? { get { return segmentedControl } }
One of the issues I was facing involved using a UINavigationController for the landing pages to push detail ViewControllers onto the stack when an item is selected.
I put a breakpoint inside the UIButton's canBecomeFocused override, and using this quick little extension asked the button why it is not focusable.
extension UIView {
func whyNotFucusable () {
print(self.perform(Selector(("_whyIsThisViewNotFocusable"))).takeUnretainedValue())
}
}
I kept receiving the following error trying to debug....
ISSUE: This view may not be focusable because other views or focus guides are occluding it.
First of all I looked up in the dictionary what the heck occluding meant....
verb, formal, technical
- stop, close up, or obstruct (an opening, orifice, or passage).
The question now was what view is obstructing my UIButton???
I quickly unwrapped the UI in the visual debugger, and there was a clear view on top of my UIButtons. Inspecting the view I found out that Unlike iOS, where the nagivationBar has a default system background color, tvOS's implementation has a clear default color. I realized that I didn't hide the nav bar, and in return it was obstructing my buttons.
I did the following, and it fixed all my issues :)
navController.setNavigationBarHidden(true, animated: false)
Hope this helps!!!