Focus Management with React Native on TV Plaforms
BY GUILLERMO VELÁSQUEZ
Follow on twitter
Helping frontend / React engineers prepare for interviews with mock interviews
Over the past couple of months, we’ve been building a React Native-based streaming video app for mobile, tablet, and TV devices using You.i TV’s cross-platform SDK, . We’ve talked before about our experience as a whole but today we want to dig down deep and talk about a feature that we really enjoy: the FocusManager.
When developing applications for connected TV and Smart TV platforms, it’s important to remember that user input comes from a remote.
Now that I’ve stated the obvious, how do we, as developers, handle and give proper feedback to the user when they are interacting with said remote? Enter Focus Management.
Focus management is required to make TV navigation easy for users. Without it, there is no way to let the user know if a visual element — like selecting an image or button — requires any further action. So, to build an app for a TV platform, we need a way to handle and give feedback about the focus of UI elements within the app. That’s where You.i Engine One’s FocusManager comes in.
Focus Management With You.i Engine One
When we first started developing for TV using You.i Engine One and its React Native solution, we were emulating the TV UI on a macOS app. So, we started developing features and using our pointer to interact with the UI. It wasn’t until later, when tickets about focus management started to show up, that we started testing on Android TV and used the remote control.
You.i Engine One is built for TV
When we started paying attention to focus management, we went to You.i TV’s documentation. That’s when it became clear that You.i Engine One was developed with TV in mind. We found a full explanation on why focus management is important.
Moreover, we could rely on the same techniques and APIs for any TV platform supported by You.i Engine One. By the time of writing this piece, tvOS, Android TV, Amazon Fire TV, Roku, PlayStation 4, and Xbox One are all included.
How does it work?
The fundamentals behind focus management are the same between platforms: simple navigation and highlighting the selected element. Differences arise when implementing how the focus behaves.
By default, FocusManager only needs FocusIn and FocusOut timelines to make something focusable. This is done when using You.i Engine One’s After Effects Compositions.
After the timeline hooks up to an item, the engine will pick it up by default. Then you’ll be able to see it getting focused by using the remote control on your platform or emulator. In practice, all it will do is play a certain animation that gives the user feedback on what it is happening on the screen.
So you should always have FocusIn and FocusOut timelines for any Ref to get it focused. If there is no focus animation on them, the user will never know if the particular view is selected or not.
Advanced Techniques with FocusManager
In most cases, the default focus behavior is enough for apps built with You.i Engine One. If we need to tweak the default behavior, we can do so. There are two main ways we can interact with the focusability of elements:
Hooking up onFocus and onBlur props to focusable elements
Once we have made an element focusable, we can hook up to its focus and blur events. This is particularly helpful when we want to hook up extra logic on top of the animations to the UI elements. For example:
Using the FocusManager module
You.i Engine One exposes the FocusManager module which lets us override the default behavior.
The FocusManager module exposes the following API:
With the Focus Manager, we can do pretty cool stuff, like:
Autofocus: A great user experience eases navigation and guides the user. For example, when filling out a form in an app, the focus inputs should guide where we want the user to enter information. The same notion applies to TV platforms. When a user goes to a particular screen, we want to focus on the next immediate action:
2. Overriding focusable elements: The default focusability of elements in You.i Engine One is somewhat related to the position of elements on screen. Take a look at the following image.
A linear list of elements, focusable all in line to the right.
The expected focusability of this list when pressing right on the controller would be: A, B, C and D. As we should expect. However, look at the next two images.
The ideal focusability of elements.
Focus Manager assumes that C is the next element to A.
The image on the left shows how we want the focusability top work when pressing “right” on our remote. Yet, as the FocusManager maps elements upon their position, it assumes that the next element to A is C.
To override this behavior, we must use themethod call like this:
3. Setting a “focus root”: If you want to “lock” on a certain view and its children while ignoring everything around it, you can set up a focus root.
Locking focus to a certain ViewRef as the “root”
In this example, we want to lock the focusability of elements to those inside the green rectangle. We might want to do that to restrict the user from being able to focus elements outside that green area. This is especially useful when triggering modals. To set up a focus root, we simply write some code similar to the following:
4. onFocus(or onBlur)InDescendants: This is particularly useful for lists of items when you want to apply the same onFocus or onBlur event to all elements of a list.
Bonus: There’s a Focus Debugger!
Remember when I said You.i Engine One was built for TV? Well, it has a nifty debugger with all sorts of cool options. The one place I go to every time I’m developing a feature for a TV platform is the focus debugger.
It essentially lets you understand where the focus is at the current moment, which element is the focus root, and what are the next focusable items in each direction.
I can’t express how many times this tool saved me hours of poking around and console logging.
Room for improvement
Although the FocusManager is a great tool, it does have a few drawbacks, mainly that its API is imperative. It makes playing nicely with React Native components somewhat troublesome with having to store the ref internally and then imperatively setting focus.
Here’s hoping future versions of You.i Engine One might have the capabilities to have declarative props on Refs like:
for ViewRefs to automatically setFocusRoot on that ViewRef when mounted and…
for, similarly, telling the FocusManager to focus an element upon rendering it or updating it so we don’t have to store the ref and imperatively set the focus.
What About Vanilla React Native?
At this point, you’re probably wondering why we didn’t just stick to vanilla React Native. After all, the official React Native documentation has an entry about . There is both support for Android TV and tvOS. It states that they’ve added support for React Native apps to “just work” when targeting TVs.
It’s fantastic news for development teams tasked with going cross-platform but at the time of writing this piece, there are some shortcomings.
TVs are not the main focus of React Native.
From the beginning, the core platforms targeted by RN were mobile ones. It is understandable that, while RN apps could work on TVs, there is a lot of ground to cover, and it seems to not be actively on their pipeline.
In fact, there are some key issues worth noting are:
Lack of Documentation: The material available for how to build an app for TVs using React Native is scarce. For instance, it barely references how to interact with UI elements. It mentions how touchable components and the TVEventHandler interface work for making items focusable and handling events. Yet, for someone who has never dealt with Focus Management, it is hard to get started. It is pretty much left to a long trial and error session.
Few Platforms: Official support on React Native only covers Android TV and tvOS. If we are targeting an application for several platforms (like Roku, Xbox, PlayStation, etc…), then the official support falls short.
After working with You.i Engine One and having conversations with You.i TV’s React Native team, I know that they are working hard to improve their engine. So far, we at G2i have been pretty impressed with what we are able to achieve with it. As with any tool that is pushing the edge of what it is possible, they are making sure that those little issues get covered along the road.