RN适配方案:屏幕适配、分辨率适配、刘海屏/全面屏适配

React Native(RN)的适配主要可以分为 屏幕尺寸适配、分辨率(DPI)适配、刘海屏/全面屏适配、横竖屏适配 四大类。下面是一套比较完整的适配方案,也是目前企业项目最常采用的实践。


一、屏幕尺寸适配(Screen Size)

目标:保证不同尺寸手机(4.7寸、6.1寸、平板等)UI比例一致。

方案一:Flex布局(推荐)

RN官方推荐全部使用 Flex。

xml 复制代码
<View style={{ flex: 1 }}>
    <View style={{ flex: 2 }} />
    <View style={{ flex: 3 }} />
</View>

优点:

  • 不需要计算高度
  • 不同尺寸自动拉伸
  • Android/iOS一致

适用于:

  • 页面布局
  • 列表
  • Header/Footer

方案二:百分比布局

RN支持百分比。

arduino 复制代码
<View
style={{
    width: "80%",
    height: "30%"
}}
/>

适用于:

  • Banner
  • 图片
  • 卡片

方案三:Dimensions

获取屏幕宽高。

arduino 复制代码
import { Dimensions } from "react-native";

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

console.log(width, height);

例如:

arduino 复制代码
<Image
style={{
    width,
    height: width * 0.5
}}
/>

二、分辨率适配(DP、DPI)

RN使用的是 dp(Density-independent Pixel) ,不是px。

例如:

arduino 复制代码
width:100

表示100dp。

RN会自动转换:

复制代码
iPhone 8

100dp
↓

200px(Retina)

因此:

不要写 px。


PixelRatio

获取设备像素比。

csharp 复制代码
import { PixelRatio } from "react-native";

PixelRatio.get();

例如:

复制代码
iPhone8

2

iPhone14 Pro

3

Android

2~4

可以计算真实像素:

ini 复制代码
const px = PixelRatio.getPixelSizeForLayoutSize(100);

字体适配

RN字体默认也是dp。

如果需要根据屏幕缩放:

scss 复制代码
PixelRatio.getFontScale()

例如:

css 复制代码
fontSize:16 / PixelRatio.getFontScale()

或者:

使用 react-native-size-matters。


三、屏幕缩放适配(推荐)

企业项目一般不会直接写:

arduino 复制代码
width:100

而是:

scss 复制代码
设计稿

↓

scale()

↓

真实尺寸

例如:

设计稿:

复制代码
375

当前:

复制代码
414

计算:

复制代码
100

↓

110

自己实现

arduino 复制代码
import { Dimensions } from "react-native";

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

const BASE_WIDTH = 375;

export function scale(size) {
    return width / BASE_WIDTH * size;
}

使用:

css 复制代码
width:scale(100)

高度缩放

arduino 复制代码
const BASE_HEIGHT = 812;

export function verticalScale(size) {
    return height / BASE_HEIGHT * size;
}

moderateScale

很多项目采用:

matlab 复制代码
function moderateScale(size, factor = 0.5) {
    return size + (scale(size) - size) * factor;
}

比直接scale舒服很多。


推荐库

arduino 复制代码
react-native-size-matters

API:

javascript 复制代码
import {
scale,
verticalScale,
moderateScale
} from "react-native-size-matters";

例如:

less 复制代码
width:scale(100)

height:verticalScale(40)

fontSize:moderateScale(16)

这是目前RN最流行的方案。


四、刘海屏 / 全面屏适配

现在基本所有手机都有:

  • 刘海
  • 挖孔
  • 灵动岛
  • 圆角
  • 手势条

因此必须适配安全区域。


SafeAreaView(推荐)

RN提供:

javascript 复制代码
import { SafeAreaView } from "react-native-safe-area-context";

<SafeAreaView style={{ flex:1 }}>
</SafeAreaView>

注意:

不要使用RN自带:

javascript 复制代码
import { SafeAreaView } from "react-native";

推荐安装:

java 复制代码
react-native-safe-area-context

useSafeAreaInsets

获取安全区域。

ini 复制代码
import {
useSafeAreaInsets
} from "react-native-safe-area-context";

const insets = useSafeAreaInsets();

console.log(insets);

例如:

css 复制代码
top

44

bottom

34

可以:

