Как создавать адаптивные макеты в React Native

Опубликовано: 2019-10-10

Разработчики собственных приложений всегда прилагают много усилий для создания красивых приложений с богатым пользовательским интерфейсом, стабильных на всех поддерживаемых устройствах. Для iOS это означает всего несколько устройств. Для Android их может быть больше дюжины.

Когда вы разрабатываете приложение с помощью React Native, вы можете сложить эти числа, а затем умножить их на два, поскольку каждое устройство можно вращать. В этой короткой статье я постараюсь показать вам несколько инструментов и приемов, которые помогут вам справиться с огромным количеством устройств, не сойдя с ума!

1. Во-первых, ФЛЕКСБОКС

Компоненты могут управлять компоновкой с помощью алгоритма flexbox. Он создан, чтобы сохранить пропорции и согласованность макета на разных размерах экрана.

Flexbox работает очень похоже на CSS в Интернете, за несколькими исключениями, которые действительно легко освоить. Когда flex prop является положительным числом, тогда компоненты становятся гибкими и подстраиваются под экран в соответствии с их значением flex. Это означает, что flex соответствует flexGrow: [число], flexShrink: 1, flexBasis: 0.

При flex: 0 — размер соответствует высоте и ширине и негибкий.
Если flex является отрицательным числом, он также использует высоту и ширину, но если места недостаточно, он уменьшится до значений minHeight и minWidth.

Есть несколько основных свойств, предоставляемых flexbox, так что давайте рассмотрим их!
Flex описывает, как элементы делят между собой пространство. Как упоминалось выше, он ограничен одиночными номерами.

Если все элементы имеют flex: 1, они будут иметь одинаковую ширину.
В других случаях они будут делить сумму flex между собой.

Все элементы с flex: 1
Элементы с flex: 1 и flex: 2

Направление гибкости — мы можем выбрать строку или столбец (вы также можете установить обратное), чтобы задать основную ось, вдоль которой будет размещаться ваш контент. По умолчанию flexDirection настроен на столбец, а не на строку, что вызвано характером экрана на мобильных устройствах.

justifyContent — это свойство помогает вам позиционировать контент внутри контейнера вдоль главной оси. Вы можете проверить несколько возможных мест размещения ниже:

justifyContent — 3 возможных места размещения

Выравнивание элементов — работает так же, как и justifyContent, но выравнивает элементы по оси, перпендикулярной главной оси.

Flex prop действительно хорошо справляется с сохранением пропорций между элементами. Независимо от размера экрана. FlexDirection и justifyContent поддерживают согласованность поведения макета.

Есть много других реквизитов flexbox. Я коснулся лишь некоторых, чтобы показать, как они могут быть полезны.

2. Соотношение сторон

Еще одна интересная особенность — соотношение сторон (оно доступно только в React Native), которое помогает контролировать пропорции ваших элементов. Если вы знаете только одно измерение вашего элемента (ширину или высоту), он сохраняет второе измерение по отношению к тому, которое вы уже знаете.

Пример соотношения сторон

3. Размеры экрана

Здорово, когда ваши дизайны одинаковы для обеих платформ и всех типов устройств (мобильных, планшетов, iPad). Однако иногда нам приходится иметь дело с разными макетами для определенных размеров экрана или типов устройств.

По умолчанию React Native не предоставляет свойства, которые четко отвечают, какое устройство или какой размер экрана. Но есть средство от этого.

Чтобы узнать, каковы размеры экрана, мы можем использовать API Dimensions.

 import { Dimensions } from 'react-native'; const {width, height} = Dimensions.get('window');

Начиная с React Native 0.61, вы также можете использовать хук.

 const {width, height} = useWindowDimensions();

Как только мы получим ширину из поддерживаемого диапазона размеров экрана, вы можете выбрать точки останова, из которых может измениться ваш макет. Вы можете указать различные стили для компонента или скрыть некоторые части экрана. Это похоже на медиа-запросы , используемые в CSS.

 import { Text, View, Dimensions } from 'react-native'; class App extends PureComponent { constructor(props) { super(props); this.state = { width: Dimensions.get('window').width }; } render() { return ( <View> {this.state.width < 320 ? <Text>width of the past</Text> : <Text>how big is big enough?</Text>} </View> ); } }

4. Обнаружение платформы

Помимо размера экрана, вы также можете изменить макет в зависимости от запущенного приложения платформы. Для этого мы можем использовать модуль Platform.

Есть много случаев, когда его можно использовать:
В функции рендеринга компонента:

 <View> {Platform.OS === 'ios' ? <Text>Hi Apple!</Text> : <Text>Hi Android!</Text>} </View>

В стилях:

 cube: { width: Platform.OS === 'ios' ? 200 : 300, aspectRatio: 1 }

Модуль Platform предоставляет метод select, который может принимать аргументы любого типа. Благодаря такой гибкости мы можем добиться того же эффекта, что и выше, но с более чистым кодом:

 const Logo = Platform.select({ ios: () => require('Apple'), android: () => require('Android'), })(); <Logo />;

В стилях:

 import {Platform, StyleSheet} from 'react-native'; const styles = StyleSheet.create({ container: { flex: 1, ...Platform.select({ ios: { backgroundColor: 'red', }, android: { backgroundColor: 'blue', }, }), }, });

5. Ротация устройства

Многие приложения могут работать в портретном и ландшафтном режимах. Если это относится к вашему приложению, вы должны убедиться, что макет не нарушается при изменении ориентации. Как и следовало ожидать, иногда макет может резко измениться, когда вы переворачиваете устройство. Для ваших компонентов может потребоваться различный стиль в зависимости от ориентации. К сожалению, по умолчанию вращение устройства не вызывает повторную визуализацию. Вот почему это должно быть обработано вручную. У нас уже есть знания, необходимые для создания собственного, и это довольно просто!

 class RotateComponent extends PureComponent { constructor(props) { super(props); this.state = { orientation: '' }; } getOrientation = () => { if (Dimensions.get('window').width < Dimensions.get('window').height) { this.setState({ orientation: 'portrait' }); } else { this.setState({ orientation: 'landscape' }); } }; componentDidMount() { Dimensions.addEventListener('change', this.getOrientation); } render() { return ( <Text>{this.state.orientation}</Text> ); } }

Если вам нужно поддерживать изменение ориентации в приложении, рекомендуется использовать HOC для внедрения ориентации.

const HOC = WrappedComponent => class extends PureComponent { конструктор (реквизит) { super (реквизит); this.state = {ориентация: "}; } componentDidMount() { Dimensions.addEventListener('change', this.getOrientation); } getOrientation = () => { if (Dimensions.get('window').width ; } };

Это все! Вы также можете передать getOrientation в поддержку onLayout, предоставляемую компонентом View. Он срабатывает при каждом изменении макета, поэтому его следует использовать осторожно. Решение за вами!

Значок нативных приложений

Интересуетесь React Native?

Учить больше

Если вы хотите воспользоваться преимуществами ориентации в своих стилях, помните, что это должны быть встроенные стили. Мы уже знаем, как вызвать повторную визуализацию макета при повороте устройства, но стили загружаются только один раз. Вот почему стили, которые влияют на макет при повороте, должны быть встроены.

Как и следовало ожидать, огромное сообщество React Native уже предоставляет пакеты, решающие многие из упомянутых здесь проблем. Вы можете проверить это здесь или здесь, чтобы назвать лишь некоторые из них.