React Native填坑之旅--布局篇

代碼在這里:
https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller

回頭看看RN的填坑之旅系列,發(fā)現(xiàn)一路寫下來都是我在開發(fā)中遇到的問題如何解決的蔑水。興之所至锌云,不問順序腰素。于是出現(xiàn)一個問題书幕,填坑系列和學(xué)習(xí)知識的順序不是很一致嚎花。比如今天要說的布局問題悼瘾。其實在一個app開發(fā)之前龟再,就應(yīng)該有所了解书闸。否則的話每次看到的<View style={{flex: 1}} />代表的是什么呢?上來就是一個疑問利凑。

在這個系列進行到一定程度的時候捺信,我會花時間重新整理全系列的文章擂煞,讓各位可以按照知識本來學(xué)習(xí)的順序循序漸進的學(xué)習(xí)React Native的知識,避免在開發(fā)中遇到不應(yīng)該遇到的問題。

正文開始宿刮。本文主要是介紹基礎(chǔ)知識校哎,但是不適用基礎(chǔ)的代碼吏夯。所以静浴,如果你在看的時候有什么問題弄不清楚的話,隨時查閱官網(wǎng)适荣。那么問題是什么现柠?三個View放在一個父View里顯示出來會是設(shè)么樣子的?這五個子View每次只要顯示一個的話應(yīng)該如何處理弛矛?

首先我們先來一點開胃小菜:

NavigationBar的布局

默認(rèn)的情況下NavigationBar的左側(cè)回退按鈕看起來是這樣的:

NavigationBar

圖中可見够吩,按鈕緊貼上沿。這個時候的布局是這樣的:

    <TouchableHighlight
        style={{backgroundColor: 'red', width: 50}}
        onPress={() => {
            if (index > 0) {
                navigator.pop();
            }
        }}>
        <Text style={{
            marginLeft: 10,
            backgroundColor: 'yellow'
        }}>Back</Text>
    </TouchableHighlight>

如何讓NavigationBar的按鈕豎直居中呢丈氓?不要想在TouchableHighlight上添加的樣式可以起作用周循。只有在外層再包裹一層View才可以。并給外層的View設(shè)置樣式万俗,讓其中的內(nèi)容豎直居中才可以湾笛。

    <View style={{flex:1, justifyContent: 'center'}}>
        <TouchableHighlight
            style={{backgroundColor: 'red', width: 50}}
            onPress={() => {
                if (index > 0) {
                    navigator.pop();
                }
            }}>
            <Text style={{
                marginLeft: 10,
                backgroundColor: 'yellow'
            }}>Back</Text>
        </TouchableHighlight>
    </View>

開始填坑

下面要實現(xiàn)一個效果。我們已經(jīng)有三個橫向排列的闰歪,等寬度的View嚎研。對應(yīng)的還有三個按鈕,每一個按鈕對應(yīng)一個View课竣。但是嘉赎,不要三個View都顯示出來置媳。每次只顯示一個于樟。點一個按鈕就顯示出對應(yīng)的View來公条。

Flex的方向

先來看看制造問題的代碼重現(xiàn):

  <View style={{flex: 1, marginTop: 64}}>
    <View style={{flex: 1, backgroundColor: 'red'}}></View>
    <View style={{flex: 1, backgroundColor: 'orange'}}></View>
    <View style={{flex: 1, backgroundColor: 'yellow'}}></View>
  </View>

看起來是這樣的:

column layout

默認(rèn)的,在一個View里的子View都是豎直依次排列的迂曲。

React Native使用Flexbox來實現(xiàn)布局的靶橱。Flexbox兩個方向,一個是column路捧,一個是row关霸。

  • column默認(rèn)的flexbox方向,是豎直的杰扫,從上到下的方向队寇。如上例的圖片中截面里紅、橙章姓、黃三個顏色的view排列的方向佳遣。
  • row是橫向的,從左到右的方向凡伊。

我們來看看flexbox在row方向的樣子:

  <View style={{flex: 1, flexDirection: 'row', marginTop: 64}}>
    <View style={{flex: 1, backgroundColor: 'red'}}></View>
    <View style={{flex: 1, backgroundColor: 'orange'}}></View>
    <View style={{flex: 1, backgroundColor: 'yellow'}}></View>
  </View>
layout row

添加了按鈕以后的界面看起來是這樣的:


with buttons

JustifyContent & AlignItems

在flow已經(jīng)決定了子view排列的方向的時候零渐。還需要進一步的調(diào)整子view的時候就會用到justifyContentalignItems

在和flow指定的方向同一方向上調(diào)整的時候使用justifyContent系忙。flow指定的方向為主方向诵盼。要在次方向上指定子view如何排列就是用alignItems。如果flexDirection指定的是column(豎直方向)银还,那么主方向就是豎直的风宁,次方向就是水平的。

Flex的值

上面介紹了flex的方向蛹疯,這里來說說flex的值杀糯。

在兄弟姐妹關(guān)系的View中,如果他們的flex都是1苍苞,那么他們評分父view的空間固翰。如果,有一個flex的值是2羹呵,那么就是說這個子View的寬(高)是其他的兄弟姐妹的2倍骂际。

在flex為0的時候,View的寬高就完全需要靠自己了冈欢。也就是這個view的寬和高需要設(shè)置具體的數(shù)值歉铝。系統(tǒng)不會替你計算。

如果flow為-1凑耻,那么View的寬度和高度太示,由width和height決定柠贤。*在空間不夠的情況下,view的寬度和高度會縮小到minWidthminHeight类缤。

看看我們要實現(xiàn)的效果和代碼

效果:

效果

實現(xiàn)代碼:

export default class FlexDemo extends React.Component {
  _onPress: (buttonIndex: number) => void;

