UICollectionViewCell to UIButton Focus in tvOS
Asked Answered
A

5

14

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 UICollectionView. If I am on the first cell or the second cell and I swipe up then I can easily focus on the UIButton. When I am on the third cell then I am not able to move the focus to the UIButton. Any ideas what is going on?

enter image description here

Annates answered 20/10, 2015 at 15:0 Comment(0)
M
18

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],
  ]];
Maki answered 20/10, 2015 at 19:28 Comment(3)
Thanks Jess - this was driving me nuts. Note that if you have a problem using this then it could be because one of your anchor points is embedded in another view. I had a collection view inside a scroll view and using the collection view bottom as my top anchor point didn't work. Changing this to the scroll view bottom worked.Chatman
Hi Jess, I have another issue. If I have button at right instead of left and if I have only one row collection view I can't able make collection view focusable. Any solution for this ?Surfboat
@Vijay_07 that's probably worth opening a new stack question. Not sure off the bat.Maki
A
2

Jess Bowers solution is almost there but Xcode says UIButtons 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.

enter image description here

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],
  ]];
Adalard answered 21/11, 2015 at 11:47 Comment(7)
UIButton is a subclass of UIControl which is a subclass of UIView. developer.apple.com/library/tvos/documentation/UIKit/Reference/… Also look at the Apple sample which uses topAnchor on a button. developer.apple.com/library/prerelease/tvos/samplecode/…Tonsorial
Ok but Xcode says buttons have no topAnchor and unfortunately Jess' solution doesn't work for me.Adalard
Something else is wrong. I just typed in a name of my button, typed .top and hit escape and the autocomplete showed me topAnchor. Current Xcode. Also, Jess' solution doesn't work for me either. I examine the guide's frame in a breakpoint and it looks right. But it has no effect.Tonsorial
That is very strange. Anyway it is not working for me.Adalard
yeah that's strange. I've used this technique many times. UIButton definitely has a topAnchor. Possibly there is something specific and different about the setup. Might be helpful to post more code in the question and i'd be happy to give feedback. Certain assumptions i made may not be true for your case. UIFocusGuide and layout guide are meant to eliminate the need for dummy views like you've got there. But they do work.Maki
I am not sure what it is, but your method is simply not working for me.Adalard
The Xcode debugger returns error: property 'topAnchor' not found on object of type 'UIButton *' error: 1 errors parsing expression when I po self.selectAllButton.topAnchor but works when I po [self.selectAllButton topAnchor]. Weird stuff.Umbilical
M
2

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]
Matter answered 28/7, 2017 at 18:22 Comment(0)
I
0

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!!!

Ivette answered 20/7, 2017 at 17:20 Comment(0)
J
-2

Use :

override weak var preferredFocusedView: UIView? { get { return segmentedControl } }

Jinja answered 4/1, 2016 at 20:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.