準備
首先,我們在官方文檔寬度和高度一節可以知道,RN中單位是dp,這個跟Android中的單位是一致的。
官網中:
A dp is equal to one physical pixel on a screen with a density of 160.To calculate dp:dp = (width in pixels * 160) / screen density
這裡的 screen density 螢幕密度,它約等於(dpi/160),在RN中我們可以通過PixelRatio得到: PixelRatio.get() === 1
mdpi Android 裝置 (160 dpi) PixelRatio.get() === 1.5
hdpi Android 裝置 (240 dpi) PixelRatio.get() === 2
iPhone 4, 4S iPhone 5, 5c, 5s iPhone 6 xhdpi Android 裝置 (320 dpi) PixelRatio.get() === 3
iPhone 6 plus xxhdpi Android 裝置 (480 dpi) PixelRatio.get() === 3.5
Nexus 6
說到這裡,不妨把涉及到的一些概念梳理一下: dp(dip)(Density-independent pixels)一種基於螢幕密度的抽象單位,像素無關密度。在每英寸160點的顯示器上,1dp = 1px。特別需要注意dp是相對長度單位,簡單的說1dp在不同的螢幕或者不同的ppi下展示出來的“物理長度”可能不一致。 px 像素點。也是相對長度 in(inch)英寸。物理長度 pt 中文叫磅,等於1/72英寸。物理長度 sp(與刻度無關的像素):與dp類似,但是可以根據使用者的字型大小喜好設定進行縮放,Android設定字型的時候使用。 density 密度。這個可以參考上邊說的,跟pixelRatio相近,約等於DPI/160。 pixelRatio 裝置像素比。通過PixelRatio.get()獲得 PPI (pixels per inch) 映像解析度 (每英寸所包含的像素數,指對角線) DPI(dots per inch)列印精度 (每英寸所能列印的點數,指寬高) 解析度 : 橫縱2個方向的像素點的數量,常見取值 480X800 ,750X1334 螢幕尺寸: 螢幕對角線的長度(英寸)。電腦電視同理。
所以我們可以知道:
1dp=(1 * density) px,相反1px=(1/density)dp
那麼,我們如何在RN中設定寬度為1px的分割線呢。
width: 1 / PixelRatio.get()
這樣就可以了。
另外,一個裝置的寬高,我們可以這樣獲得:
width: Dimensions.get('window').width,height: Dimensions.get('window').height,
那麼這個得到的寬高是什麼呢。
我們可以列印出來,比如iPhone6s,這個值列印出來是width:375,height:667,因為6s的density是2,所以我們知道這個得到的寬高是dp。 適配方案
所以,這裡RN中的適配方案:以6,6s為例:
UI設計原型:基於iphone6
解析度:1334 x 750 px;
螢幕大小:4.7英寸
DPI: 326dpi(約等於320dpi,density=2)
import {Dimensions} from 'react-native';const deviceWidthDp = Dimensions.get('window').width;const uiWidthPx = 750;export default function px2dp(uiElementPx) { return uiElementPx * deviceWidthDp / uiWidthPx;}
deviceWidthDp為當前運行裝置的寬度,uiWidthPx為UI設計圖的寬度,uiElementPx設計圖中標註的元素的px值。
那麼使用的話,比如一張圖片UI標註寬高為200x400:
<Image style={{width:px2dp(200),height:px2dp(400)}} source=xxx />
其他
我們可以寫一個工具類,這些常用的寫在一起,方便使用:
ScreenUtil.js
import {Dimensions, Platform, PixelRatio} from 'react-native'export default { width: Dimensions.get('window').width, height: Dimensions.get('window').height, onePixel: 1 / PixelRatio.get(), STATUSBAR_HEIGHT: (Platform.OS === 'ios' ? 20 : 0), APPBAR_HEIGHT: (Platform.OS === 'ios' ? 44 : 56),}
需要注意的就是:如果這個工具類和調用方不在一個包下邊的話,需要我們在工具類這個包下,寫一個index.js匯出才行,要不然找不到。
import ScreenUtil from './ScreenUtil'...export {ScreenUtil};
使用的時候就直接:ScreenUtil.width就行。
還有一個問題就是STATUSBAR_HEIGHT和APPBAR_HEIGHT這個順便說一下吧。
iOS螢幕座標是包含狀態列的,所以我們在iOS環境下運行一個組件它會在狀態列下繪製,即會和狀態列重疊,而Android則不會,他會在狀態列下邊開始繪製。
上邊代碼是在StackNavigator/Header中,尤其在我們自訂Header標題列的時候,需要注意要設定paddingTop:STATUSBAR_HEIGHT,這樣就避免了iOS下在狀態列下繪製的問題。
:
React Native 的預設單位和調適型配置方案
react-native 單位換算(px,pt,dp,ppi)
dpi 、 dip 、解析度、螢幕尺寸、px、density 關係以及換算