React Native: побеждаем lineHeight кроссплатформенно

React Native вызывает споры, но он определённо хорош двумя вещами: быстрый старт для веб-разрабов и кроссплатформенностью, то есть, пишете один раз - получаете приложение для Android и iOS сразу же.

Конечно, иногда требуются доработки под определённую платформу, но, в целом, вы можете быть уверены, что результат будет плюс-минус одинаковым.

Проблемы начинаются вместе с кастомизацией. Мало того, что добавить свой шрифт в RN-приложение непросто, ещё и начинаются проблемы с тем, как текст с этим шрифтом выглядит.

А как вообще использовать свой шрифт?

Про добавление самого файла шрифта есть много публикаций в Интернете (к примеру, хорошо написано вот тут).

Но просто добавить файлы недостаточно. Здесь стоит сказать следующее: React Native немного ломает привычный флоу работы с HTML и CSS, что вполне логично. Лично мне это показалось диким и непривычным, но, чем раньше вы поймёте, что иначе никак - тем лучше :)

Самый простой вариант - написать свой компонент, наследуемый от Text. Я в своём проекте использую библиотеку компонентов Native Base, так что покажу на её примере.

Итак, я добавил файлы шрифта Gotham Pro, теперь время написать компонент:

import React from 'react'
import { Text } from 'native-base'

export const MyText = (props) => {
  const style = {
    fontFamily: 'GothamPro',
  }
  return <Text {...props} style={style} />
}

Смотрим - шрифт правильный. Однако в дальнейшей работе вы увидите, что высота строки на iOS и Android различается.

Источник: https://stackoverflow.com/questions/47925577/different-lineheight-on-android-ios-using-react-native

Исправляем высоту строки

Это происходит из-за того, что дефолтные величины, используемые для настройки таких свойств, как lineHeight, на iOS и Android с виду одинаковые, но работают чуть-чуть по-разному. Значит, нам нужно явно указать, какой lineHeight должен использоваться сейчас.

Обновим компонент:

import React from 'react'
import { Text } from 'native-base'

export const MyText = (props) => {
  const fontSize = props?.style?.fontSize ?? 16
  const lineHeight = props?.style?.lineHeight ?? fontSize
  const style = {
    ...props.style,
    fontFamily: 'GothamPro',
    fontSize,
    lineHeight
  }
  return <Text {...props} style={style} />
}

Минуточку, зачем fontSize? К сожалению, без этого не обойтись. Нам нужно знать, какая должна быть высота строки, а для этого нужно знать, какой размер шрифта у текста. Если никакой - то мы должны понимать, какой размер у нас по-умолчанию.

Этот компонент позволяет нам “пробрасывать” стили, а также вручную управлять высотой строки и размером шрифта. Однако, если же мы хотим просто вывести текст - наш не ждёт никаких разочарований: текст будет выглядеть одинаково и на iOS, и на Android.

Не очень красиво…

Вам тоже показалось, что решение не очень-то изящное? Что ж, React Native - костыльная штука, которая позволяет делать многое, зная что-то одно. За то, что я ленюсь изучить нативную разработку, я плачу костылями. Пока что мне это подходит. А вам? :)