Проблема с обработкой экрана разных размеров в Android-React native - PullRequest
2 голосов
/ 10 ноября 2019

Я немного запутался с обработкой экрана разных размеров для приложения.

в Android есть модуль с именем dp, который, кажется, обрабатывает размер экрана и изменение разрешения. Я ожидаю, когда я использую это устройство вместо пикселей, я вижу одинаковый размер component (как кнопка, ...) на каждом экране. например, кнопка с размером 20dp должна выглядеть одинаково на всех экранах.

в статьях, которые я читал, что React-Native также использует dp в качестве основного устройства. так ожидал то же самое здесь, но это не работает, как я ожидал. кнопка с 20dp не выглядит одинаково на разных экранах.

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

например, const scaleX = Dimension.getWidth() / baseWdith => упрощенный код

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

мой вопрос в том, что dp устройство не должно делать то же самое !? почему RN не справился с автоматическим масштабированием? если для управления соотношением размеров экрана используется sth с именем dp, то почему они выполняют масштабирование вручную?

Ответы [ 2 ]

1 голос
/ 14 ноября 2019

UPD

спасибо за ответ. 1 - вы можете поделиться фрагментом кода, используя его для стилизации 2 - кажется, для IOS его логические пиксели и для Android dp. проверьте stackoverflow.com/questions/34493372/… 3 - почему ничего для масштабирования ширины и высоты одновременно. я имею в виду, что для истинного масштабирования необходимо масштабирование в обоих направлениях

  1. Готово, я обновил ответ.
  2. Пиксели используются внутри стилей, но выможно пересчитать, например, так:

    style={{ borderWidth: 1 / PixelRatio.get() }}
    

    Кроме того, вы можете написать свои собственные функции масштабирования с PixelRatio подходом

  3. Все работает нормально

    imageContainer: ViewStyle = {
        height: scaleHeight(63),
        width: scaleWidth(63),
        borderRadius: scaleWidth(63 / 2),
        backgroundColor: R.color.white,
        alignItems: 'center',
        justifyContent: 'center',
    };
    

Оригинал

Мой вопрос в том, что дп юнит не должен делать то же самое !? почему RN не справился с автоматическим масштабированием? если для управления соотношением размеров экрана используется sth с именем dp, то почему они делают масштабирование вручную?

1) В RN это всего лишь пиксели 2) Не могу сказать 3) Можно использовать проценты, ноэто не очень хорошее решение для идеального дизайна пикселей

Как это работает в моем проекте

Этот сценарий используется в работе, и все в порядке;

Для масштабирования размеров я использую «scaleWidth» и «scaleHeight»

Для масштабирования расстояний, например, расстояния между строкой состояния и некоторым содержимым, я использую «scaleY»

import { Dimensions } from 'react-native';
import DeviceInfo from 'react-native-device-info';

const IPHONE6_SCREEN_WIDTH = 375;
const IPHONE6_SCREEN_HEIGHT = 667;

export const isTablet = DeviceInfo.getDeviceType() !== 'Handset';

export const scaleWidth = (width: number) => {
    if (isTablet) {
        return width;
    }
    return Dimensions.get('screen').width / IPHONE6_SCREEN_WIDTH * width;
};

export const scaleHeight = (height: number) => {
    if (isTablet) {
        return height;
    }
    return Dimensions.get('screen').width / IPHONE6_SCREEN_WIDTH * height;
};

export const scaleX = scaleWidth;

export const scaleY = (height: number) =>
Dimensions.get('screen').height / IPHONE6_SCREEN_HEIGHT * height;

export const scaleFont = scaleWidth;

Пример:

textStyle: TextStyle = {
    fontFamily: R.font.montserratBold,
    fontSize: scaleFont(14),
    lineHeight: scaleHeight(18),
    letterSpacing: scaleWidth(1.75),
    color: R.color.white,
};

smallButtonStyle: ViewStyle = {
    ...this.buttonStyle,
    height: scaleHeight(36),
};

smallTextStyle: TextStyle = {
    ...this.textStyle,
    fontSize: scaleFont(12),
    lineHeight: scaleHeight(15),
    letterSpacing: 0,
    marginHorizontal: scaleWidth(10),
};

Как я уже говорил, я использую scaleY для вертикальных расстояний на экране. Пример:

render() {
    const { loginRequestState } = this.props;

    return (
        <HideKeyboardView>
            <KeyboardAwareScrollView
                style={styles.mainContentView()}
                contentInsetAdjustmentBehavior={'never'}
                enableOnAndroid
                contentInset={{ bottom: R.constant.botNavBarPlaceholderHeight }}
            >
                <LinkedText
                    text={R.string.signUp.title}
                    onPress={this.goToSignUp}
                    insets={{ top: scaleY(23) }}
                    alignToEnd
                />
                <Title
                    text={R.string.signIn.title}
                    insets={{ top: scaleY(36) }}
                />
                <SignInButton
                    onPress={this.handleMyElevation}
                    icon={R.image.icon.myElevationLogo}
                    insets={{ top: scaleHeight(30) }}
                    signInVariant={'myElevation'}
                />
                <SeparatorWithText
                    insets={{ top: scaleY(40) }}
                    text={R.string.global.or}
                />
                {this.renderForm()}
            </KeyboardAwareScrollView>

            <SafeAreaView style={styles.container}>
                <FlexView />
                <BotNavPlaceholder
                    toScreen={'signUp'}
                    onPress={this.goToSignUp}
                />
            </SafeAreaView>
            <TransparentLoadingView
                isVisible={loginRequestState === 'progress'}
            />
        </HideKeyboardView>
    );
}
1 голос
/ 14 ноября 2019

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

 import { Dimensions, PixelRatio } from 'react-native';
