天天看點

React-Native 螢幕适配的問題

1. 前言

在使用

react-native

進行開發的時候我們參見官方文檔知道做螢幕适配是使用

flexBox

來進行布局.

戳我檢視 flexBox 布局

有關

flexBox

的屬性這裡不做太多介紹,不會的請參考官方文檔.這裡隻是說一下在做螢幕适配的時候發現僅僅使用 

flexBox

 還有點不太夠用~

在 

react-native

 中我們使用 

StyleSheet

 這個對象來進行樣式的開發.示例代碼如下所示:

import { StyleSheet } from "react-native";

// 聲明了一個style的變量,使用它來給元件添加樣式
let style = StyleSheet.crate({
    title: {
        fontSize: 14,
        color: "#BBB",
    },
    subTitle: {
        marginTop: 10,
        marginBottom: 10,
        paddingLeft: 10,
        paddingRight: 10,
    },
});
           

可以看到在

react-native

中寫樣式和在

web

中寫

css

還是有很大的差別的.哪些好用的

less

,

sass

等基本上不可以用.而且也不可以

用複合樣式

.例如:

web 中寫樣式

/* web */
.title {
    padding: 10 20 15 5;
}
           

react-native 中寫樣式

/* react-native */
title:{
    paddingTop:10,
    paddingRight:20,
    paddingBottom:15,
    paddingLeft:5
}
           

可以看到在

rn

中寫樣式還是有點麻煩~

2. 使用

flexbox

布局

flexBox

給我們提供了很友善的布局方法,但是有時候我們還是需要一些正常屬性,例如:

width

,

height

,

paddingTop

,

fontSize

等等...因為在

rn

中樣式是沒有機關的(預設

dp

),那麼這個時候問題就來了,在不同的螢幕上它的

dpi

是不同的,如何做适配呢?

通過檢視官方文檔,找到了解決方法.封裝了一個方法

dp2px

,代碼如下所示:

import { Dimensions } from "react-native";
const deviceWidthDp = Dimensions.get("window").width;
// 預設設計稿375
const uiWidthPx = 375;
function dp2px(uiElementPx) {
    return (uiElementPx * deviceWidthDp) / uiWidthPx;
}
export default dp2px;
           

這樣在開發中如果需要使用一些

寬度

,

高度

等屬性的時候直接引用這個方法就可以了.如下所示:

import dp2px from './dp2px';

title:{
    paddingTop:dp2px(10),
    paddingRight:dp2px(20),
    paddingBottom:dp2px(15),
    paddingLeft:dp2px(5)
}
           

這樣就完成了适配的工作.但是這個就是最優解了麼,顯然不是.每次寫樣式的都需要把這個函數引用進來,而且每次都要寫大量的

dp2xp

,實在是非常的麻煩.那麼問題來了,我們如何優化?

3. 封裝 CustomStyleSheet 代替原生 StyleSheet

通過翻看源碼,發現

StyleSheet

不是一個類,我們不需要繼承它,重寫它的這個方法,隻需要自己封裝一個類似

StyleSheet

這樣的一個函數在它的内部進行一些計算,然後在需要寫樣式的地方,統一使用我們的

CustomStyleSheet

代替原生的

StyleSheet

即可.代碼如下所示:

import { StyleSheet } from "react-native";
import dp2px from "./dp2px";

let MyStyleSheet = {
    create(style) {
        let s = { ...style };
        // 目前僅對以下的屬性進行處理
        let list = [
            "width",
            "height",
            "marginTop",
            "marginBottom",
            "marginLeft",
            "marginRight",
            "paddingTop",
            "paddingRight",
            "paddingBottom",
            "paddingLeft",
            "top",
            "right",
            "bottom",
            "left",
            "fontSize",
            "lineHeight",
        ];
        for (outKey in s) {
            for (innerKey in s[outKey]) {
                if (
                    list.includes(innerKey) &&
                    typeof s[outKey][innerKey] == "number"
                ) {
                    s[outKey][innerKey] = px2dp(s[outKey][innerKey]);
                }
            }
        }
        return StyleSheet.create(s);
    },
};
export default MyStyleSheet;
           

通過上述封裝後使用起來就很友善了.在

react-native

元件中直接使用它來代替原生的

StyleSheet

即可.例如:

import MyStyleSheet from "./myStyleSheet";

// 使用封裝好的MyStyleSheet來代替原生StyleSheet,直接寫數字即可自動轉換為不同螢幕适配的dp
let style = MyStyleSheet.create({
    title: {
        fontSize: 14,
        width: 100,
    },
    subTitle: {
        paddingTop: 10,
        paddingBottom: 10,
        marginTop: 10,
        marginBottom: 10,
    },
});
           

至此,結束.附上相關資料,供學習

繼續閱讀