Para criar um layout no React Native vamos usar o Flexbox, mas nem todos os recursos que estão na especificação do Flexbox, estão incluídos. :/
Stack Layout
Esse layout na orientação vertical empilha elementos em cima uns dos outros, enquanto que para a orientação horizontal, os elementos são colocados lado a lado. Vejamos a orientação vertical:
import React, { Component } from 'react';
import { StyleSheet, View, Dimensions } from 'react-native';
const { height } = Dimensions.get('window');
const boxCount = 3;
const boxHeight = height / boxCount;
export default class VerticalStackLayout extends Component {
render() {
return (
<View style={styles.container}>
<View style={[styles.box, styles.box1]}></View>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box, styles.box3]}></View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column'
},
box: { height: boxHeight },
box1: { backgroundColor: 'red' },
box2: { backgroundColor: 'blue' },
box3: { backgroundColor: 'green' }
});
No elemento pai(container), usaremos a propriedade flex
. O valor é a quantidade de espaço que ele ocupará. Sendo 1, isso significa que ele ocupará todo o espaço disponível, desde que o elemento não tenha irmãos.
A propriedade flexDirection
permite que você especifique o eixo principal do layout. Por padrão, isso é definido como column
. O valor de flexDirection
sendo column
, significa que os elementos filhos serão dispostos verticalmente (empilhados uns sobre os outros). Se o valor for row
, significa que os filhos serão dispostos horizontalmente (lado a lado).
O exemplo acima mostra a maneira manual. O uso de Dimensions
para calcular a largura ou a altura dos elementos falhará se o seu aplicativo suportar a orientação do dispositivo retrato e paisagem. Isso ocorre porque assim que o usuário virar seu dispositivo, a largura ou a altura que você calculou não serão atualizadas. Exemplo mudando a orientação:
O Flexbox faz a computação para você, se você fornecer os valores corretos. Para alcançar o mesmo layout acima, sem usar o Dimensions
, tudo o que você precisa fazer é especificar flex: 1
para todas as caixas, em vez de especificar o valor para a propriedade height
:
box: {
flex: 1
},
Agora podemos evoluir esse layout com o uso do flex
nos elementos irmãos.
//header
box1: {
flex: 1,
backgroundColor: 'red',
},
//content
box2: {
flex: 10,
backgroundColor: 'blue',
},
//footer
box3: {
flex: .5,
backgroundColor: 'green',
}
Tenha em mente que se conteúdo interno for maior do que a altura máxima disponível, o resto do seu conteúdo será oculto. Se você espera que seu conteúdo ultrapasse esse limite, você pode usar o componente de ScrollView
, incorporado para gerar automaticamente uma barra de rolagem vertical, como em uma página da web.
Horizontal
Para implementar a orientação horizontal, basta mudar o flexDirection
para row
. Colocando o valor de flex
do box novamente para 1, isso resulta em que 3 colunas ocuparam toda a tela.
container: {
flex: 1,
flexDirection: 'row',
},
box: { flex: 1 },
box1: { backgroundColor: 'red' },
box2: { backgroundColor: 'blue' },
box3: { backgroundColor: 'green' }
Justificando o conteúdo
Se você deseja controlar a distribuição dos elementos filhos, é necessário utilizar a propriedade justifyContent
no elemento pai.
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-start',
},
box: { height: boxHeight },
box1: { backgroundColor: 'red' },
box2: { backgroundColor: 'blue' },
box3: { backgroundColor: 'green' }
Abaixo vamos ver os 5 valores possíveis que podem ser usados com essa propriedade. Você não conseguirá ver nenhuma diferença se o valor da propriedade flex
for 1, para cada um dos elementos filhos, porque eles ocupariam todo o espaço disponível.
flex-start
: os elementos filhos são alinhados em direção ao ponto de partida. Observe o fundo branco logo abaixo do último filho. É assim que você sabe que isso está sendo usado o flex-start.flex-end
: os elementos filhos são alinhados em direção à linha final. Desta vez o espaço vazio estará no ponto de partida.center
: os elementos filhos são colocados em direção ao centro. Desta vez, o espaço vazio é dividido igualmente entre o ponto inicial e final.space-around
: os elementos filhos são distribuídos de modo que haveria espaço igual em cada um deles. Isso significa que os elementos na parte externa teriam menos espaço no lado externo e o espaço entre os dois filhos é duplicado.space-between
: os elementos filhos são distribuídos de modo que haveria uma quantidade igual de espaço entre cada um deles.
Como você pode ter notado, cada um desses valores de estilo dependem da altura ou largura dos elementos filhos. Depende da largura, se flexDirection
for row
e na altura se flexDirection
for column
.
Por exemplo, space-between
realmente não terá qualquer efeito em um Stack layout vertical se cada um dos elementos filhos estiver usando flex
para controlar a altura. Isso ocorre porque não haverá mais espaço entre cada elemento para ocupar.
Alinhando os itens
justifyContent
e alignItems
podem parecer como se estivessem fazendo o mesmo. Eles também compartilham três valores possíveis: flex-start
, flex-end
e center
, com a adição do valor stretch
na propriedade alignItems
.
A principal diferença entre justifyContent
e alignItems
é o eixo em que os elementos filhos são distribuídos. Como você vimos anteriormente, justifyContent
sempre usa o eixo primário ao distribuir elementos filhos. Mas alignItems
usa o eixo oposto ao primário.
Nós já sabemos que o eixo é determinado pelo flexDirection
que foi definido. Então, se flexDirection
for row
, o eixo primário flui da esquerda para a direita. Isso significa que o eixo transversal irá fluir de cima para baixo. Por outro lado, se flexDirection
é column
que o eixo transversal irá fluir da esquerda para a direita.
Abaixo vamos ver alguns exemplos com justifyContent
e alignItems
implementados lado a lado com o flexDirection
de row
. O primeiro usa justifyContent
enquanto o segundo usa alignItems
.
flex-start
: o posicionamento dos elementos é o mesmo, por isso que a implementação de alignItems e justifyContent, são iguais.flex-end
: agora começamos a ver uma diferença. Com justifyContent, os elementos filhos irão para o final da primeira linha, enquanto com alignItems os elementos filhos irão estar no início da última linha.center
: tem a mesma ideia do resto dos valores que usamos até agora. Com justifyContent, os itens são centrados no eixo x enquanto com alignItems, os itens estão centrados no eixo y.stretch
: use para que os elementos filhos se estendam para preencher o elemento pai. Este é o valor padrão paraalignItems
, portanto, especificar esse valor é opcional.
Abaixo temos o trecho de código usado nos exemplos acima. Basta alterar os valores para o flexDirection
, justifyContent
e alignItems
:
import React, { Component } from 'react';
import {
StyleSheet,
View
} from 'react-native';
export default class AlignItems extends Component {
render() {
return (
<View style={styles.wrapper}>
<View style={styles.container}>
<View style={[styles.box, styles.box1]}></View>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box, styles.box3]}></View>
</View>
<View style={styles.container2}>
<View style={[styles.box, styles.box1]}></View>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box, styles.box3]}></View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
flex: 1
},
container: {
flex: .5,
flexDirection: 'row',
justifyContent: 'flex-start',
borderBottomWidth: 1,
borderBottomColor: '#000'
},
container2: {
flex: .5,
flexDirection: 'row',
alignItems: 'flex-start'
},
box: {
width: 100,
height: 100
},
box1: { backgroundColor: '#2196F3' },
box2: { backgroundColor: '#8BC34A' },
box3: { backgroundColor: '#e3aa1a' }
});
Se você quiser especificar o alinhamento de elementos filhos dentro de um elemento pai, você pode usar a propriedade alignSelf
. Todos os valores possíveis de alignItems
são aplicáveis a esta propriedade. Então, por exemplo, você pode alinhar um único elemento à direita do seu elemento pai, enquanto todos os restantes estão alinhados à esquerda.
Conclusão
Nessa primeira parte, implementamos o Stack layout. E na segunda parte, vamos continuar vendo outros tipos de layout que podemos fazer.
O repositório nexus-react-native/04-how-to-create-layouts, está a disposição para praticar. :)