React to changes of focus in your Xamarin.tvOS applications

The focus engine introduced in UIKit for tvOS 9.0 is one of the key concepts you should know if you want to develop applications for the Apple TV.

It allows you to know what is the control that is currently focused on the screen, and to be notified when the focus changes from a view to another view (e.g. from a textfield to a button, from a collection view cell to the next cell, etc…).

Today I have created my first and simple application that uses a UICollectionView with few cells as you can see on the screenshot below. I was proud of my work until I realized that when the application is running, there is no visual indication that gives a feedback to the user of which cell is currently selected (cell #0 or cell #1).

tvOS - CollectionView without focus

I then looked for solutions to surround the focused cell with a white border to give an instant feedback to the user. The focus engine gives you this capability through the DidUpdateFocus method.

This method exposes a context to retrieve which views are focused (the previous and the next), and an animation coordinator to change attributes of these views within an animation.

When you know this method, it is very simple to accomplish your goal. The example below shows you how to remove the border for the old focused view, and add a border for the new focused view.

public override void DidUpdateFocus(UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
  base.DidUpdateFocus(context, coordinator);
  coordinator.AddCoordinatedAnimations(() =>
  {
    if (context.PreviouslyFocusedView != null)
    {
      var previousCell = (UICollectionViewCell)context.PreviouslyFocusedView;
      previousCell.Layer.BorderColor = UIColor.Clear.CGColor;
      previousCell.Layer.BorderWidth = 0;
    }

    if (context.NextFocusedView != null)
    {
      var nextCell = (UICollectionViewCell)context.NextFocusedView;
      nextCell.Layer.BorderColor = UIColor.White.CGColor;
      nextCell.Layer.BorderWidth = 5;
    }
  }, null);
}

The visual feedback is now more understandable for the user and he knows that the currently focused view is the cell #1.

tvOS - CollectionView with border when focused

It is good but if I want to have the same feature that is standard on the Apple TV (the cells sizes increase/decrease when they are focused/unfocused), what I need to do ?

If your cell is only composed with an UIImageView, you can select the option called “Adjusts image when focused” on the properties of this view in Xcode.

tvOS - ImageView adjusts image when focused

But when your cells are more complex like the sample below (each cell is composed with an UIImageView, a translucent UIView with a UILabel above), then you probably want to increase the size all the items inside the cell at the same time.

tvOS - CollectionView with scale when focused

No problem to achieve this goal with the same method that was previously mentioned. We just need to apply a transformation to the cell (CGAffineTransform.MakeScale(…)) when it receive the focus, and revert it (CGAffineTransform.MakeIdentity()) when the focus is lost.

public override void DidUpdateFocus(UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
  base.DidUpdateFocus(context, coordinator);
  coordinator.AddCoordinatedAnimations(() =>
  {
    if (context.PreviouslyFocusedView != null)
    {
      var previousCell = (UICollectionViewCell)context.PreviouslyFocusedView;
      previousCell.Transform = CGAffineTransform.MakeIdentity();
    }

    if (context.NextFocusedView != null)
    {
      var nextCell = (UICollectionViewCell)context.NextFocusedView;
      nextCell.Transform = CGAffineTransform.MakeScale(1.25f, 1.25f);
    }
  }, null);
}

As we have seen in this article, it’s pretty easy to interact with the focus engine of tvOS to apply any modifications on views, depending on the focus state of each of them.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s