Details screenExploring the Details screen

Implementing the Details Screen in TV Apps

🎬

The details screen is probably the last screen your user will see before watchin the movie in any content-focused TV app. Because of this it’s important this screen provides users with clear information about a selected content and includes the primary call-to-action (like “Watch Now”).

Component Structure

🏗️
import { Stack, useLocalSearchParams, useRouter } from 'expo-router';
import { StyleSheet, View, Image, Pressable, Text } from 'react-native';
import { SpatialNavigationFocusableView, SpatialNavigationRoot } from 'react-tv-space-navigation';
import { scaledPixels } from '@/hooks/useScale';
 
export default function DetailsScreen() {
  const { title, description, headerImage } = useLocalSearchParams();
  const styles = useDetailsStyles();
  const router = useRouter();
  const isFocused = useIsFocused();
 
  return (
    <SpatialNavigationRoot isActive={isFocused}>
      <Stack.Screen options={{ headerShown: false }} />
      <View style={styles.container}>
        <Image source={headerImage} style={styles.backgroundImage} />
        <View style={styles.contentContainer}>
          <View style={styles.topContent}>
            {/* Title and Description */}
          </View>
          <View style={styles.bottomContent}>
            {/* Crew Information and Watch Button */}
          </View>
        </View>
      </View>
    </SpatialNavigationRoot>
  );
}

Key Features:

  • Uses useLocalSearchParams for screen data
  • Implements SpatialNavigationRoot for focus management
  • Organizes content in top and bottom sections

Implementation Steps

1. Background Image Setup

🖼️
<Image source={headerImage} style={styles.backgroundImage} />
 
// Styling
backgroundImage: {
  position: 'absolute',
  width: '100%',
  height: '100%',
  opacity: 0.3,
},

The background image uses low opacity to ensure content readability.

2. Title and Description Layout

📝
<View style={styles.topContent}>
  <Text style={styles.title}>{title}</Text>
  <Text style={styles.description}>{description}</Text>
</View>
 
// Styling
title: {
  fontSize: scaledPixels(48),
  fontWeight: 'bold',
  color: '#fff',
  marginBottom: scaledPixels(20),
  textShadowColor: 'rgba(0, 0, 0, 0.75)',
  textShadowOffset: { width: -1, height: 1 },
  textShadowRadius: 10,
},
description: {
  fontSize: scaledPixels(24),
  color: '#fff',
  marginBottom: scaledPixels(20),
  width: '60%',
  lineHeight: scaledPixels(32),
},

Note the use of scaledPixels for responsive text sizing.

3. Crew Information Section

👥
<View style={styles.crewContainer}>
  <View style={styles.crewMember}>
    <Text style={styles.crewRole}>Director</Text>
    <Text style={styles.crewName}>Chris Traganos</Text>
  </View>
  {/* Additional crew members */}
</View>
 
// Styling
crewContainer: {
  flexDirection: 'row',
  flexWrap: 'wrap',
  marginBottom: scaledPixels(30),
},
crewMember: {
  marginRight: scaledPixels(40),
  marginBottom: scaledPixels(15),
},

Creates a horizontal layout for crew information.

4. Watch Button Implementation

▶️
<SpatialNavigationFocusableView onSelect={() => {router.push('/player')}}>
  {({ isFocused }) => (
    <Pressable
      style={[styles.watchButton, isFocused && styles.watchButtonFocused]}
    >
      <Text style={isFocused ? styles.watchButtonTextFocused : styles.watchButtonText}>
        Watch now
      </Text>
    </Pressable>
  )}
</SpatialNavigationFocusableView>

Implements focus states for remote control navigation.

Check the Focus Management

🎯

The detail screen follow our specific focus management:

  • Wrapping screen in SpatialNavigationRoot
  • Using SpatialNavigationFocusableView for interactive elements

Implementation Exercise

💻

Try this exercise to enhance the details screen:

Add a focusable back button

You can use what you learned up to now