Dans cette série, vous apprendrez à utiliser React Native pour créer des mises en page couramment utilisées dans les applications mobiles. Les mises en page que vous allez créer ne seront pas fonctionnelles. Au lieu de cela, l’objectif principal de cette série est de mettre la main à la pâte dans la mise en page du contenu dans vos applications React Native.
Si vous débutez dans la mise en page d’applications React Native ou dans le style en général, consultez mon tutoriel précédent:
Pour suivre cette série, je vous mets au défi d’essayer de recréer chaque écran par vous-même avant de lire mes instructions étape par étape dans le didacticiel. Vous ne bénéficierez pas vraiment de ce tutoriel rien qu’en le lisant! Essayez d’abord avant de rechercher les réponses ici. Si vous réussissez à le faire ressembler à l’écran d’origine, comparez votre implémentation à la mienne. Alors décidez par vous-même lequel est le meilleur!
Dans cette deuxième partie de la série, vous allez créer la page de calendrier suivante:


Les applications de calendrier sont utilisées pour suivre les événements et les rendez-vous ajoutés par l’utilisateur. Vous trouverez différentes variantes dans la nature, mais la plupart d’entre elles auront les mêmes éléments qu’un calendrier physique: le mois et l’année en cours, les jours du mois et les événements ou rendez-vous ajoutés par l’utilisateur.
Voici quelques exemples de ce type de mise en page:




