// utils/sizeUtils.ts
import {Dimensions,Platform,PixelRatio, ScaledSize }from 'react-native';
import DeviceInfo from 'react-native-device-info';
export const isIPad =DeviceInfo.isTablet();
const DESIGN_WIDTH =375;
const DESIGN_HEIGHT =812;
// 动态尺寸感知
let screenWidth =Dimensions.get('window').width;
let screenHeight =Dimensions.get('window').height;
Dimensions.addEventListener('change', ({ window }: {window: ScaledSize }) => {
screenWidth = window.width;
screenHeight = window.height;
});
/**
* // 响应式布局
*
* width: calcWidth(300),
* height: calcHeight(200),
* padding: calcSafePadding(20),
* margin: calcSize(10)
* }}>
*
* fontSize: calcFont(16),
* marginTop: isLandscape() ? calcHeight(10) : calcWidth(10)
* }}>
* {isIPad ? 'iPad Optimized' : 'Mobile View'}
*
*
* @param size
* @param basedOnWidth
*/
// 智能缩放核心算法
const getScaleRatio = (size:number, basedOnWidth:boolean) => {
const designRatio =DESIGN_WIDTH /DESIGN_HEIGHT;
const screenRatio =screenWidth /screenHeight;
const isLandscape =screenWidth >screenHeight;
// 大屏设备特殊处理
if (isIPad ||Math.abs(designRatio -screenRatio) >0.2) {
const baseScale = basedOnWidth ?screenWidth /DESIGN_WIDTH :screenHeight /DESIGN_HEIGHT;
// 动态最大缩放系数(区分设备类型和方向)
let maxScale =1.6;
if (!isIPad) {
maxScale =isLandscape ?2.0 :1.8;
}
return Math.min(size *baseScale, size *maxScale);
}
return basedOnWidth ? size * (screenWidth /DESIGN_WIDTH) : size * (screenHeight /DESIGN_HEIGHT);
};
// 统一尺寸计算
const coreCalculator = (size:number, basedOnWidth:boolean) => {
let scaledSize =getScaleRatio(size, basedOnWidth);
// 超大屏衰减系数(如三星Tab S8 Ultra)
if (screenWidth >1300 ||screenHeight >1300) {
scaledSize *=0.82;
}
return PixelRatio.roundToNearestPixel(scaledSize);
};
/**
* 智能宽度适配
*/
export const calcWidth = (size:number):number =>coreCalculator(size,true);
/**
* 智能高度适配
*/
export const calcHeight = (size:number):number =>coreCalculator(size,false);
/**
* margin、border
* 自适应混合计算
*/
export const calcSize = (size:number, basedOnWidth:boolean =true):number => {
// 大尺寸元素微调(适用于按钮等控件)
if (size >50) {
return coreCalculator(size *0.97, basedOnWidth);
}
return coreCalculator(size, basedOnWidth);
};
/**
* 字体优化(移除系统缩放因素)
*/
export const calcFont = (size:number):number => {
const baseScale =Math.min(screenWidth /DESIGN_WIDTH,screenHeight /DESIGN_HEIGHT);
let scaledSize = size *baseScale;
// iPad动态缩放策略
if (isIPad) {
const screenMax =Math.max(screenWidth,screenHeight);
// 根据屏幕尺寸应用阶梯式缩放
if (screenMax >1366) {
// 12.9寸iPad Pro
scaledSize *=0.8;// 基准尺寸的90%
}else if (screenMax >1024) {
// 常规iPad
scaledSize *=0.95;
}else {
// iPad mini
scaledSize *=1.0;// 保持原始计算
}
// 横屏模式额外调整
if (isLandscape()) {
scaledSize *=0.92;// 横屏再缩小8%
}
}
// 平台差异处理
return PixelRatio.roundToNearestPixel(
Platform.select({
ios:scaledSize,
android:scaledSize >12 ?scaledSize -1 :scaledSize,
}),
);
};
/**
* 动态安全边距(兼容刘海屏和折叠屏)
*/
export const calcSafePadding = (size:number):number => {
const basePadding =calcSize(size);
const aspectRatio =screenWidth /screenHeight;
// 超宽屏特殊处理(如Galaxy Z Fold)
if (aspectRatio >0.65) {
return PixelRatio.roundToNearestPixel(basePadding *1.8);
}
return isIPad
?PixelRatio.roundToNearestPixel(basePadding *1.4)
:PixelRatio.roundToNearestPixel(basePadding *1.2);
};
// 设备分类策略优化
export const isSmallDevice = !isIPad &&screenWidth <375;
export const isMediumDevice = !isIPad &&screenWidth >=375 &&screenWidth <428;
export const isLargeDevice =isIPad ||screenWidth >=428;
// 屏幕方向辅助方法
export const isLandscape = () =>screenWidth >screenHeight;