Mettre en place une page d’accueil vidéo en React Native

Axel de Sainte Marie
7 min readFeb 14, 2020

Dans cet article nous allons lancer au démarrage de notre application, une page de lancement (Launchscreen) contenant une vidéo en plein écran. L’idée est de donner un côté très dynamique à l’application dès son entrée. Cette page fera ensuite apparaitre les options de connexion à l’application.

Avant tout de chose nous allons installer un lecteur vidéo. Nous utiliserons la bibliothèque react-native-video maintenue par React Native Community.

Pour l’installer, c’est assez classique.

yarn add react-native-video

Puis pour iOS (je suppose que vous êtes sur une version React Native 0.60 +)

cd ios && pod install && cd ..

Dans notre app, nous allons créer un fichier launchscreen.js que nous appellerons à chaque lancement de l’app. Voici sa structure initiale, dans laquelle nous avons ajouté l’import de la bibliothèque react-native-video.

import React from ‘react’;
import { StyleSheet, Text, View, SafeAreaView } from ‘react-native’;
//Lecteur video
import Video from ‘react-native-video’;
export default class Onboarding extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount() { }render() {
return (
<View style={styles.container}>
<Text>Launchsrceen</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: ‘center’,
justifyContent: ‘center’
}
});
Initialisation de notre page de lancement

Nous allons maintenant intégrer une vidéo. Vous avez deux possibilités à ce moment là : embarquer une vidéo dans votre app ou la charger depuis une URL. Dans cet exemple, je vais embarquer la vidéo pour que l’écran de lancement ne dépende pas de la qualité du réseau.

Nous allons donc embarquer notre vidéo dans notre projet. Pour cela je vais créer un dossier assets dans lequel je stockerai ma video nommée video.mp4. Dans la structure de mon application, mes composants sont stockés dans un dossier component situé au même niveau sur le dossier assets. Pour appelé ma vidéo depuis mon composant Launchscreen, il faudra donc que j’utilise le chemin ../assets/video.mp4.

Nous intégrons maintenant notre composant vidéo, avec le code suivant :

render() {
return (
<View style={styles.container}>
<Video
source={require(“../assets/video.mp4”)}
onBuffer={this.onBuffer}
onError={this.onError}
style={styles.videoPlayer} />
</View>
);
}
onBuffer = () => {
//TODO : ajouter un comportement durant le chargement de la vidéo. Particulièrement utile lors du chargement d'une vidéo en ligne.
}
onError = () => {
//TODO : ajouter un comportement si la vidéo ne se charge pas (là aussi pour les vidéos en ligne)
}
[...]
const styles = StyleSheet.create({
[...]
videoPlayer: {
width:Dimensions.get(‘screen’).width,
height:Dimensions.get(‘screen’).height
}
});

On obtient le rendu suivant (j’ai emprunté la vidéo de démo au site de la marque Boardriders).

Intégration simple du lecteur

Maintenant nous avons 2 problèmes pour avoir une page de lancement vidéo digne de ce nom.

  1. La vidéo n’est jouée qu’une fois. Or nous souhaitons qu’elle tourne en boucle jusqu’à ce que l’app soit prête à se lancer. On peut imaginer que l’app charge des données en arrière plan avant de démarrer. Pour cela nous allons ajouter l’attribut repeat et définir sa valeur à true.
  2. La vidéo n’occupe pas l’intégralité de l’écran. Pour cela, il suffit d’ajouter l’attribut resizeMode et définir sa valeur à cover, pour — comme son nom l’indique — couvrir l’intégralité de la zone défini dans le style. Ayant définit la largeur à Dimensions.get(‘screen’).width et la hauteur à Dimensions.get(‘screen’).height, nous sommes sûr de couvrir l’écran.

Voilà le code de notre composant Video mis à jour

<Video
source={require(“../assets/video.mp4”)}
onBuffer={this.onBuffer}
onError={this.onError}
style={styles.videoPlayer}
repeat={true}
resizeMode=’cover’ />

Et voilà le résultat

Notre page de lancement manque de personnalité. Nous allons ajouter le logo de l’app, et partir du principe, qu’un fois les données chargées, l’utilisateur aura le choix entre s’inscrire et se connecter.

Commençons par mettre en place le logo de l’app. L’idée est de le mettre au centre de l’écran, puis de la remonter quand les options de connexion et d’inscription apparaitront.

Continuons à rendre hommage à la marque Boardriders en prenant leur logo.

Nous allons avoir besoin de positionner notre logo au dessus de notre vidéo. Nous allons donc commencer par positionner notre vidéo en tant qu’élément de fond de notre page, grâce à l’attribut de style position et sa valeur absolute. Nous enrichissons donc le style de notre vidéo avec cet attribut.

const styles = StyleSheet.create({
[...]
videoPlayer: {
width: Dimensions.get(‘screen’).width,
height: Dimensions.get(‘screen’).height,
position:’absolute’
}
});

Maintenant nous pouvons positionner notre logo au centre de l’écran. Dans le style container de notre vue principale, nous avons déjà défini les alignements de ces éléments avec les attributs alignItems et justifyContent, tout deux définis à center. Il ne nous reste donc plus qu’à ajouter l’image du logo dans notre vue.

J’ajoute l’image logo.png dans mon dossier assets, et je l’affiche grâce à la bibliothèque Image de React Native (que je n’oublie pas d’importer dans ma page). Pour nous assurez que l’image s’affiche correctement quelque soit ses dimensions, je vous propose de lui donner un format carré de taille 260x260, et d’utiliser l’attribut resizeMode de la bibliothèque image en mettant sa valeur à contain. Cela permettra de conserver les proportions de l’image, tout en maitrisant sa largeur si c’est une image ‘paysage’ ou sa hauteur si c’est une image ‘portrait’.