const screenWidth = Dimensions.get('window').width;
const screenHeight = Dimensions.get('window').height;
const widthDP = widthPercent => {
    // Convert string input to decimal number
    const elemWidth = parseFloat(widthPercent);
    return PixelRatio.roundToNearestPixel(screenWidth * elemWidth / 100);
};
const heightDP = heightPercent => {
    // Convert string input to decimal number
    const elemHeight = parseFloat(heightPercent);
    return PixelRatio.roundToNearestPixel(screenHeight * elemHeight / 100);
};

Вы можете использовать эти функции, как показано ниже, на любом из ваших экранов

  const style = StyleSheet.create({
    container: {
        padding: 2,
        width: widthDP('69.60%'),
        height: heightDP('100%),
    },
    textStyle: {
        textAlign: "center",
        fontSize: widthDP('3.70%'),
        color: '#000000',
    },
})

Вы можете использовать приведенную ниже таблицу образцов для dpв процентах

 HEIGHT:

5:heightDP('0.80%'),
7:heightDP('1.05%'),
8:heightDP('1.2%')
9:heightDP('1.35%'),
10: heightDP('1.5%'),
11:heightDP('1.60%'),
12:heightDP('1.8%'),
14:heightDP('2.12%'),
15:heightDP('2.25%'),
17:heightDP('2.50%'),
18:heightDP('2.65%'),
19:heightDP('2.80%'),
20: heightDP('2.95%') //
22:heightDP('3.25%'),
24:heightDP('3.5%'),,
25:heightDP('3.66%'),
29:heightDP('4.27%'),
30:heightDP('4.4%'),
31:heightDP('4.58%')
33:heightDP('4.25%'),
35:heightDP('5.15%')
36: heightDP('5.30%')//
39:heightDP('5.75%'),
40:heightDP('5.9%'),
42:heightDP('6.2%'),
48:heightDP('7%'),
50:heightDP('7.35%'),
52:heightDP('7.62%')//
55:heightDP('8.10%'),
64:heightDP('9.40%'),
65:heightDP('9.52%'),
66:heightDP('9.66%'),
67:heightDP('9.80%')
71.6:heightDP('10.50%')
72:heightDP('10.55%')//
76:heightDP('11.15%'),
83:heightDP('12.20%')//
90:heightDP('13.19%'),
91:heightDP('13.35%'),
105:heightDP('15.36%')
109:heightDP('16.00%'),
123:heightDP('18%')
136.7:heightDP('20%')
140:heightDP('20.50%')//
174:heightDP('25.5%'),
190:heightDP('27.88%'),
194:heightDP('28.42%'),
209:heightDP('30.59%')
222:heightDP('32.50%')
224:heightDP('32.80%')//
230:heightDP('33.70%'),
246:heightDP('36%'),
265:heightDP('38.8%'),

328heightDP('48%')
334:heightDP('49%')//
341:heightDP('50%')//
344:heightDP('50.40%')
348:heightDP('51%')
355:heightDP('52%')
409:heightDP('60%'),
423:heightDP('62%')
434:heightDP('63.55%'),


WIDTH:


5:widthDP('1.25%'),
7:widthDP('1.80%')v
8:widthDP('1.99%'),
9:widthDP('2.2%'),
10:widthDP('2.5%'),
12:widthDP('3.0%'),
13:widthDP('3.2%'),
14:widthDP('3.5%'),
15:widthDP('3.70%'), 
16:widthDP('3.90%')//
17:widthDP('4.20%'),
18:widthDP('4%'),
18:widthDP('4.4%'),
20:widthDP('4.83%'),
22:widthDP('5.4%'),
24:widthDP('5.8%'),
26:widthDP('6.40%'),
29:widthDP('7.1%'),
30:widthDP('7.30%'),    
39:widthDP('9.50%'),
40:widthDP('9.80%')
44:widthDP('10.70%'),
45:widthDP('11.00%'),
48:widthDP('11.70%')//
60:widthDP('14.50%')
64:widthDP('15.65%'),
68.5:widthDP('16.7%')
70:widthDP('17.2%')

72:widthDP('17.55%')

75:widthDP('18.30%')
76:widthDP('18.65%')
80: widthDP('22%')
273:widthDP('66.40%'),
286:widthDP('69.60%'),
315:widthDP('76.70%'),
335:widthDP('81.5%'),

WidthDP(1)= 4.190476190476191

HeightDP(1)= 6.857142857142857
...