1. 三方庫(kù)(調(diào)用原生)的使用
這里的三方庫(kù)特指需要調(diào)用原生的庫(kù)署隘,目前項(xiàng)目里用到了react-native-share
(分享)、react-native-linear-gradient
(漸變)亚隙、react-native-splash-screen
(閃屏)磁餐、react-native-svg
(svg)。
正常我們使用react-native link
命令,原生依賴就成功地鏈接到你的iOS/Android項(xiàng)目了诊霹,但出于原生代碼可能被改寫(xiě)的情況羞延,需要在原生代碼中確認(rèn)一下引入情況:
2. lineHeight
在遷移過(guò)程發(fā)現(xiàn)幾個(gè)頁(yè)面都出現(xiàn)一下錯(cuò)誤提示:
Error while updating property 'lineHeight' in shadow node of type:RCTText
查文檔給出的解釋:
lineHeight must be an integer, numbers with decimals are not considered as valid values.
原來(lái)安卓上lineHeight必須是整數(shù),由于我們的項(xiàng)目中用了p2dp進(jìn)行適配脾还,會(huì)有把整數(shù)轉(zhuǎn)成了小數(shù)的情況伴箩,解決方法就是p2dp的結(jié)果進(jìn)行向上取整。
3. 字體引入
安卓上要使用自定義的字體鄙漏,必須要把字體文件放在[project root]/android/app/src/main/assets/fonts/
目錄下才能生效嗤谚。
4. StatusBar
StatusBar是一個(gè)值得被重視的差異,它會(huì)影響到頭部導(dǎo)航的高度樣式問(wèn)題,甚至是整個(gè)頁(yè)面的高度問(wèn)題怔蚌。
4.1 StatusBar高度
- 4.1.1 Android 手機(jī)狀態(tài)欄
(1)當(dāng)狀態(tài)欄呈現(xiàn)在 Andorid 手機(jī)屏幕頂部時(shí)巩步,它會(huì)占用頂部這個(gè)空間,我們只能使用剩下的屏幕空間桦踊。也就是說(shuō)如果從第 0 行開(kāi)始放置組件時(shí)椅野,組件會(huì)緊貼著狀態(tài)欄的下邊沿顯示;
(2)要想知道實(shí)際可用的屏幕高度,可以通過(guò)手機(jī)屏幕的高度減去狀態(tài)欄高度得到籍胯,安卓狀態(tài)欄的高度可通過(guò)StatusBar.currentHeight
獲取竟闪。 - 4.1.2 iOS 手機(jī)狀態(tài)欄
(1)在 iOS 平臺(tái)上,取得的屏幕高度就是實(shí)際可使用的高度;
(2)如果從第 0 行開(kāi)始排列組件時(shí)杖狼,組件會(huì)緊貼著手機(jī)屏幕的最上沿顯示瘫怜。如果狀態(tài)欄沒(méi)有被隱藏,它將覆蓋在第 0 行組件的上方;
(3)如果不想設(shè)置狀態(tài)欄隱藏本刽,則應(yīng)當(dāng)空出狀態(tài)欄的顯示區(qū)域鲸湃。但可以為這個(gè)區(qū)域設(shè)置背景色,以使整個(gè)界面風(fēng)格統(tǒng)一子寓。
4.2 StatusBar樣式
Default status bar style (dark for iOS, light for Android)
在Android上默認(rèn)的樣式是白色暗挑,而IOS是黑色,所以當(dāng)我們?cè)诳缙脚_(tái)設(shè)置StatusBar樣式時(shí)斜友,避免使用defult
炸裆,應(yīng)該直接使用light-content
、dark-content
4.3 StatusBar背景色
Android上可通過(guò)backgroundColor
設(shè)置背景色鲜屏,而IOS無(wú)此屬性烹看,需要通過(guò)手動(dòng)設(shè)置20dp高度的顏色作為背景色。另外項(xiàng)目中有個(gè)特殊需求洛史,需要StatusBar的顏色是漸變的惯殊,這時(shí)安卓上需要讓背景色透明,設(shè)置同等高度的漸變色來(lái)替代也殖。
5. 閃屏土思、廣告頁(yè)面
因?yàn)殚W屏涉及端代碼的編寫(xiě),自然需要重新開(kāi)發(fā)。
廣告頁(yè)面則有兩個(gè)思路:可以在端開(kāi)發(fā)己儒、也可以放在RN:
- 在端的好處在于RN的首頁(yè)是"真首頁(yè)"崎岂,在啟動(dòng)應(yīng)用顯示閃屏的時(shí)候,為預(yù)加載首頁(yè)提供了時(shí)間闪湾,讓首頁(yè)出現(xiàn)的時(shí)間大大提升冲甘;缺點(diǎn)就是不夠靈活,如果將廣告圖換一個(gè)表現(xiàn)形式途样,需要重新發(fā)包损合。
- 在RN的好處自然就是靈活,可以頻繁的變換廣告形式也無(wú)需更新App娘纷,另外如果是復(fù)雜的廣告形式嫁审,對(duì)于前端開(kāi)發(fā)人員,開(kāi)發(fā)端代碼的陳本要遠(yuǎn)高于開(kāi)發(fā)RN赖晶;缺點(diǎn)就是RN的首頁(yè)變成了廣告頁(yè)律适,而不是我們想要的首頁(yè),這樣啟動(dòng)圖無(wú)法爭(zhēng)取到首頁(yè)的訪問(wèn)的時(shí)間遏插,在首頁(yè)呈現(xiàn)的時(shí)間上肯定比上面的方法慢一些捂贿。
6. 輪播組件
這個(gè)問(wèn)題涉及到了第三方組件的兼容性。
之前在IOS上用的Carousel
組件在Android會(huì)有一些異常的表現(xiàn)胳嘲。解決方案有兩種:
- 修改組件源碼厂僧,修復(fù)異常;
- 用一個(gè)兼容性沒(méi)問(wèn)題的同類組件替換
在解決過(guò)程中兩種辦法都嘗試過(guò)了牛,都可行颜屠。從這里也獲取一個(gè)經(jīng)驗(yàn),之后在選擇三方庫(kù)的時(shí)候鹰祸,盡量選擇更新時(shí)間近甫窟、star數(shù)量高、仍在維護(hù)蛙婴、大廠出品的粗井。
7. 監(jiān)聽(tīng)物理回退
由于安卓機(jī)子有一個(gè)物理回退鍵,如果在RN項(xiàng)目中不對(duì)其處理街图,則點(diǎn)擊物理回退鍵就會(huì)關(guān)閉App浇衬,而我們的預(yù)期是希望點(diǎn)擊后回退上一頁(yè)。
首頁(yè)我們要知道餐济,點(diǎn)擊物理回退耘擂,其實(shí)會(huì)調(diào)用端的onBackPressed
方法,所以我們需要判斷如果是RN頁(yè)面颤介,應(yīng)該讓RN代碼自行決定處理方式梳星,當(dāng)然這層邏輯其實(shí)初始化項(xiàng)目就做好了:
@Override
public void onBackPressed() {
//super.onBackPressed();
if(mReactInstanceManager != null){
mReactInstanceManager.onBackPressed();
}else{
super.onBackPressed();
}
}
這樣我們只需要在RN項(xiàng)目里監(jiān)聽(tīng)這個(gè)回退赞赖,然后處理自己想要的邏輯就行了滚朵,代碼大致如下:
componentDidMount() {
if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', this._handleBack.bind(this));
}
}
componentWillUnmount() {
if (Platform.OS === 'android') {
BackHandler.removeEventListener('hardwareBackPress', this._handleBack.bind(this));
}
}
只需要在程序入口做一次監(jiān)聽(tīng)冤灾,后續(xù)頁(yè)面無(wú)需處理。
8. Modal
Android平臺(tái)Modal
組件中的onRequestClose
是一個(gè)必傳參數(shù)辕近,IOS則不需要韵吨。
可以在Modal的文檔上可以看到關(guān)于onRequestClose
參數(shù)的描述:
On the Android platform, this is a required function.
至于為什么只有安卓平臺(tái)需要,我猜大概率和物理回退的相關(guān)處理有關(guān)系移宅。
9. 自定義字體的高度問(wèn)題
目前項(xiàng)目中引入了兩個(gè)外部字體:思源宋和閱文定制的數(shù)字字體归粉。
引入字體會(huì)有一定高度的上下pandding,樣式處理上也有別于常規(guī)字體漏峰,需要設(shè)置lineHeight
糠悼、height
更好的定位位置。
10. Text樣式之ellipsizeMode屬性
Text
樣式中的ellipsizeMode
屬性 , 用來(lái)配合numberOfLines
顯示不完全省略的位置, 可選值'head'
, 'middle'
,'tail'
,'clip'
浅乔,而其中'clip'
只能在IOS中使用倔喂,安卓平臺(tái)會(huì)報(bào)錯(cuò)。
11. popover組件
這個(gè)問(wèn)題同問(wèn)題6靖苇,一樣涉及到了第三方組件的兼容性席噩。
其中比較核心的問(wèn)題是安卓平臺(tái)上不支持shadow陰影屬性的設(shè)置,這個(gè)問(wèn)題在下一條會(huì)提到贤壁。
另外這個(gè)庫(kù)的開(kāi)發(fā)時(shí)間比較早且已經(jīng)無(wú)人維護(hù)悼枢,所以類似這樣的庫(kù)以后應(yīng)該規(guī)避。
至于最終的解決方案脾拆,其實(shí)是加了一層蒙層來(lái)替代陰影的效果馒索。
12. 陰影屬性
在IOS上可以通過(guò)如下設(shè)置陰影:
shadowOffset: {width: 0, height: 0},
shadowColor: 'black',
shadowOpacity: 1,
shadowRadius: 5
而Android上并不支持shadow
相關(guān)的屬性,只提供了一個(gè)elevation
屬性名船,使用方法如下:
backgroundColor: 'black',
elevation: 20,
elevation顧名思義就是 “仰角”双揪,通過(guò)為視圖增加 “仰角” 方式來(lái)提供陰影,仰角越大包帚,陰影越大渔期。
但elevation
的設(shè)置比較局限,設(shè)置無(wú)法設(shè)置offset
渴邦。如果需要更好的效果疯趟,還是需要通過(guò)其它方式去實(shí)現(xiàn),svg谋梭、漸變等信峻,當(dāng)然也有這樣庫(kù)提供了解決方案,像react-native-shadow瓮床、react-native-cardview都是值得參考的盹舞。
13. 觸摸點(diǎn)擊
目前關(guān)于觸摸點(diǎn)擊有以下幾種方式:
- TouchableHighlight
? What it does: Darkens or lightens the background of the element when pressed.
? When to use it: On iOS for touchable elements or buttons that have a solid shape or background, and on ListView items.
- TouchableOpacity
? What it does: Lightens the opacity of the entire element when pressed.
? When to use it: On iOS for touchable elements that are standalone text or icons with no backgroundcolor.
- TouchableNativeFeedback
? What it does: Adds a ripple effect to the background when pressed.
? When to use it: On Android for almost all touchable elements.
安卓平臺(tái)推薦用TouchableNativeFeedback
14. TextInput
TextInput在安卓平臺(tái)默認(rèn)有下劃線且框內(nèi)文字樣式也有問(wèn)題产镐,需要做如下兼容處理:
underlineColorAndroid = "transparent" //android需要設(shè)置下劃線為透明才能去掉下劃線
style={{padding:0}}// 矯正樣式
15. ScrollView
我們觀察Android和IOS默認(rèn)的下拉刷新表現(xiàn)形式是不一樣的,這是因?yàn)榘沧可系?code>ScrollView沒(méi)有IOS的彈性bounces
踢步,這也使得我們通過(guò)onScroll
癣亚、onScrollEndDrag
獲取X軸、Y軸距離做的一些判斷會(huì)有所區(qū)別获印。
16. react-native-scrollable-tab-view組件卡頓
這個(gè)組件在切換兩個(gè)數(shù)據(jù)量稍大的Tab時(shí)述雾,就會(huì)有明顯的卡頓,開(kāi)始以為是性能問(wèn)題導(dǎo)致動(dòng)畫(huà)卡頓兼丰,后來(lái)debug發(fā)現(xiàn)是組件在切換回已經(jīng)render的view玻孟,還做了一次render,導(dǎo)致阻塞了動(dòng)畫(huà)的執(zhí)行鳍征,解決辦法是通過(guò)shouldComponentUpdate
判斷是否有必要render黍翎,當(dāng)然也可以使用PureComponent來(lái)實(shí)現(xiàn)。