Configuration du projet
La première étape, bien sûr, est de mettre en place un nouveau projet React Native:
react-native init react-native-common-screens
Une fois le projet configuré, ouvrez le index.android.js
et remplacez le code par défaut par ce qui suit:
import React, { Component } from 'react'; import { AppRegistry } from 'react-native'; import Calendar from './src/pages/Calendar'; export default class ReactNativeCommonScreens extends Component { render() { return ( <Calendar /> ); } } AppRegistry.registerComponent('ReactNativeCommonScreens', () => ReactNativeCommonScreens);
Créer un src/pages
dossier et créez un Calendar.js
fichier à l’intérieur.
Vous aurez également besoin du react-native-vector-icons
paquet. Ceci est spécifiquement utilisé pour les icônes de navigation ainsi que pour les autres icônes qui seront nécessaires dans la page.
npm install --save react-native-vector-icons
Ouvrez le android/app/build.gradle
fichier et ajoutez une référence au package:
dependencies { //rest of the dependencies are here at the top compile project(':react-native-vector-icons') //add this }
Faites de même avec le android/settings.gradle
fichier en ajoutant ce qui suit en bas:
include ':react-native-vector-icons' project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
Ouvert android/app/src/main/java/com/react-native-common-screens/MainApplication.java
et importez le package:
import java.util.Arrays; import java.util.List; import com.oblador.vectoricons.VectorIconsPackage; //add this
Enfin, initialisez le package:
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new VectorIconsPackage() //add this ); }
Création de la page de calendrier
Bon, maintenant que vous avez essayé de coder la mise en page vous-même (pas de triche, non?), Je vais vous montrer comment j’ai construit mon implémentation.
Au début, je pensais que ce serait le plus difficile à mettre en œuvre, mais croyez-moi, ce n’est vraiment pas si compliqué tant que vous connaissez déjà les bases. Il existe ici quelques possibilités d’utiliser du code JavaScript pour faciliter le rendu.
Commencez par inclure tous les composants et packages dont vous aurez besoin:
import React, { Component } from 'react'; import { StyleSheet, Text, View, ScrollView } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; import { range } from 'lodash'; import Button from '../components/Button';
Cette fois, il y a un nouveau package que vous n’avez pas encore installé, et c’est lodash. Vous n’aurez pas vraiment besoin de toute la bibliothèque lodash, juste le range
fonction. Ceci est utilisé pour générer un tableau de nombres basé sur une plage spécifique. Vous pouvez installer uniquement cette fonction en exécutant npm install --save lodash.range
sur votre terminal.
Ajoutez le code standard pour créer des pages:
export default class Calendar extends Component { render() { return ( <ScrollView style={styles.container}> ... </ScrollView> ); } } const styles = StyleSheet.create({ container: { flex: 1 } });
L’en-tête comporte trois éléments: le bouton pour revenir à la page précédente, le titre de la page en cours et le texte montrant une représentation conviviale de la date actuellement sélectionnée.
<View style={styles.header}> <Button noDefaultStyles={true} onPress={this.press.bind(this)} styles={{button: styles.header_item}} > <View style={styles.header_button}> <Icon name="chevron-left" size={30} color="#FFF" /> <Text style={[styles.header_text]}> Menu</Text> </View> </Button> <View style={styles.header_item}> <Text style={[styles.header_text, styles.text_center, styles.bold_text]}>Calendar</Text> </View> <View style={styles.header_item}> <Text style={[styles.header_text, styles.text_right]}>Today</Text> </View> </View>


header
a un flexDirection
de row
pour que chacun header_item
est empilé horizontalement. Le même flex
valeur est attribuée à chacun d’eux afin qu’ils consomment des quantités égales d’espace. text_center
et text_right
sont utilisés pour aligner le texte à l’intérieur de ceux header_item
s au centre et à droite. Cela est fait parce que, par défaut, ils sont alignés sur le côté le plus à gauche de leur conteneur.
header: { backgroundColor: '#329BCB', flexDirection: 'row', padding: 20 }, header_item: { flex: 1 }, header_button: { flexDirection: 'row' }, text_center: { textAlign: 'center' }, text_right: { textAlign: 'right' }, header_text: { color: '#fff', fontSize: 20 }, bold_text: { fontWeight: 'bold' },
Une fois les styles ajoutés, cela devrait maintenant ressembler à ceci:


Vient ensuite le calendrier proprement dit, divisé en trois parties: l’en-tête, les jours de la semaine et les jours du calendrier:
<View> <View style={styles.calendar_header}> ... </View> <View style={styles.calendar_weekdays}> ... </View> <View style={styles.calendar_days}> ... </View> </View>
L’en-tête du calendrier permet à l’utilisateur de changer l’année et le mois.
Il y a au moins deux façons de mettre cela en œuvre. La première méthode consiste à traiter chaque élément comme un élément unique et à appliquer justifyContent: 'space-between'
à son contenant. La deuxième méthode consiste à regrouper tous les éléments qui ont à voir avec l’année et à regrouper ceux qui ont à voir avec le mois.
La deuxième méthode est celle qui est appliquée ci-dessous. Sémantiquement parlant, cela a beaucoup plus de sens car le bouton de navigation en arrière d’une année, l’année elle-même et le bouton de navigation vers l’avant sont tous liés, vous pouvez donc les traiter comme une seule chose en les mettant dans le même conteneur. La même chose est vraie avec les contrôles du mois.
<View style={styles.calendar_header}> <View style={styles.calendar_header_item}> <Button noDefaultStyles={true} onPress={this.press.bind(this)} > <Icon name="chevron-left" size={18} color="#333" /> </Button> <Text style={styles.calendar_header_text}>2013</Text> <Button noDefaultStyles={true} onPress={this.press.bind(this)} > <Icon name="chevron-right" size={18} color="#333" /> </Button> </View> <View style={styles.calendar_header_item}> <Button noDefaultStyles={true} onPress={this.press.bind(this)} > <Icon name="chevron-left" size={18} color="#333" /> </Button> <Text style={styles.calendar_header_text}>November</Text> <Button noDefaultStyles={true} onPress={this.press.bind(this)} > <Icon name="chevron-right" size={18} color="#333" /> </Button> </View> </View>


De là, vous pouvez appliquer la même technique à ces deux groupes de composants dans la même ligne. Pour ajouter des espaces entre les deux boutons (arrière et avant) et l’étiquette, nous utilisons justifyContent: 'space-between'
. Nous utilisons alignItems: 'center'
pour pousser tous les éléments à l’intérieur vers le centre. Enfin, nous ajoutons un rembourrage gauche et droit pour ajouter plus d’espace entre les deux groupes.
calendar_header: { flexDirection: 'row' }, calendar_header_item: { flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingTop: 20, paddingRight: 40, paddingLeft: 40 }, calendar_header_text: { fontWeight: 'bold', fontSize: 20 },


Viennent ensuite les jours de la semaine. Nous utilisons une fonction pour les rendre car il est préférable d’utiliser du code JavaScript pour rendre tous les éléments.
<View style={styles.calendar_weekdays}> { this.renderWeekDays() } </View>
Donc au lieu d’en avoir sept View
ou Text
composants rendant chaque jour de la semaine, vous pouvez simplement avoir un tableau contenant les jours de la semaine. Vous pouvez ensuite parcourir ces jours en utilisant le Array.map()
fonction. Pour chaque itération, rendez un Text
composant qui montre le jour.
renderWeekDays() { let weekdays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; return weekdays.map((day) => { return ( <Text key={day} style={styles.calendar_weekdays_text}>{day.toUpperCase()}</Text> ); }); }
Notez que dans le code ci-dessus, le toUpperCase()
La fonction est utilisée pour convertir toutes les lettres de chaque jour en majuscules. React Native n’est pas fourni avec text-transform
Propriété CSS, c’est donc le seul moyen d’obtenir des lettres majuscules en dehors de l’utilisation manuelle de chaînes majuscules.


Voici le style de l’en-tête du calendrier:
calendar_weekdays_text: { flex: 1, color: '#C0C0C0', textAlign: 'center' },


Les jours calendaires utilisent également une fonction de rendu des jours:
<View style={styles.calendar_days}> { this.renderWeeks() } </View>
le renderWeeks()
utilise la fonction range()
fonction dans lodash pour générer un tableau contenant les jours du mois dernier et les jours du mois en cours. Ces deux tableaux sont ensuite fusionnés.
Cependant, vous ne pouvez pas utiliser directement le tableau résultant comme source de données pour les jours calendaires. C’est parce que si vous parcourez simplement les éléments et affichez un Text
composante pour chaque jour, il n’y aura aucune distinction entre chaque semaine. Vous savez déjà que pour intégrer chaque jour calendaire, vous devez postuler flexDirection: 'row'
à son contenant. Donc, en l’appliquant à un seul conteneur, tous les jours calendaires seraient placés sur une seule ligne.
Cela signifie que vous devez avoir un conteneur séparé pour chaque semaine. La question est de savoir comment. Encore une fois, il existe au moins deux façons d’y parvenir.
La première méthode consiste à avoir une variable stockant le nombre de jours actuellement générés, puis à ajouter une instruction conditionnelle qui rendra une ouverture <View>
chaque fois que la variable contient et une clôture
</View>
à chaque fois que c’est 7
. Une fois que c’est 7
, réinitialisez-le à . C’est la méthode la plus simple.
Mais je vais utiliser une méthode différente ici. Sous le getWeeksArray()
fonction est utilisée pour l’implémenter. Cette fonction accepte le tableau de jours et les regroupe en tableaux contenant chacun sept jours. À partir de là, vous pouvez parcourir chacun de ces tableaux pour rendre le conteneur de la semaine. Ensuite, pour chaque itération, vous parcourez à nouveau les jours de la semaine pour afficher les jours. C’est ce que le renderDays()
fonction fait.
renderWeeks() { let past_month_days = range(27, 31); let this_month_days = range(1, 30); let days = past_month_days.concat(past_month_days, this_month_days); let grouped_days = this.getWeeksArray(days); return grouped_days.map((week_days, index) => { return ( <View key={index} style={styles.week_days}> { this.renderDays(week_days) } </View> ); }); }
Voici le getWeeksArray()
fonction:
getWeeksArray(days) { var weeks_r = []; var seven_days = []; var count = 0; days.forEach((day) => { count += 1; seven_days.push(day); if(count == 7){ weeks_r.push(seven_days) count = 0; seven_days = []; } }); return weeks_r; }
Et voici le renderDays()
fonction:
renderDays(week_days) { return week_days.map((day, index) => { return ( <Button label={day} key={index} onPress={this.press.bind(this)} styles={{button: styles.day, label: styles.day_text}} noDefaultStyles={true} /> ); }); }


Ajoutez le style pour chaque semaine (week_days
) et jour (day
et day_text
):
week_days: { flexDirection: 'row' }, day: { flex: 1, backgroundColor: '#F5F5F5', padding: 17, margin: 2 }, day_text: { textAlign: 'center', color: '#A9A9A9', fontSize: 25 },


Vient ensuite la note ajoutée par l’utilisateur pour le jour actuellement sélectionné et la date et l’heure sélectionnées. Encore une fois, il est préférable de regrouper les éléments en fonction de leur objectif plutôt que de la manière dont ils sont placés dans la page. Certes, tous ces éléments sont liés, nous les placerons donc dans le même conteneur. Mais en y regardant de plus près, vous verrez que vous pouvez les regrouper davantage: la note réelle et la date sélectionnée. Dans cet esprit, voici le balisage avec lequel vous vous retrouverez:
<View style={styles.notes}> <View style={styles.notes_notes}> <Text style={styles.notes_text}>Riding my bike around the neighborhood.</Text> </View> <View style={[styles.notes_selected_date]}> <Text style={styles.small_text}>8:23 PM</Text> <Text style={styles.big_text}>14</Text> <View style={styles.inline}> <Icon name="bicycle" size={20} color="#CCC" /> <Text style={styles.small_text}> THURSDAY</Text> </View> </View> </View>


La date sélectionnée occupe moins d’espace que la note, vous devez donc appliquer un plus grand flex
valeur aux notes. flex: 3
et flex: 1
sont utilisés dans ce cas, ce qui signifie que les billets consomment 3/4 de l’espace disponible et la date sélectionnée en consomme 1/4. Vous pouvez également utiliser des décimales (0.75
et 0.25
) si cela a plus de sens pour vous. L’important est de choisir une norme et de s’y tenir. alignItems: 'flex-end'
est utilisé sur notes_selected_date
afin que tous ses enfants soient alignés à droite. Cela est nécessaire car, par défaut, ils sont alignés à gauche.
notes: { marginTop: 10, padding: 20, borderColor: '#F5F5F5', borderTopWidth: 1, borderBottomWidth: 1, flexDirection: 'row', backgroundColor: '#FAFAFA' }, notes_notes: { flex: 3 }, notes_text: { fontSize: 18 }, notes_selected_date: { flex: 1, alignItems: 'flex-end', flexDirection: 'column' }, small_text: { fontSize: 15 }, big_text: { fontSize: 50, fontWeight: 'bold' }, inline: { flexDirection: 'row' },


Enfin, nous ajoutons les journaux, qui sont très similaires à ceux du tutoriel précédent, je vous laisse donc le soin de déterminer comment la mise en page est réalisée!
<View style={styles.logs}> <View> <Text style={styles.log_text}>Create New Entry</Text> <Text style={styles.log_subtext}>On Thursday, November 14</Text> </View> <Button noDefaultStyles={true} onPress={this.press.bind(this)} > <Icon name="chevron-right" size={30} color="#CCC" /> </Button> </View>
Voici les styles:
logs: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 20, borderColor: '#F5F5F5', borderBottomWidth: 1 }, log_text: { fontSize: 25 }, log_subtext: { fontSize: 18 }
Conclusion
C’est ça! Dans ce didacticiel, vous avez créé une page de calendrier. Nous avons créé une belle mise en page de calendrier pour une application et je vous ai montré comment le code JavaScript peut être utilisé pour compenser certaines des limitations de Flexbox.
Comme vous l’avez vu, nous avions besoin d’un moyen de limiter le nombre de jours consécutifs à sept jours seulement. Flexbox n’a pas de moyen de spécifier cela, nous avons donc utilisé JavaScript pour reconstruire le tableau original de jours de telle sorte qu’ils soient divisés en groupes de sept jours chacun. À partir de là, tout ce que nous avions à faire était d’envelopper chaque groupe dans un View
puis appliquez flexDirection: 'row'
pour que chacun d’eux soit rendu dans sa propre rangée.
Dans un prochain didacticiel, vous apprendrez à implémenter la mise en page couramment utilisée dans les pages de la galerie. En attendant, consultez certains de nos autres tutoriels sur React Native et Flexbox.
-
Commencez avec React Native
-
Premiers pas avec les mises en page natives React
-
Créez une application sociale avec React Native
-
Comment créer une navigation par bandes avec Flexbox
-
Animez votre application native React
-
Une introduction au module CSS Flexbox
Laisser un commentaire