React Native元件(二)View元件解析

劉望舒發表於2017-06-29

相關文章
React Native探索系列
React Native元件系列

前言

瞭解了RN的元件的生命週期後,我們接著來學習RN的具體的元件。View元件是最基本的元件,也是首先要掌握的元件,這一篇我們來學習View元件。

1.概述

View元件是RN中最基本的元件,絕大部分的元件都繼承了View元件的屬性,所以學習其他元件前,要首先掌握View元件。
View元件是一個支援Flexbox佈局、樣式、一些觸控處理的容器,它可以放到其它的元件裡,也可以有任意多個任意型別的子元件。View元件對應著多個平臺的檢視,比如Android的View以及iOS的UIView。
由於View元件的屬性非常多,這裡主要介紹一些常用的屬性。

2.style屬性

style屬性作為元件屬性中的一種,它包含了多種屬性,這裡對它們意義進行講解。

2.1 Flexbox

View元件的Flexbox屬性這裡就不再介紹了,詳細請看React Native探索(四)Flexbox佈局詳解這一篇文章。正是因為View元件提供了Flexbox屬性,因此,繼承了View元件的其他元件也都具有Flexbox屬性。

2.2 shadow相關 (iOS)

View元件提供了四種陰影屬性如下表:

樣式名 引數屬性 說明
shadowColor color 設定陰影顏色
shadowOffset {width: number, height: number} 設定陰影位移值
shadowOpacity number 設定陰影透明度
shadowRadius number 設定陰影模糊半徑

設定View元件的陰影屬性並沒有什麼意義,在View元件中定義這些樣式是為了讓繼承它的元件去各自實現這些效果,比如Text元件。需要注意的是隻有iOS平臺能使用shadow屬性。

2.3 elevation (Android)

elevation取值為number。Android平臺沒有shadow來設定陰影,但是,可以用elevation屬性來間接的設定陰影。它使用Android原生的 elevation API來設定元件的高度,這樣就會在介面上呈現出陰影的效果,此屬性僅支援Android 5.0及以上版本。

import React, {Component} from 'react';
import {AppRegistry, StyleSheet, View} from 'react-native';
class ViewApp extends Component {
    render() {
        return (
             <View style={{flex: 1, justifyContent: 'center',
                   alignItems:'center',backgroundColor:'white'}}>
                   <View style={styles.shadow}/>
             </View>
        );
    }
}
const styles = StyleSheet.create({
    shadow: {
        height: 120,
        width: 120,
        backgroundColor: 'black',
        elevation: 20,
        shadowOffset: {width: 0, height: 0},
        shadowColor: 'black',
        shadowOpacity: 1,
        shadowRadius: 5
    }
});
AppRegistry.registerComponent('ViewSample', () => ViewApp);複製程式碼

在iOS平臺執行如上程式碼,效果為:

在Android平臺執行效果則為:

很明顯,elevation的效果遠遠不及shadow,這時我們可以採用第三方庫react-native-shadow

2.4 border相關

borderStyle的取值為 enum('solid', 'dotted', 'dashed'),用來設定邊框的風格,三個值分別對應著實線邊框、點狀邊框和虛線邊框,預設值為solid。
除了可以設定邊框的風格,還可以用定義邊框的顏色和邊框的圓角。邊框的顏色設定有borderColor、borderTopColor 、borderRightColor 、borderBottomColor 、borderLeftColor,取值都為string,通常情況下用borderColor就足夠了。
邊框的圓角設定有borderRadius 、borderTopLeftRadius 、borderTopRightRadius 、borderBottomLeftRadius 、borderBottomRightRadius,取值為number。

