Размер адаптивного шрифта React Native

95

Я хотел бы спросить, как реагировать на нативный дескриптор или делать отзывчивый шрифт. Например, в iphone 4s у меня есть fontSize: 14, а в iphone 6 - fontSize: 18.

Сидней Лотерия
источник
19
Если кто-то ищет способ полностью отключить масштабирование шрифтов, используйтеText.defaultProps.allowFontScaling=false
CoderDave 01
1
@CoderDave, это великолепно!
Abdo
1
Если вам нужен относительный размер шрифта на основе размера экрана вместо точного размера шрифта, вы можете попробовать npmjs.com/package/react-native-responsive-dimensions , он автоматически изменит размер ваших шрифтов в зависимости от размера экрана устройства
Дани Акаш,

Ответы:

100

Вы можете использовать PixelRatio

например:

var React = require('react-native');

var {StyleSheet, PixelRatio} = React;

var FONT_BACK_LABEL   = 18;

if (PixelRatio.get() <= 2) {
  FONT_BACK_LABEL = 14;
}

var styles = StyleSheet.create({
  label: {
    fontSize: FONT_BACK_LABEL
  }
});

Редактировать:

Другой пример:

import { Dimensions, Platform, PixelRatio } from 'react-native';

const {
  width: SCREEN_WIDTH,
  height: SCREEN_HEIGHT,
} = Dimensions.get('window');

// based on iphone 5s's scale
const scale = SCREEN_WIDTH / 320;

export function normalize(size) {
  const newSize = size * scale 
  if (Platform.OS === 'ios') {
    return Math.round(PixelRatio.roundToNearestPixel(newSize))
  } else {
    return Math.round(PixelRatio.roundToNearestPixel(newSize)) - 2
  }
}

Применение:

fontSize: normalize(24)

вы можете пойти еще дальше, разрешив использовать размеры для каждого <Text />компонента заранее заданного размера.

Пример:

const styles = {
  mini: {
    fontSize: normalize(12),
  },
  small: {
    fontSize: normalize(15),
  },
  medium: {
    fontSize: normalize(17),
  },
  large: {
    fontSize: normalize(20),
  },
  xlarge: {
    fontSize: normalize(24),
  },
};
чинлун
источник
22
где вы использовали здесь свою шкалу констант?
Ян Франц Палнгипанг
2
Кажется, это ничего не делает. mini always === 12
A.com
16
Почему вы вычитаете 2 для устройств, отличных от ios?
Parth Tamane
@chinloong Спасибо, это прекрасно работает, но почему -2 на Android?
colakollektiv
52

Мы используем простые и понятные функции утилит масштабирования, которые мы написали:

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

//Guideline sizes are based on standard ~5" screen mobile device
const guidelineBaseWidth = 350;
const guidelineBaseHeight = 680;

const scale = size => width / guidelineBaseWidth * size;
const verticalScale = size => height / guidelineBaseHeight * size;
const moderateScale = (size, factor = 0.5) => size + ( scale(size) - size ) * factor;

export {scale, verticalScale, moderateScale};

Экономит время, делая много «если». Вы можете прочитать об этом в моем блоге .


Изменить: я подумал, что было бы полезно извлечь эти функции в их собственный пакет npm, который я также включил ScaledSheetв пакет, который является автоматически масштабируемой версией StyleSheet. Вы можете найти его здесь: react-native-size-questions .

нирский
источник
Спасибо, как лучше всего использовать эту утилиту? Я имею в виду, где использовать шкалу, вертикальную шкалу и умеренную шкалу?
Пир Шукаруллах Шах
4
Я использую умеренный масштаб почти для всего, что требует масштабирования, например fontSize, полей, изображения и размера Svg (для макета я использую flex), потому что масштабирование imo не должно быть линейным, но это вопрос личных предпочтений. Если вы хотите добиться линейного результата, используйте в основном масштаб и используйте verticalScale для таких вещей, как высота контейнеров.
nirsky
16

Поскольку в настоящее время адаптивные блоки недоступны в react-native, я бы сказал, что лучше всего будет определить размер экрана, а затем использовать его для определения типа устройства и условной установки fontSize.

Вы можете написать такой модуль:

function fontSizer (screenWidth) {
  if(screenWidth > 400){
    return 18;
  }else if(screenWidth > 250){
    return 14;
  }else { 
    return 12;
  }
}

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

Этот или этот модуль может помочь вам найти размеры или тип устройства.

Исаак Мэдвед
источник
Я установил response-native-device, но при запуске приложения выдает ошибку «Невозможно разрешить модуль Dimension»
Сидней Лотерия,
Похоже, вам нужно убедиться, что вы используете правильную версию RN для модуля
Исаак Мэдвед
Я использую последнюю версию React Native :) Думаю, в настоящее время она не поддерживается?
Сидней Лотерия,
Возможно ... Может быть, попробуйте удалить папку node_modules и повторноnpm install
Исаак Мэдвед
6

Взгляните на библиотеку, которую я написал: https://github.com/tachyons-css/react-native-style-tachyons

Он позволяет вам remпри запуске указать root-fontSize ( ), который вы можете сделать в зависимости от вашегоPixelRatio или других характеристик устройства.

Затем вы получаете стили относительно вашего rem, не только fontSize, но и отступы и т. Д.:

<Text style={[s.f5, s.pa2, s.tc]}>
     Something
</Text>

Расширение:

  • f5всегда ваш основной размер шрифта
  • pa2 дает вам отступ относительно вашего базового размера шрифта.
Фабиан Зейндль
источник
5

Я просто использую соотношение размеров экрана, которое мне подходит.