makefile 复制代码
paddingTop: insets.top
paddingBottom: insets.bottom

全屏页面

例如视频:

ini 复制代码
<View
style={{
    paddingTop: insets.top,
    paddingBottom: insets.bottom
}}
>

五、状态栏适配

javascript 复制代码
import { StatusBar } from "react-native";

<StatusBar
barStyle="dark-content"
/>

Android:

ini 复制代码
translucent={true}
backgroundColor="transparent"

配合:

makefile 复制代码
paddingTop: insets.top

六、横竖屏适配

监听:

javascript 复制代码
Dimensions.addEventListener(
"change",
({ window }) => {
    console.log(window.width);
}
);

或者:

scss 复制代码
useWindowDimensions()
scss 复制代码
const { width, height } = useWindowDimensions();

推荐使用 Hook,会自动更新。


七、图片适配

ini 复制代码
<Image
resizeMode="contain"
/>

常见模式:

scss 复制代码
contain

cover

stretch

center

推荐:

复制代码
cover

或者:

css 复制代码
contain

八、字体适配

Android字体可能随系统设置变化。

可以关闭:

ini 复制代码
<Text allowFontScaling={false}>

或者统一封装:

ini 复制代码
<Text
allowFontScaling={false}
style={{
    fontSize:moderateScale(16)
}}
>

九、推荐项目目录

markdown 复制代码
utils/
    scale.ts
hooks/
    useSafeArea.ts
components/
    Screen.tsx

scale.ts

arduino 复制代码
import { Dimensions } from "react-native";
import { scale, verticalScale, moderateScale } from "react-native-size-matters";

export { scale, verticalScale, moderateScale };

export const SCREEN_WIDTH = Dimensions.get("window").width;
export const SCREEN_HEIGHT = Dimensions.get("window").height;

Screen.tsx

javascript 复制代码
import { SafeAreaView } from "react-native-safe-area-context";

export default function Screen({ children }) {
    return (
        <SafeAreaView style={{ flex: 1 }}>
            {children}
        </SafeAreaView>
    );
}

以后页面统一:

xml 复制代码
<Screen>
    {/* 页面内容 */}
</Screen>

十、企业级最佳实践

在实际项目中,一般推荐采用以下组合:

场景 推荐方案
页面布局 Flex 布局
宽高适配 react-native-size-mattersscale / verticalScale / moderateScale
字体适配 moderateScale + 视情况关闭 allowFontScaling
刘海屏/全面屏 react-native-safe-area-contextSafeAreaViewuseSafeAreaInsets
状态栏 StatusBar + SafeAreaInsets
屏幕变化 useWindowDimensions
图片 resizeMode="cover"contain

总结: 当前主流 RN 项目通常采用 Flex 布局 + react-native-size-matters 做尺寸缩放 + react-native-safe-area-context 做安全区域适配 + useWindowDimensions 监听屏幕变化。这种组合兼容 iOS、Android 以及刘海屏、全面屏设备,维护成本低,也是社区较为成熟的实践。

相关推荐
zzzzzz3102 小时前
别急着把页面做成舞台:从 react-bits 看动画组件该怎么选
javascript·react.js·开源
烬羽17 小时前
AI Coding 全流程实战:从需求到上线,我用 AI 开发了一个 NPM 包
前端·react.js·ai编程
前进的程序员17 小时前
Codex破局:前端组件秒级生成|提速React/Vue开发,可复用提示词+实战调试经验
前端·vue.js·react.js·codex
YHHLAI20 小时前
从「跑分」到「干活」:Benchmark 与 GPT 5.6 的两种叙事
大数据·前端·人工智能·react.js·前端框架
码云之上21 小时前
从Popup类组件看定位参考系陷阱与设计取舍
前端·react.js·scss
FungLeo21 小时前
React 管理后台实战 · 列表里突然出现一堆空白行?PIPL 擦除后前端怎么处理才不露馅
前端·react.js·状态模式·pipl
Virony1 天前
React基础知识
前端·react.js·前端框架
liangshanbo12151 天前
React Hooks 为什么不能在条件分支/循环中调用?
前端·react.js·前端框架
嘟嘟07171 天前
一个微信公众号 Markdown 渲染组件,如何用 SDD 把需求、架构、任务一次写清
react.js·markdown