你的 px2dp
函數基本思路是正確的,但可以進一步優化以確保更精確的適配。以下是改進后的完美精確方案:
完美精確的適配方案
import { Dimensions, PixelRatio, Platform, ScaledSize } from 'react-native';// 獲取屏幕尺寸(考慮橫豎屏)
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');// UI設計基準寬度(根據你的設計稿調整)
const UI_DESIGN_WIDTH = 750;/*** 將設計稿中的px值轉換為實際dp值* @param uiElementPx 設計稿中的像素值* @param baseWidth 設計稿基準寬度(默認750)* @returns 實際設備上的dp值*/
function pxToDp(uiElementPx: number, baseWidth: number = UI_DESIGN_WIDTH): number {// 確保使用屏幕的最小邊作為基準(防止橫豎屏切換導致問題)const minScreenEdge = Math.min(screenWidth, screenHeight);// 計算比例因子const scaleFactor = minScreenEdge / baseWidth;// 轉換并四舍五入到最近的像素return PixelRatio.roundToNearestPixel(uiElementPx * scaleFactor);
}/*** 獲取精確的屏幕信息*/
function getExactScreenInfo() {const { width, height, scale, fontScale } = Dimensions.get('window');const pixelRatio = PixelRatio.get();return {dpWidth: width,dpHeight: height,pixelWidth: width * scale,pixelHeight: height * scale,pixelRatio,scale,fontScale,orientation: width > height ? 'landscape' : 'portrait',isAndroid: Platform.OS === 'android',isIOS: Platform.OS === 'ios',};
}// 使用示例
const screenInfo = getExactScreenInfo();
console.log('屏幕信息:', screenInfo);const elementSize = pxToDp(100); // 將設計稿中的100px轉換為實際dp值
console.log('轉換后的尺寸:', elementSize);
關鍵改進點
- 自動處理橫豎屏:始終使用屏幕的最小邊作為基準,確保橫豎屏切換時布局一致
- 精確像素對齊:使用
PixelRatio.roundToNearestPixel
確保渲染時不會出現亞像素模糊 - 完整屏幕信息:提供全面的屏幕信息獲取函數
- 類型安全:使用TypeScript增強了類型檢查
為什么這是更完美的方案?
- 跨平臺一致性:考慮了Android和iOS的不同特性
- 橫豎屏安全:無論設備如何旋轉,都能正確計算
- 像素完美:避免了因浮點數計算導致的渲染模糊
- 可擴展性:可以輕松調整設計基準尺寸
使用建議
- 在設計時確定一個基準寬度(如750px,相當于iPhone 6/7/8的設計尺寸)
- 所有尺寸都使用
pxToDp()
函數轉換 - 對于字體大小,可以使用類似的函數,但可能需要額外考慮系統字體縮放
// 字體大小適配(可選)
function pxToFontDp(uiElementPx: number, baseWidth: number = UI_DESIGN_WIDTH): number {const minScreenEdge = Math.min(screenWidth, screenHeight);const scaleFactor = minScreenEdge / baseWidth;return PixelRatio.roundToNearestPixel(uiElementPx * scaleFactor * (1 / fontScale));
}
這樣實現的方案在各種設備和屏幕尺寸下都能提供精確的布局適配。
跳轉 》》React Native屏幕適配的藝術:px2dp從像素完美到跨平臺優雅布局之詳細篇
如果覺得寫的不錯,請動動手指點贊、關注、評論哦
如有疑問,可以評論區留言~