Suivant l’image que vous utiliserez, vous pourriez avoir des couleurs qui se distinguent mal avec la vidéo en dessous. Pour vous assurez d’avoir un bon rendu, la bonne manière est d’ajouter un overlay, sombre si votre logo présente des couleurs claires, et vice versa. (Pour notre exemple j’utiliserai du noire avec un alpha de 70, soit la couleur #00000070).

Pour cela nous allons ajouter une vue remplissant la totalité de l’écran, en tant que ‘second’ vue de fond, entre la vidéo et le logo. Nous utiliserons de nouveau l’attribut position, pour pouvoir superposer l’ensemble de ces vues.

import { StyleSheet, View, Dimensions, Image } from ‘react-native’;[…]
export default class Launchscreen extends React.Component {
[…]
render() {
return (
<View style={styles.container}>
<Video
source={require(“../assets/video.mp4”)}
onBuffer={this.onBuffer}
onError={this.onError}
style={styles.videoPlayer}
repeat={true}
resizeMode=’cover’ />
<View
style={styles.overlay} />
<Image
source={require(‘../assets/logo.png’)}
style={styles.logo}
resizeMode='contain' />
</View>
);
}
[…]
}
const styles = StyleSheet.create({
[...]
logo: {
width:260,
height:260
},
overlay: {
width: Dimensions.get('screen').width,
height: Dimensions.get('screen').height,
position: 'absolute',
backgroundColor:'#00000070'
}
});

Et voilà la résultat.

Nous allons maintenant finaliser le scénario, qui prévoit de charger des données, puis de proposer à l’utilisateur de se connecter ou de s’inscrire.

Dans un premier temps, nous allons simuler un chargement de données en appellant la méthode getData qui lancera un timeOut de 3 secondes, avant d’afficher les options de connexion. Nous introduirons une variable dataLoaded, initialisée à false et qui basculera à true après les 3 secondes pour indiquer à l’app de basculer du chargement à l’affichage des options de connexion. Un indicateur d’activité standard fournis par la bibliothèque ActivityIndicator de React Native sera affiché pendant le chargement.

Commençons donc par mettre en place le code de “chargement”.

import { StyleSheet, View, Dimensions, Image, ActivityIndicator } from 'react-native';
[...]
export default class Launchscreen extends React.Component {
constructor(props) {
super(props);
this.state = {
dataLoaded:false
}
}
componentDidMount() {
this.getData();
}
render() {
return (
<View style={styles.container}>
<Video
source={require("../assets/video.mp4")}
onBuffer={this.onBuffer}
onError={this.onError}
style={styles.videoPlayer}
repeat={true}
resizeMode='cover' />
<View
style={styles.overlay} />
<View
style={styles.logoView}>
<Image
source={require('../assets/logo.png')}
style={styles.logo}
resizeMode='contain' />
</View>
<View style={styles.loader}>
{this.getConnectionOptionsView()}
</View>
</View>
);
}
getConnectionOptionsView = () => {
if (this.state.dataLoaded === false) {
return (
<ActivityIndicator
color='#fff'
size='large' />
);
} else {
return <View />;
}
getData = () => {
setTimeout(() => {
this.setState({ dataLoaded: true })
}, 3000);
}
[...]
}
const styles = StyleSheet.create({
[...]
loader: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logoView: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center'
}
}

Comme vous pouvez le voir, on a maintenant notre vue principale divisée en 2, avec le logo inclue dans la vue dont le style est logoView, et l’indicateur d’activité donc le style est loader. Ces deux styles ont l’attribue flex à 1, ce qui signifie qu’il se partage l’espace verticale en deux partie de même hauteur.

Pour afficher ou non l’indicateur d’activité, nous allons appeler la méthode getConnectionOptionsView à l’intérieur même du rendu. Ainsi nous pourrons en changer le contenue en fonction de la valeur de dataLoaded. Nous allons maintenant changer cette méthode, pour qu’elle ne renvoie plus une vue vide, mais bien des boutons de connexion et d’inscription.

import { StyleSheet, View, Dimensions, Image, ActivityIndicator, TouchableOpacity, Text } from ‘react-native’;
[…]
getConnectionOptionsView = () => {
if (this.state.dataLoaded === false) {
return (
<ActivityIndicator
color=’#fff’
size=’large’ />
);
} else {
return (
<View>
<TouchableOpacity
onPress={this.logIn}
style={styles.logInButton}>
<Text style={styles.logInButtonTitle}>
Se connecter
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.register}
style={styles.registerButton}>
<Text style={styles.registerButtonTitle}>
S’inscrire
</Text>
</TouchableOpacity>
</View >
);
}
}
logIn = () => {
//TODO : Ajouter la méthode de connexion
}
register = () => {
//TODO : Ajouter la méthode d’inscription
}
[...]
}
const styles = StyleSheet.create({
[...]
logInButton: {
width: 260,
height: 50,
backgroundColor: '#000000',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 20
},
logInButtonTitle: {
textAlign: 'center',
fontSize: 18,
color: '#ffff'
},
registerButton: {
width: 260,
height: 50,
backgroundColor: '#ffff',
justifyContent: 'center',
alignItems: 'center'
},
registerButtonTitle: {
textAlign: 'center',
fontSize: 18,
color: '#000000'
}
});

Et voilà nous avons fini la mise en place de notre page d’accueil !

Résultat final

--

--

Axel de Sainte Marie

Show Runner de projets mobiles. Développeur React Native et passionné par les challenges du monde mobile.