Focus Management

What is focus management?

Focus Management is a system designed for 10-foot screen to let the user select a particular visual element or component on a screen. You can use one of the following options to use focus:

  • The directional arrow keys or the TAB key on a keyboard
  • Remote control’s directional-pad for a Smart TV
  • Game controller for Xbox/Playstation

When an element is focused, it is highlighted to confirm the user that element is focused or selected for further action:

Animated gif that demonstrates how focus moves from one element to the next

You.i Engine One is able to dynamically calculate how it should manage focus behaviors, but sometimes it is necessary to implement custom behaviors such as focusing between elements that aren’t directionally aligned, or setting the ‘default’ item to focus on when visiting a page. The engine also has callbacks such as onFocus and onBlur to implement custom behavior when an element receives or loses focus.

For details on advanced focus management, see:

Why we need focus

Focus management is required to make 10-foot navigation easy for app users. Without it, there is no way to let the user know if a visual element, such as image or button, is selected for any further action. The following diagram explains the how focus works in a default scenario for any 10-foot device:

This diagram illustrates how focus works on a 10-foot screen.

Focus management is not required on touch devices as the elements present are navigated with a remote or keyboard keys, or game controllers using touch or swipe.

Applying focus to your apps

The following topics explains important focus-related concepts that a developer should know to work with You.i React Native-based app:

Setting Focus to a Component

Use the FocusManager module to set the default focus using the focus() function.

FocusManager.focus(componentRef);

