Из этой серии вы узнаете, как использовать React Native для создания макетов страниц, обычно используемых в мобильных приложениях. Макеты, которые вы создаете, не будут функциональными — вместо этого, основной целью этой серии является то, что вы можете запачкать руки при размещении контента в ваших приложениях React Native.
Если вы новичок в разработке приложений React Native или стилей в целом, посмотрите мой предыдущий учебник:
Чтобы следовать этой серии, я призываю вас сначала попытаться воссоздать каждый экран самостоятельно, прежде чем вы прочитаете мои пошаговые инструкции в руководстве. Вы действительно не получите много пользы от этого урока, просто прочитав его! Попробуйте сначала, прежде чем искать ответы здесь. Если вам удалось сделать его похожим на исходный экран, сравните вашу реализацию с моей. Тогда решите для себя, какой из них лучше!
В этом третьем посте серии вы создадите следующую страницу фотогалереи:
Галереи часто используются для отображения коллекции соответствующего контента таким образом, что представлена только необходимая информация. В большинстве случаев это фото, заголовок и другая важная информация.
Вот пара примеров этого типа макета, используемого в дикой природе:
Настройка проекта
Первым шагом, конечно же, является создание нового проекта React Native:
1
|
react-native init react-native-common-screens
|
После настройки проекта откройте файл index.android.js
и замените код по умолчанию следующим index.android.js
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
import React, { Component } from ‘react’;
import {
AppRegistry
} from ‘react-native’;
import Gallery from ‘./src/pages/Gallery’;
export default class ReactNativeCommonScreens extends Component {
render() {
return (
<Gallery />
);
}
}
AppRegistry.registerComponent(‘ReactNativeCommonScreens’, () => ReactNativeCommonScreens);
|
Создайте папку src/pages
и создайте в Gallery.js
файл Gallery.js
.
Вам также понадобится пакет react-native-vector-icons
. Это специально используется для иконок в нижнем колонтитуле.
1
|
npm install —save react-native-vector-icons
|
Откройте файл android/app/build.gradle
и добавьте ссылку на пакет:
1
2
3
4
|
dependencies {
//rest of the dependencies are here at the top
compile project(‘:react-native-vector-icons’) //add this
}
|
Сделайте то же самое с файлом android/settings.gradle
, добавив следующее внизу:
1
2
|
include ‘:react-native-vector-icons’
project(‘:react-native-vector-icons’).projectDir = new File(rootProject.projectDir, ‘../node_modules/react-native-vector-icons/android’)
|
Откройте android/app/src/main/java/com/react-native-common-screens/MainApplication.java
и импортируйте пакет:
1
2
3
4
|
import java.util.Arrays;
import java.util.List;
import com.oblador.vectoricons.VectorIconsPackage;
|
Наконец, инициализируйте пакет:
1
2
3
4
5
6
7
|
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new VectorIconsPackage() //add this
);
}
|
Создание страницы галереи
Хорошо, теперь, когда вы попытались кодировать макет самостоятельно (без обмана, верно?), Я покажу вам, как я построил свою реализацию.
В отличие от предыдущих двух страниц, страница галереи нуждается в некоторых изображениях, которые будут служить ее основным содержанием. Вы можете перейти в Google и искать изображения или загрузить изображения из репозитория GitHub . Все изображения, которые я использовал, помечены для повторного использования их соответствующими владельцами, поэтому вы можете свободно использовать их, если хотите. Когда у вас есть изображения, сохраните их в каталоге src/images
. Благодаря тому, как будут выкладываться изображения, все они должны иметь одинаковые размеры.
Начните с создания файла ( src/pages/Gallery.js
) и добавьте стандартный шаблон:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
import React, { Component } from ‘react’;
import {
StyleSheet,
View,
ScrollView,
Image,
} from ‘react-native’;
import Icon from ‘react-native-vector-icons/FontAwesome’;
import Button from ‘../components/Button’;
export default class Gallery extends Component {
…
}
|
Эта страница нуждается в функции constructor()
где вы определяете пути к изображениям, которые вы хотите использовать. В React Native вы обращаетесь к изображениям, находящимся в вашем рабочем каталоге, так как вы требуете их, как и в случае с модулем JavaScript. Также важно отметить, что вы не можете иметь динамически сгенерированные пути к изображениям, поэтому вы должны указать фактический путь вручную.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
constructor(props) {
super(props);
this.state = {
photos: [
{
label: ‘beach’,
src: require(‘../images/beach.jpg’)
},
{
label: ‘bridge’,
src: require(‘../images/bridge.jpg’)
},
{
label: ‘fields’,
src: require(‘../images/fields.jpg’)
},
{
label: ‘mountains’,
src: require(‘../images/mountains.jpg’)
},
{
label: ‘sunflower’,
src: require(‘../images/sunflower.jpg’)
},
{
label: ‘sunset’,
src: require(‘../images/sunset.jpg’)
},
{
label: ‘lake’,
src: require(‘../images/lake.jpg’)
},
{
label: ‘nature’,
src: require(‘../images/nature.jpg’)
},
{
label: ‘pink’,
src: require(‘../images/pink.jpg’)
},
{
label: ‘rails’,
src: require(‘../images/rails.jpg’)
},
]
};
}
|
Вам не нужно определять их в состоянии, так как значения не изменятся. На самом деле вы можете определить их в отдельном файле, импортировать, назначить для переменной, а затем использовать ее напрямую. Но ради простоты я решил просто все поставить в состояние.
Внутри метода render()
вы ScrollView
тенденцию оборачивать все внутри компонента ScrollView
, потому что компонент вкладки в самой нижней части экрана должен иметь фиксированную позицию. Это означает, что даже если фотографии превышают доступную высоту, вкладки должны оставаться на месте. Чтобы достичь этого, используйте компонент View
чтобы обернуть все и только обернуть коллекцию фотографий в ScrollView
. Это позволяет применять прокрутку только к контейнеру из коллекции фотографий:
01
02
03
04
05
06
07
08
09
10
|
render() {
return (
<View style={styles.container}>
<ScrollView style={styles.gallery}>
{ this.renderGallery() }
</ScrollView>
<View style={styles.tabs}>
</View>
);
}
|
Теперь вы можете начать видеть образец здесь. Каждый раз, когда вам нужно использовать код JavaScript внутри функции render()
, вы должны создать отдельную функцию для хранения этого кода вместо того, чтобы помещать его непосредственно в функцию render()
. Это делает его стройным и чистым.
Теперь давайте перейдем к стилю. Несмотря на то, что ScrollView
на этот раз не используется для ScrollView
всего ScrollView
, важно отметить, что вам все равно необходимо указать flex: 1
для основного контейнера, чтобы он занимал все доступное пространство.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
container: {
flex: 1,
flexDirection: ‘column’
},
gallery: {
flexDirection: ‘column’
},
tabs: {
flexDirection: ‘row’,
backgroundColor: ‘#333’,
padding: 20
},
tab: {
flex: 1
},
icon: {
textAlign: ‘center’
},
|
Функция renderGallery()
очень похожа на renderWeeks()
которую мы использовали в предыдущем уроке, который мы использовали для визуализации страницы календаря. Если вы хотите узнать больше о том, как это работает, прочитайте предыдущее руководство на страницах календаря . Что вам нужно знать, так это то, что resizeMode
применяется к Image
. В этом случае он устанавливается на cover
, которое заставляет изображение занимать все доступное пространство его контейнера, сохраняя при этом его соотношение сторон. Это приводит к тому, что изображение становится немного взорванным для устройств с большими экранами, если исходное изображение меньше.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
renderGallery() {
var count = 0;
var previous_item = »;
var pairs = this.getPairsArray(this.state.photos);
return pairs.map((item, index) => {
return (
<View style={styles.item} key={index}>
<Image
resizeMode={Image.resizeMode.cover}
style={styles.photo}
source={item[0].src} />
<Image
resizeMode={Image.resizeMode.cover}
style={styles.photo}
source={item[1].src} />
</View>
);
});
}
|
Вот getPairsArray()
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
getPairsArray(photos) {
var pairs_r = [];
var pairs = [];
var count = 0;
photos.forEach((item) => {
count += 1;
pairs.push(item);
if(count == 2){
pairs_r.push(pairs)
count = 0;
pairs = [];
}
});
return pairs_r;
}
|
Наконец, вот стиль для каждой строки ( item
) и фотографии ( photo
). Обратите внимание на использование flex: 1
на фактической фотографии. Это сделано потому, что сам компонент Image
является своим собственным контейнером. Вы хотите, чтобы сам контейнер занимал половину доступного пространства для каждой строки — вот почему следует назначить свойство flex
. Если этого не сделать, будут использованы только те размеры, которые необходимы для фотографии, а добавленный ранее режим resizeMode
даже не даст эффекта.
1
2
3
4
5
6
7
|
item: {
flex: 1,
flexDirection: ‘row’,
},
photo: {
flex: 1
}
|
Вывод
Это оно! Из этого урока вы узнали, как реализовать макет страницы галереи. Мы сосредоточились на том, как обращаться с изображениями, когда речь идет о планировании ваших приложений React Native. Часто вам нужно использовать комбинацию flex
и resizeMode
, чтобы заставить изображения resizeMode
так, как вы хотите. Как мое решение сравнилось с вашим? Дайте нам знать в дискуссионном форуме ниже.
В следующем уроке вы узнаете, как реализовать макет, обычно используемый в новостных приложениях. А пока посмотрите другие наши учебники по React Native и Flexbox!