import React, {Component} from 'react';
import {AppRegistry, StyleSheet, View, Text} from 'react-native';
class ViewApp extends Component {
    render() {
        return (
            <View style={styles.viewStyle}>
                <View style={styles.viewTextStyle}>
                    <Text style={styles.textStyle}>border</Text>
                </View>
            </View>
        );
    }
}
const styles = StyleSheet.create({
    viewStyle: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'white'
    },
    viewTextStyle: {
        justifyContent: 'center',
        alignItems:'center',
        width: 80,
        height: 50,
        borderWidth:1,
        borderStyle:'dashed',
        borderRadius:10,
        borderColor:'red'
    },
    textStyle: {
        fontSize: 20
    }
});
AppRegistry.registerComponent('ViewSample', () => ViewApp);複製程式碼

上面的例子用到了border相關的屬性。需要注意的是,如果不設定borderRadius,borderStyle的dotted和dashed的取值會無效,效果如下圖所示。

2.5 transform

transform的取值為:

[{perspective: number}, 
{rotate: string},
{rotateX: string},
{rotateY: string},
{rotateZ: string},
{scale: number},
{scaleX: number}, 
{scaleY: number},
{translateX: number},
{translateY: number}, 
{skewX: string},
{skewY: string}]複製程式碼

transform的取值總的來說,共分為四種型別:translate、scale、rotate和skew,分別用來設定View元件的平移、縮放、旋轉和傾斜。
View元件用transform屬性的效果不是很明顯,絕大部分元件都繼承了View元件的transform屬性,比如Text。我們改寫2.4小節中的例子,將textStyle改為如下程式碼:

textStyle: {
        fontSize: 20,
        transform: [{rotate: '40deg'}, {scale: 0.9}, {translateY: 10}]
    }複製程式碼

執行效果如下:


對於translate、scale、rotate的效果,Android開發者會非常熟悉,那麼rotate和skew有什麼區別呢?再來修改textStyle:

textStyle: {
        fontSize: 20,
        transform:[{skewY:'40deg'}]
    }複製程式碼

執行效果如下:

從兩個圖的效果可以看出,rotate和skew的區別就是:rotate在旋轉的同時,不會改變Text元件的形態,而skew則隨著傾斜角度的改變,Text元件的形態也會發生相應的變化。如果我們加大skew的傾斜角度,比如60deg,Text元件的形態則會變為下圖的效果。

2.6 overflow (iOS)

overflow取值為enum('visible', 'hidden')。它用來定義當View元件的子元件的寬高超過View元件寬高時的行為,預設值為hidden,即隱藏超出的部分。overflow只在iOS平臺有效,在Android平臺即使設定overflow為visible,呈現的還會是hidden的效果。

2.7 backgroundColor

backgroundColor取值為string。它用來設定背景顏色,預設的顏色為非常淺的灰色,只有Text和TextInput元件繼承了父元件的背景顏色,其他的元件都要設定自己的背影顏色。

2.8 opacity

opacity 的取值為0到1,當值為0時,表示元件完全透明,而值為1時,則表示元件完全不透明。

3.屬性

3.1 觸控事件回撥函式

觸控事件回撥函式用來處理使用者的觸控螢幕操作,一般情況下,觸控事件都是在其他元件中完成的。關於觸控事件是一個比較大的知識點,這裡只介紹這些觸控事件回撥函式的作用。

  • onStartShouldSetResponder: 觸控事件為touchDown時,是否申請成為事件響應者,接收觸控事件。如果返回true,則表示元件需要成為事件響應者。
  • onStartShouldSetResponderCapture:觸控事件為touchDown時,是否要攔截此事件,阻止子元件接收該事件,如果返回true,則表示要進行攔截。
  • onMoveShouldSetResponder : 觸控事件為TouchMove時,是否申請成為事件響應者,接收觸控事件。如果返回true,則表示元件需要成為事件響應者。
  • onMoveShouldSetResponderCapture :觸控事件為TouchMove時,是否要攔截此事件,阻止子元件接收該事件。
  • onResponderGrant: 申請成為事件響應者成功,元件開始接收觸控事件 。
  • onResponderReject: 申請成為事件響應者失敗,其他元件正在進行事件處理 。
  • onResponderMove:觸控手指移動的事件(TouchMove)。
  • onResponderTerminationRequest:在元件成為事件響應者期間,其他元件申請成為響應者,返回為true,則表示同意釋放響應者角色。
  • onResponderTerminate:如果元件釋放響應者角色,會回撥該函式,通知元件事件響應處理被終止了。這個回撥也會發生在系統直接終止元件的事件處理,例如使用者在觸控操作過程中,突然來電話的情況。
  • onResponderRelease:表示觸控完成(touchUp)的時候的回撥,表示使用者完成了本次的觸控互動。

