Fullscreen Implementation Guide

How to implement app-managed fullscreen in React Native for full StreamLayer SDK format support on iOS and Android.

The StreamLayer SDK supports multiple display formats — overlay, sidebar, L-bar, PIP, side-by-side, and frame ad. On iOS, these formats require the host app to control the video player's size and position. If a React Native app uses a video player component that triggers the native iOS fullscreen mode (AVPlayerViewController), the system takes over the layout and the SDK can only display the basic overlay format.

Android does not have this limitation — its immersive mode hides system bars without affecting the view hierarchy. However, using app-managed fullscreen on both platforms keeps the implementation consistent and ensures all SDK formats work everywhere.

Platform Behavior Summary

PlatformNative FullscreenApp-Managed Fullscreen
iOSOverlay only — sidebar, L-bar, PIP blockedAll formats work
AndroidAll formats work (immersive mode is fine)All formats work

The Recommended Approach

Since your React Native app wraps the video player and StreamLayer components in the same view hierarchy, manage fullscreen at the JavaScript level by toggling layout styles rather than calling native fullscreen APIs.

Step 1: Build a Fullscreen Container

Create a container component that expands to fill the screen when fullscreen is active. Both the video player and the StreamLayerView component should be children of this container.

import React, { useState, useCallback, useEffect } from 'react'
import { View, StyleSheet, StatusBar, Dimensions, BackHandler } from 'react-native'
import { StreamLayerView } from 'react-native-streamlayer'

const { width: SCREEN_W, height: SCREEN_H } = Dimensions.get('screen')

function VideoScreen() {
  const [isFullScreen, setIsFullScreen] = useState(false)

  // Handle Android back button to exit fullscreen
  useEffect(() => {
    const handler = BackHandler.addEventListener('hardwareBackPress', () => {
      if (isFullScreen) {
        setIsFullScreen(false)
        return true
      }
      return false
    })
    return () => handler.remove()
  }, [isFullScreen])

  const toggleFullScreen = useCallback(() => {
    setIsFullScreen(prev => !prev)
  }, [])

  return (
    <View style={isFullScreen ? styles.fullscreen : styles.windowed}>
      <StatusBar hidden={isFullScreen} />
      
      {/* Your video player */}
      <YourVideoPlayer
        style={styles.player}
        onFullScreenPress={toggleFullScreen}
      />

      {/* StreamLayer components */}
      <StreamLayerView
        style={StyleSheet.absoluteFill}
        // ... your StreamLayer configuration
      />
    </View>
  )
}

const styles = StyleSheet.create({
  windowed: {
    width: '100%',
    aspectRatio: 16 / 9,
  },
  fullscreen: {
    position: 'absolute',
    top: 0,
    left: 0,
    width: SCREEN_W,
    height: SCREEN_H,
    zIndex: 9999,
    backgroundColor: '#000',
  },
  player: {
    flex: 1,
  },
})

Step 2: Lock Orientation (Optional)

If your app supports both portrait and landscape, lock orientation to landscape when entering fullscreen. Use expo-screen-orientation (Expo) or react-native-orientation-locker.

import * as ScreenOrientation from 'expo-screen-orientation'

const toggleFullScreen = useCallback(async () => {
  if (!isFullScreen) {
    await ScreenOrientation.lockAsync(
      ScreenOrientation.OrientationLock.LANDSCAPE
    )
  } else {
    await ScreenOrientation.unlockAsync()
  }
  setIsFullScreen(prev => !prev)
}, [isFullScreen])

Step 3: Disable Native Player Fullscreen

Make sure your video player component does not trigger the native iOS AVPlayerViewController fullscreen. Most React Native video player libraries have a prop to disable this.

For react-native-theoplayer (used in StreamLayer sample apps):

<THEOplayerView
  config={{
    ...playerConfig,
    // Prevent native iOS fullscreen — let the app manage it
    fullscreenOrientationCoupling: false,
  }}
  onPlayerReady={onReady}
/>

For react-native-video:

<Video
  source={videoSource}
  // Disable native fullscreen controls
  controls={false}
  // Use custom controls with your own fullscreen toggle
/>

Common Mistakes

Letting the video player trigger native fullscreen on iOS. This is the number one cause of "sidebar doesn't appear in fullscreen." Check your player library's documentation for how to disable its built-in fullscreen behavior.

Using Dimensions.get('window') instead of Dimensions.get('screen'). On Android, window excludes the system bars. Use screen for true fullscreen dimensions.

Not handling the Android back button. In fullscreen, users expect the back button to exit fullscreen, not navigate away. Use BackHandler to intercept it.


Related