Advertisement
  1. Code
  2. Mobile Development
  3. React Native Development

Layouts de App Comuns em React Native: Página de Galeria

Scroll to top
This post is part of a series called Common React Native App Layouts.
Common React Native App Layouts: Calendar Page
Common React Native App Layouts: News Feed

() translation by (you can also view the original English article)

Nessa série, aprendemos como criar layouts de páginas comuns, usados em apps mobile, com React Native. Os layouts não são funcionais—contudo, o foco da série é fazer-nos estruturar conteúdo em apps com React Native.

Se estiver começando a estruturar apps em React Native ou estilização em geral, veja nosso tutorial anterior:

Para acompanhar a série, temos o desafio de criar cada tela sozinhos, antes de ler as instruções passo-a-passo no tutorial. Não nos beneficiamos muito apenas lendo o tutorial! Tentemos primeiro antes de olhar as respostas. Se conseguir fazer parecer com a tela original, comparemos nossa solução com a do passo-a-passo. E então, decidamos qual é a melhor!

Nessa terceira publicação da série, criaremos uma página de galeria de fotos:

photo gallery pagephoto gallery pagephoto gallery page

Galerias, no geral, são usadas para mostrar uma coleção de conteúdo relacionado onde apenas a informação necessária é apresentada. A maioria das vezes, isso inclui uma foto, título e outra informação relevante.

Eis alguns exemplos desse tipo de layout sendo usado por aí:

Crunchyroll Anime GalleryCrunchyroll Anime GalleryCrunchyroll Anime Gallery
Librivox Audiobook GalleryLibrivox Audiobook GalleryLibrivox Audiobook Gallery

Configuração do Projeto

O primeiro passo, é configurar um novo projeto em React Native.

1
react-native init react-native-common-screens

Com o projeto configurado, abramos index.android.js e substituamos o conteúdo por isso:

1
import React, { Component } from 'react';
2
import {
3
  AppRegistry
4
} from 'react-native';
5
6
import Gallery from './src/pages/Gallery';
7
8
export default class ReactNativeCommonScreens extends Component {
9
10
  render() {
11
    return (
12
      <Gallery />
13
    );
14
  }
15
16
}
17
18
AppRegistry.registerComponent('ReactNativeCommonScreens', () => ReactNativeCommonScreens);

Criemos a pasta src/pages e criemos o arquivo Gallery.js dentro.

Também precisaremos do pacote react-native-vector-icons. Usado especificamente para os ícones no rodapé.

1
npm install --save react-native-vector-icons

Abramos o arquivo android/app/build.gradle e adicionemos a referência ao pacote:

1
dependencies {
2
    //rest of the dependencies are here at the top
3
    compile project(':react-native-vector-icons') //add this
4
}

Façamos o mesmo em android/settings.gradle, adicionando isso ao final do arquivo:

1
include ':react-native-vector-icons'
2
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')

Abramos android/app/src/main/java/com/react-native-common-screens/MainApplication.java e importemos o pacote:

1
import java.util.Arrays;
2
import java.util.List;
3
4
import com.oblador.vectoricons.VectorIconsPackage; //add this

Por último, uniciemo-no:

1
@Override
2
protected List<ReactPackage> getPackages() {
3
  return Arrays.<ReactPackage>asList(
4
      new MainReactPackage(),
5
      new VectorIconsPackage() //add this

6
  );
7
}

Criando a Página de Galeria

Certo, agora que tentamos criar o código por conta própria (sem trapaça, certo?), mostraremos nossa implementação.

Diferentes das páginas anteriores, a galeria precisa de algumas imagens que serviremos como conteúdo principal. Podemos ir no Google e pesquisar imagens ou usar as existentes no repositório do Github. Todas as imagens tem permissão de seus autores para serem usadas, logo podemos usá-las sem problemas. Com as imagens, salvemo-nas na pasta src/images. Pelo jeito que as imagens serão apresentadas, todas devem ter dimensões iguais.

Comcemos criando src/pages/Gallery.js e adicionando o código base:

1
import React, { Component } from 'react';
2
3
import {
4
  StyleSheet,
5
  View,
6
  ScrollView,
7
  Image,
8
} from 'react-native';
9
10
import Icon from 'react-native-vector-icons/FontAwesome';
11
import Button from '../components/Button';
12
13
export default class Gallery extends Component {
14
    ...
15
}

A página precisa de um constructor() onde definiremos os caminhos das imagens que usaremos. No React Native, para referir a imagens localizadas no diretório do projeto, basta requerê-las como requeremos um módulo JavaScript. Vale notar que não podemos ter caminhos de imagens dinamicamente gerados, logo, temos de fornecer um caminho de verdade.

