RN 屏幕适配
android中1dp=1px (160dpi)、1dp=2px (320dpi)dpr=1的屏幕使用一倍图,dpr=2的屏幕使用二倍图,dpr=3的屏幕使用三倍图
Reading Materials
Basic
分辨率
分辨率即横纵两个方向上的像素点数量, 常见的分辨率:
1920x1080即1080p(1k屏)2560x1440即显示器2k屏3840x2160即显示器4k屏 (Quad Full HD)4096x2160即显示器4k屏 (UHD)
tsx
import {useWindowDimensions} from 'react-native';
const {width, height} = useWindowDimensions();
console.log('[INFO] wxh: ', `${width}x${height}`);DPI
DPI 即 Dots Per Inch, 每英寸点数, 计算公式为对角像素数/对角英寸
tsx
console.log('[INFO] DPI: ', `${PixelRatio.get() * 160} dpi`);160dpi<->mdpi240dpi<->hdpi320dpi<->xhdpi480dpi<->xxhdpi
PPI
PPI 即 Pixels Per Inch, 每英寸像素数, 也称像素密度
图片适配
js
const image = getImage({
width: PixelRatio.getPixelSizeForLayoutSize(200), // 等同于 200 * PixelRatio.get()
height: PixelRatio.getPixelSizeForLayoutSize(100) // 等同于 100 * PixelRatio.get()
});
<Image source={image} />;字体适配
屏幕适配
总的来说, RN 项目有以下几种屏幕适配方案:
Dimensions:tsximport {Dimensions} from 'react-native'; // 可换成 useWindowDimensions const windowDimensions = Dimensions.get('window'); /** * 设计稿宽度, 单位: px */ export const DESIGN_WIDTH = 1025; /** * 设计稿高度, 单位: px */ export const DESIGN_HEIGHT = 629; // const TARGET_WIDTH = 1920; // const TARGET_HEIGHT = 1024; export const WIDTH_SCALE = windowDimensions.width / DESIGN_WIDTH; export const HEIGHT_SCALE = windowDimensions.height / DESIGN_HEIGHT; // 这里无需使用 use 前缀, 使用 u 即可 (非 hook) export const uResponsiveWidth = (width: number, transform = true) => (transform ? width * WIDTH_SCALE : width); export const uResponsiveHeight = (height: number, transform = true) => (transform ? height * HEIGHT_SCALE : height); export const uResponsiveFontSize = (fontSize: number, transform = true) => transform ? fontSize * Math.min(WIDTH_SCALE, HEIGHT_SCALE) : fontSize;然后在
StyleSheet.create中调用相应方法即可实现屏幕适配基于
StyleSheet封装CustomStyleSheetjsimport {StyleSheet} from 'react-native'; import dp2px from './dp2px'; let CustomStyleSheet = { create(style) { let s = {...style}; // 目前仅对以下的属性进行处理 let list = [ 'width', 'height', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'top', 'right', 'bottom', 'left', 'fontSize', 'lineHeight' ]; for (let outKey in s) { for (let innerKey in s[outKey]) { if (list.includes(innerKey) && typeof s[outKey][innerKey] == 'number') { s[outKey][innerKey] = dp2px(s[outKey][innerKey]); } } } return StyleSheet.create(s); } }; export default CustomStyleSheet;babel插件自动转换, 如以下插件一些其他插件:
flutter_screenutil
可参考 flutter_screenutil 实现 RN 版本的屏幕适配