3.2 pointerEvents

pointerEvents的取值為enum('box-none', 'none', 'box-only', 'auto') 。它用來控制當前檢視是否可以作為觸控事件的目標。
在開發中,很多元件是被佈局到手機介面上的,其中一些元件會遮蓋住它的位置下方的元件,有一些場景需要被遮蓋住的元件來處理事件。比如一個地圖元件上覆蓋了一個影象元件用來顯示資訊,但是我們不想這個影象元件影響使用者的手指拖動地圖的操作,這時就可以使用影象元件從View元件繼承得到的pointerEvents屬性來解決這個問題。
pointerEvents的取值含義如下所示:

  • none:元件自身不能作為觸控事件的目標,交由父元件處理。
  • box-none:元件自身不能作為觸控事件的目標,但其子元件可以。
  • box-only:元件自身可以作為觸控事件的目標,但其子元件不能。
  • auto:元件可以作為觸控事件的目標。

3.3 removeClippedSubviews

removeClippedSubviews的取值為bool。它的一個特殊的與效能優化相關的屬性,通常在ListView和ScrollView中使用,當元件有很多子元件不在螢幕顯示範圍時,可以將removeClippedSubviews設定為true,允許釋放不在顯示範圍子元件,從而優化了效能。需要注意的是,要想讓此屬性生效,要確保overflow屬性為預設的hidden。

3.4 動畫相關

needsOffscreenAlphaCompositing (Android)
needsOffscreenAlphaCompositing的取值為bool,是Android平臺獨有的屬性。它用來決定檢視是否要先離屏渲染再進行半透明度處理,來確保顏色和混合效果正確。為了正確的顯示透明表現而進行離屏渲染會帶來極大的開銷,對於非原生開發者來說很難除錯,因此,它的預設值為false。

renderToHardwareTextureAndroid (Android)
renderToHardwareTextureAndroid的取值為bool,同樣是是Android平臺獨有的屬性。它用來決定檢視是否要把它本身(以及所有的子檢視)渲染到一個GPU上的硬體紋理中。
在Android平臺上,這對於只修改透明度、旋轉、位移和縮放的動畫和互動是很有用的:檢視不必每次都重新繪製,顯示列表也不需要重新執行,紋理可以被重用於不同的引數。負面作用是這會大量消耗視訊記憶體,所以當互動/動畫結束後應該把此屬性設定回false。

shouldRasterizeIOS (iOS)
shouldRasterizeIOS的取值為bool,是iOS平臺獨有的屬性。它決定檢視是否需要在被混合之前繪製到一個點陣圖上。
這對於動畫和互動來說是有很有用的,它不會修改這個元件的尺寸和它的子元件。舉例來說,當我們移動一個靜態檢視的位置的時候,柵格化允許渲染器重用靜態檢視的快取點陣圖,並快速合成。
柵格化會導致離屏的繪圖傳遞,點陣圖會消耗記憶體。所以使用此屬性需要進行充分的測試和評估。

還有一些View屬性這裡沒有給出,比如RN為了方便失能人士使用手機而提供的相關屬性等等,具體的屬性請檢視官方文件

參考資料
官方文件
《React Native跨平臺移動應用開發》第二版
React Native 中如何給 Navigator 新增一條合格的陰影
React Native 觸控事件處理詳解
React Native中pointerEvent屬性


歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。

相關文章