Focus ManagementIntroduction

Introduction to Focus Management in TV Apps

Understanding Focus Management

Focus management is an important aspect of TV app development that fundamentally differs from mobile or web applications. While mobile apps rely on touch interactions and web apps use mouse clicks this doesn’t usually happen on the distant screen of a TV. The user needs a way to exactly know which element of the UI is selected and where to move the interaction.

Key Concepts

On TV, users navigate with a remote control using directional buttons - up, down, left, and right. Because of this, TV interfaces must follow strict focus management rules:

Single Focus Point: Only one element can be focused at a time. This focus point represents where user interaction will occur. Directional Navigation: Users move the focus between elements using directional buttons on their remote. Focus moves to the closest element in the pressed direction. Visual Feedback: The focused element must stand out clearly through visual changes like scaling, highlighting, or borders, making it immediately obvious where the focus is on screen. Predictable Movement: Focus must move logically and consistently. When users press a direction, they should be able to predict where the focus will land based on the screen layout.

These principles ensure users can navigate TV apps efficiently and intuitively despite being limited to remote control input.

Managing Focus is not easy, and for our project we used a library capable of help us.

React TV Space Navigation Library

React TV Space Navigation is a library designed to solve the challenges of spatial navigation in TV applications. It provides a cross-platform solution that works consistently across AndroidTV, tvOS, and web TV devices.

Library Overview

The library is built on LRUD (Left-Right-Up-Down), a UI-agnostic library that handles the core logic of spatial navigation. React TV Space Navigation wraps this core functionality in a React-friendly API.

Key Features

  1. Cross-Platform Compatibility: Works consistently across different TV platforms
  2. Declarative API: Simple, component-based approach to defining navigation
  3. Scroll Support: Built-in handling for scrollable content
  4. Focus Management: Automated focus handling and movement
  5. Customizable Behavior: Flexible configuration for different navigation needs

Core Components

// Main components provided by the library
import { 
  SpatialNavigationRoot,          // Root container for navigation
  SpatialNavigationFocusableView, // Makes elements focusable
  SpatialNavigationScrollView,    // Handles scrollable content
  SpatialNavigationView,          // Directional container
  DefaultFocus                    // Sets default focus target
} from 'react-tv-space-navigation';

Implementation in Our Project

Let’s examine how React TV Space Navigation is implemented in our TV app.

Basic Structure

import { SpatialNavigationRoot, SpatialNavigationFocusableView } from 'react-tv-space-navigation';
 
export default function Screen() {
  const isFocused = useIsFocused();
  const isActive = isFocused && !isMenuOpen;
 
  return (
    <SpatialNavigationRoot isActive={isActive}>
      <View style={styles.container}>
        <ContentSection />
      </View>
    </SpatialNavigationRoot>
  );
}

Making Elements Focusable

const FocusableCard = ({ title, onSelect }) => (
  <SpatialNavigationFocusableView onSelect={onSelect}>
    {({ isFocused }) => (
      <View style={[styles.card, isFocused && styles.cardFocused]}>
        <Text style={styles.cardTitle}>{title}</Text>
      </View>
    )}
  </SpatialNavigationFocusableView>
);

Handling Scrollable Content

const ContentRow = ({ items }) => (
  <SpatialNavigationScrollView horizontal>
    <SpatialNavigationView direction="horizontal">
      {items.map((item) => (
        <FocusableCard
          key={item.id}
          title={item.title}
          onSelect={() => handleItemSelect(item)}
        />
      ))}
    </SpatialNavigationView>
  </SpatialNavigationScrollView>
);

Managing Default Focus

const ContentSection = () => (
  <DefaultFocus>
    <SpatialNavigationView>
      {/* First focusable item will receive default focus */}
      <FocusableCard title="First Item" />
      {/* Other cards */}
    </SpatialNavigationView>
  </DefaultFocus>
);

Conclusion

The next sections will dive deeper into specific implementation patterns of React TV Space navigation usage in our project.