Dando continuidade ao artigo Criando Layouts. Na parte 1, vimos o Stack layout e agora vamos continuar vendo os tipos de layout que conseguimos criar no React native.
Grid Layout
O React Native não vem com um sistema de layout de grade, mas o flexbox é flexível o suficiente para criar um. Ao utilizar o que já vimos até agora, podemos recriar um grid layout usando o flexbox. Ex:
import React, { Component } from 'react';
import {
StyleSheet,
View
} from 'react-native';
export default class GridLayout extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box, styles.box3]}></View>
<View style={[styles.box, styles.two]}></View>
</View>
<View style={styles.row}>
<View style={[styles.box, styles.two]}></View>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box, styles.box3]}></View>
</View>
<View style={styles.row}>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box, styles.two]}></View>
<View style={[styles.box, styles.box3]}></View>
</View>
<View style={styles.row}>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box]}></View>
<View style={[styles.box, styles.box3]}></View>
</View>
<View style={styles.row}>
<View style={[styles.box, styles.box2]}></View>
<View style={[styles.box]}></View>
</View>
<View style={styles.row}>
<View style={[styles.box]}></View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: { flex: 1 },
row: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 10
},
box: {
flex: 1,
height: 100,
backgroundColor: '#333',
},
box2: { backgroundColor: 'green' },
box3: { backgroundColor: 'orange' },
two: { flex: 2 }
});
No código acima, você pode ver que estamos simulando o que costumamos fazer em uma estrutura de grade no CSS. Cada linha com uma exibição separada e os itens da grade estão dentro dela. O valor 1 na propriedade flex
é aplicado a cada item para que eles compartilhem igualmente o espaço disponível em cada linha. Mas para itens que precisam ocupar um espaço maior, um valor flex
maior é aplicado. Isso ajusta automaticamente a largura dos outros itens para acomodar todos os itens.
Se você quiser adicionar espaços entre cada item de uma linha, você pode adicionar um preenchimento a cada um deles e criar uma caixa dentro de cada um. Ex:
Absolute Layout
O React Native só suporta os valores absolute
e relative
, para a propriedade position
. Isso não limita muito, porque sempre podemos combiná-los com o flexbox para posicionar os diferentes elementos em qualquer lugar que desejarmos. Ex:
Podemos conseguir isso facilmente se tivermos um comando total sobre os valores de posicionamento disponíveis no navegador. Mas, como estamos no React Native, precisamos pensar primeiro no modo flexbox e usar o posicionamento CSS para as caixas.
Usando o flexbox, isso pode ser conseguido de duas maneiras. Você pode usar row
ou column
para a propriedade flexDirection
no elemento pai. Usando o valor row
no flexDirection
, a tela seja dividida em três colunas. A primeira coluna conterá a caixa vermelha, a segunda coluna conterá as caixas azul, cinza e verde e a terceira conterá as caixas amarela e roxa.
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
export default class Positioning extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.left}>
<View style={[styles.box, styles.bigRedBox]}>
</View>
</View>
<View style={styles.middle}>
<View style={[styles.box, styles.bigBlueBox]}>
<View style={[styles.innerBox, styles.blackBox]}></View>
</View>
<View style={[styles.bigGrayBox]}></View>
<View style={[styles.box, styles.bigGreenBox]}>
<View style={[styles.innerBox, styles.blackBox]}></View>
</View>
</View>
<View style={styles.right}>
<View style={[styles.box, styles.bigYellowBox]}>
<View style={[styles.innerBox, styles.blackBox]}></View>
</View>
<View style={[styles.innerBox, styles.purpleBox]}></View>
</View>
</View>
);
}
}
A primeira coluna tem apenas a caixa vermelha, basta definir a propriedade justifyContent
com center
no elemento pai que define a coluna. Como já vimos, o o valor default
do flexDirection
é column
. Isto significa que se você definir justifyContent
como center
, os elementos filhos serão alinhados no centro do eixo Y.
A segunda coluna tem basicamente a mesma ideia que a primeira, só que desta vez não queremos alinhar todas as caixas ao centro. O que queremos é que eles tenham espaços iguais entre eles. A propriedade justifyContent
com valor space-between
, resolve isso. Mas ao mesmo tempo, também queremos centralizar os elementos filhos no eixo x, então nós usamos alignItems
com valor center
.
A única parte complicada aqui é que você não deve aplicar nenhuma propriedade width
a caixa cinza porque queremos que ele ocupe todo o espaço do elemento pai. Uma vez que não aplicamos a propriedade width
, devemos usar a propriedade alignSelf
com valor stretch
, para que a caixa cinza ocupe a largura total do seu elemento pai.
Em seguida, para posicionar a pequena caixa preta um pouco longe de sua posição relativa, usamos position
com o valor relative
e depois acrescentamos as propriedades top
e left
com os valores que queremos, porque sua posição relativa está em torno do canto superior esquerdo de seu pai.
Na pequena caixa roxa, colocamos a propriedade position
com o valor absolute
e as propriedades bottom
e right
, para alinhá-la ao canto inferior direito de seu pai. Isso funciona porque elementos posicionados com position: absolute
no React Native estão vinculados aos seus pais.
A terceira coluna basicamente aplica a mesma ideia.
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
},
left: {
flex: 1,
justifyContent: 'center',
},
middle: {
flex: 5,
justifyContent: 'space-between',
alignItems: 'center',
},
right: {
flex: 1,
justifyContent: 'center',
alignItems: 'flex-end',
},
box: {
width: 100,
height: 100,
backgroundColor: '#f2f2f2',
},
bigGreenBox: { backgroundColor: 'green' },
bigRedBox: { backgroundColor: 'red' },
bigYellowBox: { backgroundColor: 'yellow' },
bigGrayBox: {
height: 100,
alignSelf: 'stretch',
backgroundColor: '#ccc'
},
innerBox: {
width: 20,
height: 20,
},
redBox: {
position: 'relative',
backgroundColor: 'red',
top: 10,
left: 10
},
blueBox: {
position: 'absolute',
backgroundColor: 'blue',
top: 10,
right: 10
},
purpleBox: {
position: 'absolute',
backgroundColor: 'purple',
bottom: 10,
right: 10
},
blackBox: {
position: 'relative',
backgroundColor: 'black',
}
});
Header e footer fixos.
Para isso, precisamos usar o componente de ScrollView
, se o conteúdo for maior que a altura do elemento, o React Native gerará automaticamente uma barra de rolagem vertical. Isso nos permite adicionar marginTop
e marginBottom
no elemento com o conteúdo principal, para que o header
e o footer
fixos não obstruam o conteúdo principal. Os valores de left
e right
do header
e footer
estão configurados com 0, para que eles ocupem a largura total do dispositivo.
import React, { Component } from 'react';
import { StyleSheet, View, ScrollView } from 'react-native';
export default class FixedHeaderFooter extends Component {
render() {
return (
<View style={styles.container}>
<View style={[styles.header]}></View>
<ScrollView>
<View style={[styles.content]}>
<View style={[styles.box]}></View>
<View style={[styles.box]}></View>
<View style={[styles.box]}></View>
<View style={[styles.box]}></View>
<View style={[styles.box]}></View>
<View style={[styles.box]}></View>
<View style={[styles.box]}></View>
</View>
</ScrollView>
<View style={[styles.footer]}></View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
},
header: {
height: 40,
position: 'absolute',
left: 0,
right: 0,
top: 0,
backgroundColor: 'red,
zIndex: 10
},
content: {
alignItems: 'center',
marginTop: 50,
marginBottom: 40
},
footer: {
height: 40,
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'blue'
},
box: {
width: 100,
height: 100,
backgroundColor: 'gray',
marginBottom: 10
}
});
Conclusão
Vimos como usar o Flexbox do React Native para posicionar os elementos e criarmos os layouts. Espero que essas duas partes consigam te ajudar na tarefa de criação de layouts e que tenha ajudado a conhecer as propriedades mencionadas.
O repositório nexus-react-native/04-how-to-create-layouts, está a disposição para praticar. :)