How to setup a constraint to a tvOS focused element

1.4k Views Asked by At

I have a UICollectionView in my tvOS app that has a image and a caption text. I've setup a constraint to pin the caption text just under the image.

enter image description here

When the cell is focused and the images grows, the text does not move and stays over the image. Is there a way to set a constraint that takes in account the focused image size?

Image without focus

Image with focus

3

There are 3 best solutions below

0
On

Use this code, I hope it help you. This code write into the custom cell class.

override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if (self.focused) {
   self.custom_ImageView.adjustsImageWhenAncestorFocused = true
   self.custom_LabelView1.frame = CGRectMake(0, 279, 548, 29)
}
else {
   self.custom_ImageView.adjustsImageWhenAncestorFocused = false
   self.custom_LabelView1.frame = CGRectMake(0, 259, 548, 29)
}
}
0
On

I ended up setting a @IBOutlet to my spacing constraint and I update it in the didUpdateFocusInContext method. To add some effect, I also transform the label.

In my collection cell:

override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
    coordinator.addCoordinatedAnimations({
        if self.focused {
            self.spacingConstraint.constant = 30
            UIView.animateWithDuration(0.3) {
                self.label.transform = CGAffineTransformMakeScale(1.15, 1.15)
                self.layoutIfNeeded()

            }
        }
        else {
            self.spacingConstraint.constant = 0
            UIView.animateWithDuration(0.3) {
                self.label.transform = CGAffineTransformMakeScale(1, 1)
                self.layoutIfNeeded()

            }
        }
        }, completion: nil)
}
0
On

You can use a UIImageView property focusedFrameGuide for that. It returns a UILayoutGuide object, which unfortunately can't be used in Interface Builder, but you can create constraints with it in code. Note that this constraint makes sense only when the view is focused, so you have to set its active property according to the self.focused property.

First create the constraint on view initialization:

self.focusedSpacingConstraint = NSLayoutConstraint(item: imageView.focusedFrameGuide, attribute: .BottomMargin, relatedBy: .Equal, toItem: label, attribute: .Top, multiplier: 1, constant: 0)
//add it to the view and set active to false

Then activate either this constraint or the default one depending on the focus:

override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
    coordinator.addCoordinatedAnimations({
  self.focusedSpacingConstraint.active = self.focused
  self.spacingConstraint.active = !self.focused

  //set label's transform and animate layout changes
}

You can also use the focusedFrameGuide to set label's height (as a percentage of image's height).

The advantage of this approach is that you don't have to change the (hardcoded) constant whenever the image size changes.