FocusManager.focus() can be used from any callback or with any function that gives you a ref to your component (regardless of whether the component is a Facebook RN component or a You.i Ref component such as ButtonRef. For example it can be from a ref callback, or from a callback like onLoad.

A common way to do this is to store the ref and then set use it in the parent’s componentDidMount lifecycle method.

class Screen extends React.Component {
  buttonRef = React.createRef()
  componentDidMount() { 
    FocusManager.focus(this.buttonRef.current);
  }
  render() {
    return <Button ref={this.buttonRef} />
  }
}

But you could also do this as soon as a focusable component’s ref is accessible, as in these next two examples:

//example showing focus as part of the ref callback
class Screen extends React.Component { {
  _onRef = ref => {
    FocusManager.focus(ref);
  }
  render() {
    return <Button ref={this._onRef} />
  }
}
//example using onLoad for ButtonRef, could substitute any other callback that gives a ref
class Screen extends React.Component {
  _onLoad = ref => {
    FocusManager.focus(ref);
  }

  render() {
    return <ButtonRef onLoad={this._onLoad} />
  }
}

For more information on the onLoad callback, see Holding References to Ref Components.

Using Focus Callbacks

The ref components in You.i React Native provides various callbacks for focus management. Refer to the following use cases to help understand how to use the focus-related callbacks:

Focus gained or lost on a ref component

To determine if a ref component has gained focus or lost focus, use onFocus and onBlur respectively. For example:

<ViewRef
onFocus={() => {}}
onBlur={() => {}}
/>

Focus gained or lost on a child ref component

To determine if a child ref component has gained or lost focus, use onFocusInDescendants and onBlurInDescendants respectively. For example:

<ViewRef
onFocusInDescendants={() => {}}
onBlurInDescendants={() => {}}
/>

Setting Focus Direction

Sometimes, you may want to override the default focus behavior provided by the You.i React Native. For this case, you can use setNextFocus() to override default behavior and define your own. The setNextFocus() function takes three arguments:

  • Starting element; the one that will be losing focus.
  • Next element; where you want focus to move to.
  • Direction; a string that specifies which direction will have this new focus behavior.

For more information, see Working with the Focus Manager module.

Sticky Headers

If you have a sticky header set on a vertical ScrollView, where both the header and the list items underneath are focusable, and the header is overlapping a currently focused list item, you might not be able to switch focus from the list item to the overlapping sticky header. This is due to You.i React Native’s default focus logic. To prevent this situation, you can either offset the size of your header by setting list magnets using snapToInterval or through layout styling, or make your sticky headers not focusable. Note this is the same for both sticky headers and invert sticky headers.

Enabling and Disabling Focus

Using the focusable prop, you can control whether a component should receive focus or not with the You.i React Native. When focusable is set to false, the selected component will not be selected or receive focus. If a view gets covered by another view, or another screen in the event of react-navigation, it is better to set the visible prop to false. This disables focus and prevents overdraw. Even better, it cascades, so you can surround the entire screen with a ViewRef component and hide it.

Setting Focus Root

Sometimes, you want focus to remain within a single composition. For example, if you have an overlay that you need to show, and you want the focus system to only allow focusing on items within that composition instead of underneath, you will need to set it as the focus root.

When an item is set as the Focus Root in the scene tree, only itself or its children will be able to receive focus. It is as if you set the focusable prop to false on all the components that are not a child of the focus root. For more information on setFocusRoot(), see Working with the Focus Manager module.

Focus and After Effects Workflow

For the default behavior of the You.i React Native solution, focus management does not need anything more than Focus In and Focus Out timelines with animation for any view. You should always have Focus In and Focus Out timelines for any ViewRef to get it focused. Also if you have the timelines for focus, but do not have any focus animation on them, the user will never know if the particular view is selected or not.

The React Native does very little focus management of its own with this integration of the You.i Engine. Facebook React Native communicates with the You.i Engine on the focusable views, via the isTVSelectable prop, and responds to focus in/out events, via onFocus and onBlur, respectively.

The following screen shot displays the Focus In and Focus Out timelines in After Effects:

screen capture from After Effects showing the focus in and focus out timelines

The following GIF illustrates the difference between Focus In start and end points and how animation plays a major role for focus management:

Focus in start and end points

The following GIF illustrates the difference between Focus Out start and end points and how animation plays a major role for focus management:

Focus out start and end points

Focus Behavior in You.i RN Components with AE workflow and You.i RN Components without AE workflow

Focus is handled differently in You.i RN components with AE workflow and without AE workflow. The following table explains the differences:

Focus in You.i RN Components with AE workflow Focus in You.i RN components without AE workflow
  • These components are focusable, if the focusable prop is true and the visible prop is not false.
  • If the component is a You.i RN component with AE workflow, and it has a Focus In animation, the focusable prop is true by default.
  • FocusManager can programmatically focus a You.i RN component with AE workflow as soon the onCompositionDidLoad prop is called.

  • Not all these RN components are focusable, except Touchable (and if extended, Button).
  • These components do not use the visible or focusable props.
  • These RN components do not have the onCompositionDidLoad prop.
  • Focusable RN components without AE workflow can be focused on using FocusManager only after the first render is completed.
  • These RN components can be focused on as soon as a You.i RN component’s onCompositionDidLoad is called.

Using FocusZone and FocusZoneRef

Two custom React Native components, FocusZone and FocusZoneRef, allow you to harness the power of CYIFocusZoneView in the React Native layer and within After Effects. These components enable you to determine where focus lands in a view, allowing you to override the Engine’s default focus logic.

These components employ a prop, entryMode, and a function, setInitialFocus /setInitialFocusRef, that determine which entries in a subtree gain focus and retain it when the view connected to that subtree is exited and returned to. The modes, and how they behave with and without an initial focus, are the following:

Mode Behavior If Initial Focus is Set If Initial Focus is not Set or is Invalid
Normal Behaves like a normal view; doesn’t require special handling, i.e. it follows the default focus logic of the Engine. It’s used for the first entry into the subtree. Consecutive entriesbehave as normal. Behaves as normal.
None Focus won’t enter this component or its subtree (regardless of initial focus setting). Focus can still be explicitly assigned by requesting focus on an item within the disabled focus zone. n/a n/a
Last When focus enters the subtree, it’s given to the last thing that had focus in this subtree. It’s used for the first entry into the subtree. Consecutive entries apply focus to the last thing that had focus in the subtree. The first entry behaves as normal, and consecutive entries apply focus to the last thing that had focus in the subtree.
Fixed When focus enters the subtree, it’s given to the specified initial focus view. It’s used for every focus entry to the subtree. Behaves as normal.

FocusZone and FocusZoneRef can be used with the Focus Manager module’s setNextFocus function to specify where the focus will go when leaving the subtree rooted at the FocusZone.

For details on usage, including code samples, refer to the FocusZone and FocusZoneRef component reference.

Like other You.i React Native ref components, FocusZoneRef allows you to directly connect to views in After Effects Compositions. For more on FocusZoneRef and the After Effects workflow, see Setting Focus in After Effects.

Using the Focus Debugger

The Dev panel has a tool called Focus Debugger for debugging focus when you encounter issues. It shows what the You.i React Native thinks it should be handling focus at any given time. For more information on Dev Panel, see Using Dev Panel for Debugging.

When you select Focus Debugger from the Dev panel and as you navigate around the app, you can see debug draws of where focus will go for any given direction from a certain element.