  constructor(props) {
    super(props);
    this.state = {
      view1Style: {flex: 1, width: 0}, // If flex is 1, width does not work.
      view2Style: {flex: 0, width: 0},
      view3Style: {flex: 0, width: 0}
    };

    this._onPress = this._onPress.bind(this);
  }

  _onPress(buttonIndex) {
    switch(buttonIndex) {
      case 0:
        this.setState({
          view1Style: {flex: 1, width: 0}, // If flex is 1, width does not work.
          view2Style: {flex: 0, width: 0},
          view3Style: {flex: 0, width: 0}
        });
        break;
      case 1:
        this.setState({
          view1Style: {flex: 0, width: 0}, // If flex is 1, width does not work.
          view2Style: {flex: 1, width: 0},
          view3Style: {flex: 0, width: 0}
        });
        break;
      case 2:
        this.setState({
          view1Style: {flex: 0, width: 0}, // If flex is 1, width does not work.
          view2Style: {flex: 0, width: 0},
          view3Style: {flex: 1, width: 0}
        });
        break;
      default:
        this.setState({
          view1Style: {flex: 1, width: 0}, // If flex is 1, width does not work.
          view2Style: {flex: 0, width: 0},
          view3Style: {flex: 0, width: 0}
        });
        break;
    }
  }

  render() {
    return (
  <View style={{flex: 1, flexDirection: 'row', marginTop: 64}}>
    <View key="view1" style={[this.state.view1Style, {backgroundColor: 'red'}]}></View>
    <View key="view2" style={[this.state.view2Style, {backgroundColor: 'orange'}]}></View>
    <View key="view3" style={[this.state.view3Style, {backgroundColor: 'yellow'}]}></View>

    <View style={{
      flex: 1,
      flexDirection: 'row',
      justifyContent: 'space-between',
      alignItems: 'center',
      position: 'absolute',
      height: 50,
      left:0,
      right: 0,
      bottom: 0,
      backgroundColor: 'black',
      opacity: 0.6
    }}>
      <View style={{flex: 1, justifyContent:'center'}} key='b1'>
        <TouchableOpacity
          style={styles.button}
          onPress={()=>this._onPress(0)}>
          <Text style={styles.buttonText}>1</Text>
        </TouchableOpacity>
      </View>
      <View style={{flex: 1, justifyContent: 'center'}} key='b2'>
        <TouchableOpacity
          style={styles.button}
          onPress={()=>this._onPress(1)}>
          <Text style={styles.buttonText}>2</Text>
        </TouchableOpacity>
      </View>
      <View style={{flex: 1, justifyContent: 'center'}} key='b3'>
        <TouchableOpacity
          style={styles.button}
          onPress={()=>this._onPress(2)}>
          <Text style={styles.buttonText}>3</Text>
        </TouchableOpacity>
      </View>
    </View>
  </View>
    );
  }
};

實現(xiàn)原理:
如何去改變一個組件的外觀布局臼勉?自然少不了setState方法。一開始餐弱,我們就把這幾個子view的布局都放在state里宴霸。

在下面的三個按鈕的點擊事件中,設(shè)置不同的state膏蚓,那么赤瓢谢、橙和黃三個view就會發(fā)生變化。

前面提高flex的值為0的時候widthheight起作用驮瞧,flex不為0的時候不起作用氓扛。這就是核心算法之所在了。在一開始讓紅色的view的flex為1论笔。其他的view的flex為0采郎,并且寬度也為0

之后每次點擊了一個按鈕的時候翅楼,對應(yīng)的view的布局設(shè)置為flex等于1尉剩,其他的view的flex為0。這樣就實現(xiàn)了上面的效果毅臊。

小小的練習(xí)

最后留一個練習(xí)題理茎,上面的效果對于一個簡單的View來說也可以使用conditional render來搞定。那么就請你做一個這樣的練習(xí)管嬉。

最后

上面的講解都是我遇到的問題的講解皂林。包含了一些flexbox布局的基礎(chǔ),但是更難理解一下蚯撩。React Native的布局包括的東西還有很多础倍。后續(xù)會在本文或者系列的其他的文章中講解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胎挎,一起剝皮案震驚了整個濱河市沟启,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌犹菇,老刑警劉巖德迹,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異揭芍,居然都是意外死亡胳搞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肌毅,“玉大人筷转,你說我怎么就攤上這事⌒” “怎么了呜舒?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長摊滔。 經(jīng)常有香客問我阴绢,道長店乐,這世上最難降的妖魔是什么艰躺? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮眨八,結(jié)果婚禮上腺兴,老公的妹妹穿的比我還像新娘。我一直安慰自己廉侧,他們只是感情好页响,可當(dāng)我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著段誊,像睡著了一般闰蚕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上连舍,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天没陡,我揣著相機與錄音,去河邊找鬼索赏。 笑死盼玄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的潜腻。 我是一名探鬼主播埃儿,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼融涣!你這毒婦竟也來了童番?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剃斧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后专普,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悯衬,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了筋粗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片策橘。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖娜亿,靈堂內(nèi)的尸體忽然破棺而出丽已,到底是詐尸還是另有隱情,我是刑警寧澤买决,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布沛婴,位于F島的核電站,受9級特大地震影響督赤,放射性物質(zhì)發(fā)生泄漏嘁灯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一躲舌、第九天 我趴在偏房一處隱蔽的房頂上張望丑婿。 院中可真熱鬧,春花似錦没卸、人聲如沸羹奉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诀拭。三九已至,卻和暖如春煤蚌,著一層夾襖步出監(jiān)牢的瞬間耕挨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工铺然, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留俗孝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓魄健,卻偏偏與公主長得像赋铝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沽瘦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容