1
constructor(props) {
2
    super(props);
3
  this.state = {
4
		photos: [
5
			{
6
				label: 'beach',
7
				src: require('../images/beach.jpg')
8
			},
9
			{
10
				label: 'bridge',
11
				src: require('../images/bridge.jpg')
12
			},
13
			{
14
				label: 'fields',
15
				src: require('../images/fields.jpg') 
16
			},
17
			{
18
				label: 'mountains',
19
				src: require('../images/mountains.jpg')
20
			},
21
			{
22
				label: 'sunflower',
23
				src: require('../images/sunflower.jpg')
24
			},
25
			{
26
				label: 'sunset',
27
				src: require('../images/sunset.jpg')
28
			},
29
			{
30
				label: 'lake',
31
				src: require('../images/lake.jpg')
32
			},
33
			{
34
				label: 'nature',
35
				src: require('../images/nature.jpg')
36
			},
37
			{
38
				label: 'pink',
39
				src: require('../images/pink.jpg')
40
			},
41
			{
42
				label: 'rails',
43
				src: require('../images/rails.jpg')
44
			},
45
		]
46
	};
47
}

Não precisamos defini-las agora, já que os valores não alterarão. Poderíamos definí-las em um arquivo separado, importá-lo e atribuir a uma variável, e usá-la diretamente. Mas, para simplificar, decidimos colocar tudo na propriedade state.

Dentro de render(), não faremos como os outros, envolvendo tudo com um componente ScrollView, porque o componente de abas da parte inerior da tela deve ter uma posição fixa. Isso significa que mesmo se as fotos passarem da altura disponível, as abas devem permanecer no lugar. Para conseguir isso, usemos um componente View para envolver tudo e envolver apenas as fotos em um ScrollView. Isso permite-nos aplicar a rolagem apenas ao container da coleção de fotos:

1
render() {
2
    return (
3
		<View style={styles.container}>
4
			<ScrollView style={styles.gallery}>
5
				{ this.renderGallery() }
6
			</ScrollView>

7
			<View style={styles.tabs}>
8
		</View>

9
	);
10
}

Agora, começamos a ver um padrão. Toda vez que precisamos usar JavaScript dentro de render(), devemos criar uma função separada para esse código ao invés de colocá-lo diretamente dentro de render(). Isso mantém simples e limpo.

Agora, sigamos para a estilização. Embora uma ScrollView não seja usada para envolver tudo, agora, é important enotar que ainda precisamos usar flex: 1 no container principal para ele tomar todo o espaço disponível.

1
container: {
2
    flex: 1,
3
	flexDirection: 'column'
4
},
5
gallery: {
6
	flexDirection: 'column'
7
},
8
tabs: {
9
	flexDirection: 'row',
10
	backgroundColor: '#333',
11
	padding: 20
12
},
13
tab: {
14
	flex: 1
15
},
16
icon: {
17
	textAlign: 'center'
18
},

renderGallery() é bem parecida com renderWeeks() que usamos no tutorial anterior, usada para renderizar a página do calendário. Se quiser relembrar como funciona, vá em frente e veja o tutorial anterior sobre páginas de calendário. O que é preciso saber é que resizeMode é aplicado em Image. Nesse caso, usamos cover, que faz a imagem ocupar todo o espaço disponível em seu container, e mantendo a proporção. Isso faz as imagens estourarem um pouco em aparelhos com telas maiores se a imagem for menor.

1
renderGallery() {
2
    var count = 0;
3
	var previous_item = '';
4
	var pairs = this.getPairsArray(this.state.photos);
5
	return pairs.map((item, index) => {
6
		return (
7
			<View style={styles.item} key={index}>
8
				<Image 
9
					resizeMode={Image.resizeMode.cover} 
10
					style={styles.photo} 
11
					source={item[0].src} />

12
				<Image 
13
					resizeMode={Image.resizeMode.cover} 
14
					style={styles.photo} 
15
					source={item[1].src} />

16
			</View>

17
		);
18
	});
19
}

Eis getPairsArray():

1
getPairsArray(photos) {
2
    var pairs_r = [];
3
	var pairs = [];
4
	var count = 0;
5
	photos.forEach((item) => {
6
	  count += 1;
7
	  pairs.push(item);
8
	  if(count == 2){
9
	    pairs_r.push(pairs)
10
	    count = 0;
11
	    pairs = [];
12
	  }
13
	});
14
	return pairs_r;
15
}

gallery page styled footergallery page styled footergallery page styled footer

Por fim, eis o estilo para cada linha (item) e foto (photo). Notemos o uso de flex: 1 na foto. Isso é porque o componente Image é seu próprio container. Queremos que o container em si ocupe metade do espaço disponível para cada linha—é por isso que uma propriedade flex deve ser usada. Se não for feito, apenas as dimensões requeridas pela foto serão usadas e resizeMode, adicionada anteriormente, não entrará em efeito.

1
item: {
2
    flex: 1,
3
	flexDirection: 'row',
4
},
5
photo: {
6
	flex: 1
7
}

Conclusão

É isso! Nesse tutorial, aprendemos como implementar layout para uma página de galeria. Focamos em como lidar com imagens ao estruturar apps com React Native. Geralmente, usaremos uma combinação de flex e resizeMode para fazer as imagens seguirem do jeito que queremos. Como sua solução compara com a nossa? Diga-nos deixando uma comentário abaixo.

No próximo tutorial, aprenderemos como implementar um layout muito usado em apps de notícias Enquanto isso, veja alguns outros tutoriais sobre React Native e Flexbox!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.