0

Overview of problem

I'm using react-native-video and on Android, when switching between an <Image /> component and a <Video /> component, the UI that I have absolutely positioned on top flashes/flickers. I'm using the video in a carousel from react-native-reanimated-carousel and am changing from an image to a video when the slide becomes the current slide. I'm doing this because there is a bug where Exoplayer (the Android implementation used by react-native-video) can't instantiate more than one or two videos at a time and also to conserve memory.

I've tested without react-native-reanimated-carousel and have included a basic example below where you can toggle between a video and image component with a button. When toggling between a image component and any other react native component, the UI doesn't flicker.

This loom video shows an example of the flicker with the carousel. The same flicker happens with the barebones example below.

https://www.loom.com/share/fc726d7ad15b427193c4081d313cf894?sid=5d3ec8ee-842e-4128-9cdf-71542e6726cc

Environment info

Library version: 5.2.1 Device: LG V50S ThinQ Android: version 10

Steps To Reproduce

  1. Load the component under "Reproducible sample code" which switches between an image and a video when pressed.
  2. Press to switch between a video and an image
  3. You'll see the components rendered on top of the video/image not to flicker ...

Reproducible sample code

import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react"
import { Animated, Image, Platform, Pressable, Text, View } from "react-native"
import { StyleSheet } from "react-native"
import Video from "react-native-video"

export default memo(function FeaturedCarouselSlide() {
  const [isVideoPausedLocal, setIsVideoPausedLocal] = useState(true)

  const onVideoLoaded = useCallback(() => {
    setIsVideoPausedLocal(false)
  }, [setIsVideoPausedLocal])

  const isPaused = isVideoPausedLocal

  const poster = "https://dd2cgqlmnwvp5.cloudfront.net/hero-carousel/Team_Hoops_Carousel.jpg"


  const [isVideo, setIsVideo] = useState(true)

  const videoFormat = Platform.OS === "android" ? "webm" : "mp4"

  return (
    <Pressable
      style={styles.container}
      onPress={() => {
        setIsVideo(!isVideo)
      }}
    >
      {isVideo ? (
        <Video
          style={[styles.video]}
          paused={isPaused}
          source={{
            uri: `https://dd2cgqlmnwvp5.cloudfront.net/hero-carousel/Team_Hoops_Carousel.${videoFormat}`,
          }}
          resizeMode={"cover"}
          poster={poster}
          posterResizeMode="cover"
          repeat
          muted
          onLoad={onVideoLoaded}
        />
      ) : (
        <View style={[styles.video, { flex: 1 }]}>
          <Image style={{ width: "100%", height: "100%", borderRadius: 16 }} source={{ uri: poster }} />
        </View>
      )}
      <View style={styles.overlay} pointerEvents="box-none">
        <View style={styles.spaceInfoContainer}>
          <Text numberOfLines={2} style={styles.title}>
            Title Here
          </Text>
          <View style={styles.creatorAndStats}>
            <Text numberOfLines={1} style={styles.name}>
              Name here
            </Text>
          </View>
        </View>
      </View>
    </Pressable>
  )
})

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    borderRadius: 16,
    backgroundColor: "transparent",
  },
  video: {
    position: "absolute",
    // width: "100%",
    // height: "100%",
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    borderRadius: 16,
  },
  overlay: {
    position: "absolute",
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    width: "100%",
    height: "100%",
    borderRadius: 16,
  },
  spaceInfoContainer: {
    width: "100%",
    position: "absolute",
    bottom: 0,
    padding: 16,
  },
  title: {
    paddingVertical: 8,
    textShadowColor: "rgba(0, 0, 0, 0.15)",
    textShadowOffset: {
      width: 0,
      height: 4,
    },
    textShadowRadius: 10,
  },
  creatorAndStats: {
    flexDirection: "row",
    justifyContent: "space-between",
  },
  name: {
    marginLeft: 4,
    maxWidth: 180, 
  },

})
bzlight
  • 1,066
  • 4
  • 17
  • 43

0 Answers0