Карусели — важнейший инструмент для отображения нескольких элементов контента в одном месте. Допустим, вы владеете успешным интернет-магазином и хотите разместить на сайте каталог с предложениями и скидками — тогда целесообразно оформить его в виде карусели. При таком подходе список не занимает много места, тем самым улучшая дизайн UX.
Перед вами один из примечательных примеров карусели в приложении Instagram:
Создание карусели с помощью React Native включает следующие этапы:
- применение компонента React Native FlatList API для отображения элементов и настройки горизонтальной ориентации списка;
- написание дополнительного кода для показа пользовательской анимации при пролистывании слайдера;
- создание функциональности пагинации. Благодаря ей пользователь будет знать число элементов, представленных в карусели.
Как видно, разработка карусели для приложения требует много вложений времени и сил. Как же их минимизировать?
Просто воспользоваться React Native Snap Carousel. Это библиотека с открытым исходным кодом, позволяющая с легкостью создавать элементы карусели. Перечислим ее преимущества:
- включает встроенную поддержку отложенной загрузки, тем самым повышая производительность;
- предоставляет API для кастомизации — можно менять внешний вид и поведение компонента;
- содержит набор методов для управления каруселью, позволяющих пользователю передвигать элемент нажатием на кнопку или сочетанием клавиш.
С преимуществами ознакомились — займемся делом!
В данном обучающем руководстве создадим карусель изображений с кнопками навигации. По итогам работы получим результат:
Настройка проекта
Инициализация
Прежде всего, с помощью Expo создаем репозиторий React Native. Для этого выполняем следующую команду терминала:
expo init carouse-native-tutorial
Expo предлагает выбрать шаблон. На этом этапе отдаем предпочтение minimal workflow
:
Установка зависимостей
В данном проекте потребуется лишь модуль react-native-snap-carousel
для создания слайд-шоу и карусели:
npm install react-native-snap-carousel
Создание карусели
Таблица стилей
В корневой директории проекта создаем файл styles.js
, в котором будет содержаться код, необходимый для проектирования интерфейса.
В styles.js
пишем код:
import { Dimensions, StyleSheet, Platform } from 'react-native';
const { width: screenWidth } = Dimensions.get('window');
const styles = StyleSheet.create({
container: {
paddingTop: 30,
},
title: {
fontSize: 20,
},
item: {
width: '100%',
height: screenWidth - 20, //высота на 20 единиц меньше, чем ширина экрана.
},
imageContainer: {
flex: 1,
borderRadius: 5,
backgroundColor: 'lightblue',
marginBottom: Platform.select({ ios: 0, android: 1 }), //обработка ошибки отображения.
},
- Строка 3: Получаем ширину устройства пользователя через модуль
Dimensions
. - Строки 8–10: Стиль
title
меняет размер шрифта соответствующего элемента, приравнивая его к 20 единицам. - Строки 11–14: Свойство
item
отвечает за стиль элементов карусели. Здесь мы сообщаем React, что элементы слайд-шоу будут занимать всю доступную ширину. - Строки 15–20:
imageContainer
представляет стиль карусели — закругляются края с помощью свойстваborderRadius
.
Далее добавляем данный фрагмент кода в тот же файл, как показано ниже:
image: {
...StyleSheet.absoluteFillObject,
resizeMode: 'contain',
},
dotContainer: {
backgroundColor: 'rgb(230,0,0)',
},
dotStyle: {
width: 10,
height: 10,
borderRadius: 5,
backgroundColor: 'black',
},
inactiveDotStyle: {
backgroundColor: 'rgb(255,230,230)',
},
});
export default styles;
- Строки 1–4:
image
оформляет стиль элементов карусели. - Строки 5–15: Задействуем свойства
dotContainer
,dotStyle
иinactiveDotStyle
для стилизации компонента пагинации. Об этой операции поговорим чуть позже. - Строка 18: Экспортируем конфигурацию
styles
, тем самым связывая стили с проектом.
Источник данных
В проекте создаем новый файл data.js
, в котором перечисляем изображения, предназначенные для демонстрации в слайдере.
В этом файле создаем массив объектов, каждый из которых содержит поля source
, title
и description
:
const data = [
{
title: "Coral Reef",
description: "Location: Red Sea",
source:
"https://images.unsplash.com/photo-1633205719979-e47958ff6d93?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=387&q=80",
},
{
title: "Phone",
description: "iPhone 6 on the table",
source:
"https://images.unsplash.com/photo-1535303311164-664fc9ec6532?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=387&q=80",
},
{
title: "Old building",
description: "Location: Germany",
source:
"https://images.unsplash.com/photo-1623345805780-8f01f714e65f?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=387&q=80",
},
];
export default data;
Элемент карусели
В корневой директории проекта создаем файл CarouselItem.js
, ответственный за отрисовку изображений в карусели.
В CarouselItem.js
прописываем следующий код:
import React from 'react';
import { ParallaxImage } from 'react-native-snap-carousel';
import { View, Text, Pressable, SafeAreaView } from 'react-native';
import styles from './styles';
function CarouselItem({ item, index }, parallaxProps) {
return (
<Pressable onPress={() => alert('Image description:' + item.description)}>
<SafeAreaView style={styles.item}>
<ParallaxImage
source={{ uri: item.source }} /* источник изображения */
containerStyle={styles.imageContainer}
style={styles.image}
{...parallaxProps} /* передача необходимых свойств */
/>
- Строка 6:
CarouselItem
принимает свойства, содержащие важную информацию об источнике данных. - Строка 8: Модуль
Pressable
сообщает приложению, что пользователь может взаимодействовать с данным компонентом. ОбработчикonPress
информирует программу, что при нажатии пользователем на элемент React должен вывести описание изображения во всплывающем окне. - Строки 10: Компонент
ParallaxImage
показывает изображения в слайд-шоу.
Закончив с этой частью, добавляем в тот же файл код:
/* CarouselItem.js */
<Text style={styles.title} numberOfLines={2}>
{item.title}
</Text>
</SafeAreaView>
</Pressable>
);
}
export default CarouselItem;
- Строка 3: Отображаем поле изображения
title
. - Строка 10: Экспортируем элемент
CarouselItem
, что означает возможность применения этого пользовательского модуля в проекте.
Элемент карусели готов, далее переходим к слайдеру.
Настройка слайдера
Начнем с файла CustomSlider.js
, в котором пропишем код:
import * as React from 'react';
import { View, Text } from 'react-native';
export default function CustomSlider({ data }) {
console.log(data);
return (
<View>
<Text> Hello, world</Text>
</View>
);
}
- Строка 4: Компонент
CustomSlider
принимает свойствоdata
. Это будет источник данных. - Строка 5: В целях отладки выводим значение
data
.
Осталось лишь отобразить модуль CustomSlider
в UI. Для этого переходим в App.js
и меняем весь код на следующий:
import React from 'react';
import { View } from 'react-native';
import data from './data';
import CustomSlider from './CustomSlider';
// Вы можете импортировать из локальных файлов
// или любого чистого модуля javascript, доступного в npm
export default function App() {
return (
<View>
<CustomSlider data={data} />
</View>
);
}
- Строка 6: Отрисовываем
CustomSlider
и передаем источник данных в аргументdata
.
Получаем результат:
Как видно, React вывел данные в консоль. А это значит, что код работает!
Создание слайдера
В этой части займемся отрисовкой требуемых изображений в пользовательском компоненте карусели.
Для этого заменяем весь код в CustomSlider.js
на следующий:
import { Dimensions } from "react-native";
import Carousel from "react-native-snap-carousel";
import CarouselItem from "./CarouselItem";
import styles from "./styles";
const { width } = Dimensions.get("window");
export default function CustomSlider({ data }) {
const settings = {
sliderWidth: width,
sliderHeight: width,
itemWidth: width - 80,
data: data,
renderItem: CarouselItem,
hasParallaxImages: true,
};
return (
<View style={styles.container}>
<Carousel {...settings} />
</View>
);
}
- Строки 8: Объект
settings
содержит конфигурацию карусели. - Строка 13: Сообщаем React Native, что
CarouselItem
отвечает за демонстрацию элементов на стороне фронтенда. - Строка 18: Отрисовываем карусель и передаем конфигурацию.
Получаем результат:
Как видим, у нас появился прекрасно работающий слайдер. А это значит, что с кодом все в порядке!
Методы навигации
В этом разделе предоставим пользователю управление каруселью с помощью элементов Button
.
В CustomSlider.js
добавляем указанный фрагмент:
import { useRef } from "react";
import { Button } from "react-native";
const carouselRef = useRef(null);
return (
<View style={styles.container}>
<Carousel
ref={carouselRef}
/*further code... */
/>
- Строка 4: Создаем экземпляр
useRef
, предназначенный для управления слайд-шоу. - Строка 8: Компоненту
Carousel
присваиваем хукcarouselRef
и получаем возможность выполнять методы навигации.
Далее вносим следующий код в блок return
в том же файле:
//код для добавления блока return в CustomSlider.js
<View>
<Button
onPress={() => carouselRef.current.snapToItem(0)}
title="Go to start"
/>
<Button
onPress={() => carouselRef.current.snapToItem(data.length - 1)}
title="Go to end"
/>
</View>
- Строки 3–6: Метод
snapToItem
осуществляет переход к слайду с указанным индексом. В данном случае мы инструктируем React Native перенаправить пользователя к первому изображению. - Строки 7–9: При нажатии перенаправляем пользователя к последнему изображению в массиве.
Ниже представлен результат:
Пользовательские компоненты пагинации
Задача данного раздела — применить пагинацию с помощью компонента Pagination
. Этот шаг позволит улучшить дизайн интерфейса.
Сначала создаем файл CustomPaging.js
, в котором пишем код:
import * as React from 'react';
import { Pagination } from 'react-native-snap-carousel';
import styles from './styles';
export default function CustomPaging({ data, activeSlide }) {
const settings = {
dotsLength: data.length,
activeDotIndex: activeSlide,
containerStyle: styles.dotContainer,
dotStyle: styles.dotStyle,
inactiveDotStyle: styles.inactiveDotStyle,
inactiveDotOpacity: 0.4,
inactiveDotScale: 0.6,
};
return <Pagination {...settings} />;
}
- Строка 5: Данный компонент принимает 2 свойства:
data
(список изображений) иactiveSlide
(текущий индекс слайдера). - Строка 6: Переменная
settings
содержит конфигурациюPagination
. - Строка 15: Передаем конфигурацию и отображаем компонент
Pagination
.
Затем переходим в CustomSlider.js
и добавляем код:
import CustomPaging from "./CustomPaging";
//дополнительный код удален для краткости
const [slideIndex, setSlideIndex] = useState(0);
const settings = {
onSnapToItem: (index) => setSlideIndex(index), //добавляем его в переменную 'settings'.
};
return (
<View style={styles.container}>
<Carousel ref={carouselRef} {...settings} />
<CustomPaging data={data} activeSlide={slideIndex} />
</View>
);
- Строка 3: Создаем хук
slideIndex
. Исходя из имени, эта переменная указывает на текущий индекс карусели. - Строка 5: Обработчик
onSnapToItem
запускается каждый раз, когда пользователь сдвигает изображения слайд-шоу. Здесь мы инструктируем React Native обновлять переменнуюslideIndex
согласно текущему номеру слайда. - Строка 10: Отображаем компонент
CustomPaging
, а также передаем источник данных и состояниеslideIndex
в качестве свойств.
Цель достигнута!
Дополнительные ресурсы
Заключение
На основе материала статьи вы узнали, как создать простой слайдер изображений с помощью библиотеки React Native Snap Carousel. Ее документация понятна и лаконична, что позволяет без особых усилий приступить к разработке каруселей изображений.
Читайте также:
- Нативные, гибридные и web-приложения в сравнении
- Выбор лучшего фреймворка для создания мобильного приложения
- 5 лучших курсов по React Native для разработчиков мобильных приложений
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Hussain Arif: Build an Image Carousel In React Native