const { width, height } = Dimensions.get('window');

// Use iPhone6 as base size which is 375 x 667
const baseWidth = 375;
const baseHeight = 667;

const scaleWidth = width / baseWidth;
const scaleHeight = height / baseHeight;
const scale = Math.min(scaleWidth, scaleHeight);

export const scaledSize =
    (size) => Math.ceil((size * scale));

Контрольная работа

const size = {
    small: scaledSize(25),
    oneThird: scaledSize(125),
    fullScreen: scaledSize(375),
};

console.log(size);

// iPhone 5s
{small: 22, oneThird: 107, fullScreen: 320}
// iPhone 6s
{small: 25, oneThird: 125, fullScreen: 375}
// iPhone 6s Plus
{small: 28, oneThird: 138, fullScreen: 414}
Шентаой
источник
Означает ли это, что вам нужно использовать симулятор iPhone 6, и в зависимости от того, как он там выглядит, он будет хорошо смотреться на других устройствах?
Уолтер Монеке,
@WalterMonecke в моем случае да. Вы также можете адаптироваться к использованию другого симулятора в качестве базы.
shentaoy
4

Мне удалось это преодолеть, выполнив следующие действия.

  1. Выберите размер шрифта, который вам нравится в текущем представлении (убедитесь, что он подходит для текущего устройства, которое вы используете в симуляторе).

  2. import { Dimensions } from 'react-native' и определите ширину за пределами компонента следующим образом: let width = Dimensions.get('window').width;

  3. Теперь console.log (ширина) и запишите его. Если у вас красивый размер шрифта 15, а ширина, например, 360, возьмите 360 и разделите на 15 (= 24). Это будет важная ценность, которая будет адаптирована к разным размерам.

    Используйте этот номер в своем объекте стилей следующим образом: textFontSize: { fontSize = width / 24 },...

Теперь у вас есть отзывчивый fontSize.

Вальтер Монеке
источник
эй, это действительно работает? f1 = ширина / (ширина / размер) это не может работать?
Элронд
1
В итоге я использовал react-native-text.
Walter Monecke
4

adjustsFontSizeToFitи numberOfLinesработает у меня. Они превращают длинное письмо в одну строку.

<View>
  <Text
    numberOfLines={1}
    adjustsFontSizeToFit
    style={{textAlign:'center',fontSize:30}}
  >
    {this.props.email}
  </Text>
</View>
Гандам Мейстер
источник
10
согласно документации, «adjustsFontSizeToFit» применяется только к iOS
mdehghani
3

Мы можем использовать гибкий макет и использовать adjustsFontSizeToFit = {true} для гибких размеров шрифта. И текст будет корректироваться в соответствии с размером контейнера.

     <Text
    adjustsFontSizeToFit
    style={styles.valueField}>{value}
    </Text>

Но в стилях вам нужно также указать размер шрифта, только тогда будет работать adjustsFontSizeToFit.

    valueField: {
    flex: 3,
    fontSize: 48,
    marginBottom: 5,
    color: '#00A398',
},
Пайел Датта
источник
2

Недавно я столкнулся с этой проблемой и в итоге использовал таблицу стилей response-native-extended-stylesheet

Вы можете установить remзначение и дополнительные условия размера в зависимости от размера экрана. Согласно документам:

// component
const styles = EStyleSheet.create({
  text: {
    fontSize: '1.5rem',
    marginHorizontal: '2rem'
  }
});
// app entry
let {height, width} = Dimensions.get('window');
EStyleSheet.build({
  $rem: width > 340 ? 18 : 16
});
колаколлектив
источник
2

Почему бы не использовать PixelRatio.getPixelSizeForLayoutSize(/* size in dp */);, он такой же, как pdв Android.

Ахмед Камаль
источник
2
import { Dimensions } from 'react-native';

const { width, fontScale } = Dimensions.get("window");

const styles = StyleSheet.create({
    fontSize: idleFontSize / fontScale,
});

fontScaleполучить масштаб в соответствии с вашим устройством .

Парас Корат
источник
fontscale просто возвращает 1 на виртуальном устройстве Android Emulator 4_WVGA_Nexus_S_API, которое я использую.
reggie3 07
0

Нужно использовать этот способ. Я использовал этот, и он работает нормально.

response-native-responseive -screen npm install react-native-response-screen --save

Прямо как у меня аппарат 1080x1920

The vertical number we calculate from height **hp**
height:200
200/1920*100 = 10.41% - height:hp("10.41%")


The Horizontal number we calculate from width **wp**
width:200
200/1080*100 = 18.51% - Width:wp("18.51%")

Работает на всех устройствах

Тушар Кумават
источник
0

У меня сработал немного другой подход: -

const normalize = (size: number): number => {
  const scale = screenWidth / 320;
  const newSize = size * scale;
  let calculatedSize = Math.round(PixelRatio.roundToNearestPixel(newSize))

  if (PixelRatio.get() < 3)
    return calculatedSize - 0.5
  return calculatedSize
};

Обратитесь к Pixel Ratio, поскольку это позволяет вам лучше настроить функцию в зависимости от плотности устройства.

Арпан Шарма
источник
-3

Вы можете использовать что-то вроде этого.

var {высота, ширина} = Размеры.get ('окно'); var textFontSize = width * 0,03;

inputText: {
    color : TEXT_COLOR_PRIMARY,
    width: '80%',
    fontSize: textFontSize
}

Надеюсь, это поможет без установки сторонних библиотек.

Гуна Сехар
источник
1
а откуда 0,03 взялось?
David Noreña
он будет отзывчивым?
Дипак Ганачари