Dando continuidade ao artigo **Criando Layouts**. Na [parte 1](/tecnologia/artigos/react-native/react-native-criando-layouts-parte-1/), vimos o **Stack layout** e agora vamos continuar vendo os tipos de layout que conseguimos criar no **React native**.## Grid LayoutO **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:![Stack Layout Vertical](/assets/tecnologia/artigos/layout-grid-layout.png)``` import React, { Component } from 'react'; import { StyleSheet, View } from 'react-native';export default class GridLayout extends Component { render() { return ( ); } }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:![Stack Layout Vertical](/assets/tecnologia/artigos/layout-grid-layout-with-space-between.png)## Absolute LayoutO **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:![Stack Layout Vertical](/assets/tecnologia/artigos/layout-positioning.png)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 ( ); } } ```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 ( ); } }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ãoVimos 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](https://github.com/descco-tools/nexus-react-native/blob/master/04-how-to-create-layouts/App.js), está a disposição para praticar. :)
Para criar um layout no **React Native** vamos usar o **Flexbox**, mas nem todos os recursos que estão na [especificação do Flexbox](https://www.w3.org/TR/css-flexbox-1/), estão incluídos. :/## Stack LayoutEsse 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 ( ); } }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).![Stack Layout Vertical](/assets/tecnologia/artigos/layout-vertical-stack-layout-manual.png)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:![Stack Layout Vertical](/assets/tecnologia/artigos/layout-vertical-stack-layout-manual-h.png)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`:![Stack Layout Vertical](/assets/tecnologia/artigos/layout-vertical-stack-layout-flex.png)``` box: { flex: 1 }, ```![Stack Layout Vertical](/assets/tecnologia/artigos/layout-vertical-stack-layout-flex-h.png)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', } ```![Stack Layout Vertical](/assets/tecnologia/artigos/layout-vertical-stack-layout-header-content-footer.png)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.### HorizontalPara 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.![Stack Layout Vertical](/assets/tecnologia/artigos/layout-horizontal-stack-layout.png)``` container: { flex: 1, flexDirection: 'row', }, box: { flex: 1 }, box1: { backgroundColor: 'red' }, box2: { backgroundColor: 'blue' }, box3: { backgroundColor: 'green' } ```## Justificando o conteúdoSe 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' } ```![Stack Layout Vertical](/assets/tecnologia/artigos/layout-justify-content.png)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`.![Stack Layout Vertical](/assets/tecnologia/artigos/layout-align-items-stretch.png)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 para `alignItems`, portanto, especificar esse valor é opcional.![Stack Layout Vertical](/assets/tecnologia/artigos/layout-align-items.png)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 ( ); } }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ãoNessa primeira parte, implementamos o **Stack layout**. E na [segunda parte](/tecnologia/artigos/react-native/react-native-criando-layouts-parte-2/), vamos continuar vendo outros tipos de layout que podemos fazer.O repositório [nexus-react-native/04-how-to-create-layouts](https://github.com/descco-tools/nexus-react-native/blob/master/04-how-to-create-layouts/App.js), está a disposição para praticar. :)
A grande vantagem que o **React native** nos traz, é tornar único o código tanto para **Android**, quanto para **IOS**. Não só pensando nos dispositivos móveis, graças ao **React**, o código pode ser utilizado no desenvolvimento web. Mas quando chegamos na parte de estilização, podemos ter que nos acostumar e perceber que nessa parte a diferença do que estamos acostumados a ver no desenvolvimento web, é maior que o esperado.## Cascading Style Sheets (CSS)A princípio mexer com estilo no **React native**, parece ser bem simples. Podemos ver as regras de CSS e que diferente da web, onde as as mesmas são escritas em [kebab-case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles), utilizaremos a sintaxe com **CamelCase**.O **React Native** utiliza o mecanismo de layout de [Yoga](https://yogalayout.com/), que implementa as especificações do flexbox e empresta nomes de regras CSS. Ex:``` .text { font-family: Arial; font-size: 12px; } ```Que ficaria assim no **React native**:``` const styles = StyleSheet.create({ text: { fontFamily: 'Arial', fontSize: 12, } }); ```Isso faz com que a escrita do estilo seja muito familiar. Mas depois fica claro que o estilo no **React Native** é muito diferente do estilo na web. Nomes de regras e flexbox são as únicas coisas que o **CSS** e o estilo no **React Native** tem em comum.## Escopo por componenteNo navegador, o **CSS** tem o escopo a nível da página. Para uma aplicação web de uma única página, isso significa que cada folha de estilo afeta a aplicação inteira. As regras de estilos individuais são aplicadas aos elementos no **DOM**, sendo definidos dentro dos blocos dos seletores. Existem muitas maneiras diferentes de selecionar os elementos **DOM**.Com o **React Native**, os estilos não tem efeito em seu aplicação, a menos que você os passe especificamente aos seus componentes. Não existe um conceito de `seletor` porque os componentes e os estilos estão bem acoplados. Isso significa que você pode usar o mesmo nome para estilos em várias folhas de estilo sem causar efeitos colaterais:``` const headerStyles = StyleSheet.create({ container: { backgroundColor: 'red' } }); const footerStyles = StyleSheet.create({ container: { backgroundColor: 'red' } });```## HerançaOs estilos não são herdados por padrão. Na web, os elementos **DOM** herdam alguns dos estilos dos pais por padrão. Estes são principalmente estilos relacionados a texto, e isso significa que você pode fazer:``` .container { font-family: Arial; font-size: 12px; } Title Test with text```Que é equivalente a:``` const styles = StyleSheet.create({ container: { fontFamily: 'Arial', fontSize: 12, }, bold: { fontWeight: '700', } }); Title Test with text```Os componentes podem para passar propriedades de estilo para os componentes filho. É o caso do `` do **React Native**. Um componente `` que é filho de outro componente `,` herdará seus estilos:``` Text Text```O compartilhamento de estilos de texto com `` tem uso limitado, pois `` não permite que a maioria dos outros componentes **React Native** sejam seus filhos.## Lógica no estiloO **CSS** é muito limitado na sua capacidade de calcular valores. Existem algumas funções que você pode usar, como `calc()` e as variáveis **CSS** são suportadas em navegadores modernos. Além disso, a lógica para calcular estilos dinamicamente precisa ocorrer em outros lugares, sendo compilado com pré-processadores (como SASS).No **React Native**, os estilos são definidos em **JavaScript**. Tendo uma linguagem de programação nos dá uma série de possibilidades.Assim, temos novos padrões de estilo. Esse é um [repositório que vale a pena ver](https://github.com/MicheleBertoli/css-in-js).## Style e StyleSheetOs estilos só podem ser transmitidos diretamente para um componente, da mesma forma que você passaria estilos para elementos **DOM** através do atributo `style`:``` text ```Achou que iria se livrar do estilo `inline`? XDA documentação do **React native** nos informar mais sobre o [style](https://facebook.github.io/react-native/docs/style.html).O que pode ser novo para você é o [StyleSheet](https://facebook.github.io/react-native/docs/stylesheet.html), que cria uma folha de estilo a partir de um objeto de estilo, tornando possível se referir a ele por **ID** ao invés de criar um novo objeto de estilo sempre.## Gerenciando estilosPra mim, essa é a parte mais critica. Antes de recorrer a módulos de terceiros, uma escolha minha e um conselho é explorar as possibilidades ao utilizar o **React native**, principalmente se a ideia é ir para a linha **universal** (nativo e web).### MixinsComo utilizamos no pré-processador **SASS** (meu preferido.. :D), os mixins são uma boa saída para reaproveitamento de código e organização:``` export const errorText = { fontWeight: '700', color: 'red', }; `````` import { errorText } from 'textMixins';export default StyleSheet.create({ formErrorMessage: { ...errorText, fontSize: 22, }, fieldErrorMessage: { ...errorText, fontSize: 18, }, }); ```### Estilo globalComo em muitas metodologias de **CSS**, temos uma boa organização definido o estilo primitivo e o reutilizando em suas folhas de estilo. Ex:``` export const COLOR_BLUE = 'blue'; export const COLOR_RED = 'red'; // ...export default StyleSheet.create({ blue: { color: COLOR_BLUE }, red: { color: COLOR_RED }, // ... bg_blue: { backgroundColor: COLOR_BLUE }, bg_red: { backgroundColor: COLOR_RED }, // ... o_100: { opacity: 1 }, o_90: { opacity: 0.9 }, o_80: { opacity: 0.8 }, // ... }); ```Podendo ser usado assim:``` import styles from 'styles';class MyComponent extends React.Component { render() { return ( Text ); } } ```Ou assim:``` import { COLOR_BLUE, COLOR_RED } from 'styles';class MyComponent extends React.Component { render() { return ( Text ); } }const styles = { container: { backgroundColor: COLOR_BLUE, }, text: { color: COLOR_RED, } } ```Teste e busque a melhor solução para o seu projeto. Aqui veremos só algumas possibilidades. Então descubra o seu problema e comece a pensar na solução para a arquitetura.Muitas vezes, mesmo uma pequena mudança na forma como um componente funciona, significa que os nomes dos estilos não se encaixam. E os problemas podem aparecer e prejudicar o projeto. Então gaste um tempo, testando a necessidade do projeto e a melhor solução de organização e utilização.## Funções auxiliaresEstilos em JavaScript significa que você obtém o poder de uma linguagem de programação em vez de uma linguagem de estilo simples.``` // font https://gist.github.com/samueljmurray/eeb9495146ef0aad24f534cecd17487c import { Dimensions } from 'react-native';// Height const screenSizes = [ { name: 'xs', height: 568 }, { name: 's', height: 667 } ];// Example usage: // screenSize({xs: 8, s: 12}, 16) // screenSize({s: 12}, 16) // screenSize({xs: 8}, 16) export function screenSize(screenSizeOptions, defaultValue) { const matchedScreenSizes = screenSizes.filter((screenSize) => { return Dimensions.get('window').height { if (screenSizeOptions.hasOwnProperty(matchedScreenSize.name)) { value = screenSizeOptions[matchedScreenSize.name]; return true; } else { return false; } }); if (!hasScreenSizeOption) { value = defaultValue; } return value;```## Passando contexto para o estiloUm componente ``, por exemplo, pode aceitar uma propriedade de cor (string) e estilo quando estiver desabilitado (booleano), que afetam o seu estilo:``` export default StyleSheet.create({ button: { backgroundColor: 'red', }, buttonDisabled: { backgroundColor: 'gray', }, }); `````` import styles from 'buttonStyles';class Button extends React.Component { render() { return ( // ... ); } } ```O problema do exemplo acima, que pode ficar muita lógica misturada (estilo e funcionalidade do componente). Então, vamos deixar a lógica de estilo no seu devido lugar.``` export default (props) => StyleSheet.create({ button: StyleSheet.flatten([ { backgroundColor: 'red', }, props.color && { backgroundColor: props.color, }, props.disabled && { backgroundColor: 'gray', }, ]), }); `````` import styles from 'buttonStyles';class Button extends React.Component { render() { const s = styles(this.props); return ( // ... ); } } ```Mais um exemplo, sem **StyleSheet**:``` class Button extends React.Component { render() { const s = styles(this.props); return ( // ... ); } }const styles = props => ({ button: { backgroundColor: props.disabled ? 'gray': (props.color ? props.color : 'red'), }, }); ```Ficou mais complexo. Simplificando ficaria assim:``` class Button extends React.Component { render() { const { color, disabled } = this.props; const buttonStyle = disabled ? styles.button({ color }) : styles.buttonDisabled; return ( // ... ); } }const styles = { button: props => ({ backgroundColor: props.color ? props.color : 'red', }, buttonDisabled: { backgroundColor: 'gray', } }); ```Esses foram exemplos que seguirmos uma linha antes de avaliar bem o projeto, pode ficar muito complexo, independente do caminho escolhido. O melhor caminho é ver na prática e testar as possibilidades que conseguir.## ConclusãoTestando as abordagens ao estilo no **React native**, podemos ver a flexibilidade e também muda a forma como pensamos sobre como os estilos podem ser definidos em aplicações baseadas em componentes **JavaScript**, não apenas no **React Native**, mas também na web.Tem muitas bibliotecas para testar:- [Styled components](https://github.com/styled-components/styled-components) - [Extended StyleSheets for React Native](https://github.com/vitalets/react-native-extended-stylesheet) - [Further - algebraic style composition for functional UIs](https://github.com/jongold/further)Então, vamos testar!
Se está desenvolvendo uma aplicação com **React native**, você vai querer personalizar o mesmo. Então, vamos ver como colocar a tela inicial e os ícones do aplicativo como queremos.Primeiro temos que criar o nosso projeto.``` react-native init helloworld ```## Criando as imagesExistem dispositivos de todas as formas e tamanhos, portanto, nossas imagens de tela inicial também precisam ter uma variedade de tamanhos. O Phonegap tem um guia dos tamanhos de [telas](https://github.com/phonegap/phonegap/wiki/App-Splash-Screen-Sizes) e [ícones](https://github.com/phonegap/phonegap/wiki/App-Icon-Sizes) que o seu aplicativo deve ter.Usaremos o [Image Gorilla da Ape Tools](https://apetools.webprofusion.com/#/tools/imagegorilla) para gerar todos os tamanhos necessários para a nossa tela inicial. Na ferramenta use uma imagem PNG sem transparência de 2048x2048 para a tela de abertura e uma imagem PNG de 1024x1024 para o ícone.![Tela de abertura](/assets/tecnologia/artigos/splash-screen.jpg) ![Ícone](/assets/tecnologia/artigos/icon-app.jpg)Assim que o processo do Image Gorilla seja concluído, baixe o zio e extraia. Você verá vários diretórios, só estamos interessados nos diretórios Android e IOS.### Adicionando no IOSAbra o arquivo `ios/helloworld.xcodeproj`, com o **XCode**.Após o processo de indexação, selecione o projeto no menu esquerdo, que será mostrado o conteúdo para a edição. Role para baixo até achar a opção `Launch Images Source` e clique em `Use Asset Catalog...`.![Tela XCode](/assets/tecnologia/artigos/splash-screen-01.jpg)Na caixa de diálogo que aparece clique em `Migrate`. Em seguida, no campo **Launch Screen File**, exclua **LaunchScreen** e deixe o campo em branco. Você também pode excluir o **LaunchScreen.xib** do navegador à esquerda.![Tela XCode](/assets/tecnologia/artigos/splash-screen-02.jpg)Dentro da pasta `Imagens.xcassets`, existe agora uma opção **LaunchImage** dentro dela. Aqui é onde vamos arrastar e soltar as imagens IOS geradas.![Tela XCode](/assets/tecnologia/artigos/splash-screen-03.jpg)Agora, executando `react-native run-ios`, já é possível ver a nossa tela de abertura nova e o ícone.![Tela XCode](/assets/tecnologia/artigos/splash-screen-04.jpg) ![Tela XCode](/assets/tecnologia/artigos/splash-screen-05.jpg)### Adicionando no AndroidAs próximas dicas tem como base o artigo [Splash Screens the Right Way](https://www.bignerdranch.com/blog/splash-screens-the-right-way/).No Android, primeiro copie os seguintes diretórios das imagens geradas:- drawable-hdpi - drawable-mdpi - drawable-xhdpi - drawable-xxhdpie cole no diretório `android/app/src/main/res`.Abra o projeto no Android Studio (sempre abro o arquivo `android/build.gradle`, que assim ele já verifica as configurações do gradle). Em `app/res/drawable`, crie um novo `Drawable resource file`. Nomeie esse arquivo `project_splash`.![Tela Android Studio](/assets/tecnologia/artigos/splash-screen-06.jpg)Dentro do arquivo cole o seguinte:``` // project_splash.xml```A exibição da tela de abertura deve estar pronta imediatamente, mesmo antes de poder inflar um arquivo de layout em sua atividade de `splash`.Então você não usará um arquivo de layout. Em vez disso, especifique o plano de fundo da tela inicial como o fundo do tema da atividade.Agora precisamos adicionar um novo estilo no arquivo `android/app/res/values/styles.xml`, resultando no seguinte arquivo.``` // styles.xml @drawable/project_splash```Agora precisamos fazer algumas atualizações **AndroidManifest.xml**. Vamos criar uma nova atividade com o nome de **.SplashActivity**.Basicamente, mude o nome da atividade existente e adicione `android:theme='@style/SplashTheme`. Em seguida, crie uma atividade vazia com o nome de **.MainActivity**. Isso resulta em um arquivo como este.``` // AndroidManifest.xml```Observe que movemos todas as configurações de **MainActivity** para **SplashActivity**.Agora precisamos dizer ao **SplashActivity** que vá para o **MainActivity**, o que representa a nossa aplicação real. Para fazer isso você precisa criar uma nova classe Java chamada **SplashActivity**.![Tela Android Studio](/assets/tecnologia/artigos/splash-screen-07.jpg)E coloque o seguinte código nesse arquivo. Certifique-se de manter a primeira linha o mesmo que o que for criado para o seu aplicativo, é específico do aplicativo.``` // SplashActivity.java package com.helloworld;import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity;public class SplashActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = new Intent(this, MainActivity.class); startActivity(intent); finish(); } } ```Pronto! Temos as telas de abertura no Android. Para o ícone, basta substituir a imagen `ic_launcher.png` de cada pasta `android/app/src/main/res/mipmap-*`, com as imagens `icon.png` que estão nos diretórios respectivos `drawable-*`, mantendo o nome `ic_launcher.png`. Ou se preferir altere o arquivo `AndroidManifest.xml`, o valor de `android:icon`. Ex: `android:icon='@drawable/icon'`.![Tela Android Studio](/assets/tecnologia/artigos/splash-screen-08.jpg)Com tudo isso concluído, você deve ver o seguinte (extremamente brevemente) ao criar o aplicativo.![Tela Android Studio](/assets/tecnologia/artigos/splash-screen-09.jpg) ![Tela Android Studio](/assets/tecnologia/artigos/splash-screen-10.jpg)## ConclusãoDepois da configuração dos ambientes e a implementação dos ícones e telas de abertura, agora é só focar na aplicação que pretende desenvolver.
Para ver na prática o **React native**, vamos para o nosso **Hello world**. A documentação([Getting Started](https://facebook.github.io/react-native/docs/getting-started.html)) explica bem os passos de instalação e para rodar os projetos, mas você também pode ver aqui abaixo e conferir um exemplo em [nexus-react-native - hello-world](https://github.com/descco-tools/nexus-react-native/tree/master/01-hello-world).## Pré-requisitos- **Node** - Interpretador de código JavaScript que funciona do lado do servidor. - **Watchman** - Ferramenta do Facebook para observar as alterações no sistema de arquivos. É altamente recomendável que você o instale para um melhor desempenho. - **Xcode** - Ambiente de desenvolvimento integrado e software livre da Apple Inc. - **JDK** - Significa Kit de Desenvolvimento Java, e é um conjunto de utilitários que permitem criar sistemas de software para a plataforma Java. - **Android Studio** - Ambiente de desenvolvimento integrado para desenvolver para a plataforma Android. - **react-native-cli** - Permite instalar a interface do React Native via linha de comando.### IOS (Mac)- [Node](https://nodejs.org/en/download/) - [Watchman](https://facebook.github.io/watchman/) - [Xcode](https://itunes.apple.com/br/app/xcode/id497799835)### Android (Windows/Linux/Mac)- [Node](https://nodejs.org/en/download/) - [Watchman](https://facebook.github.io/watchman/) - [Java SE Development Kit (JDK)](http://www.oracle.com/technetwork/java/javase/downloads/index.html) - [Android Studio](https://developer.android.com/studio/index.html)## Android Studio### InstalaçãoEscolha uma configuração `custom` quando solicitado ao selecionar o tipo de instalação. Certifique-se de que esses itens estejam marcados:- `Android SDK` - `Android SDK Platform` - `Performance (Intel ® HAXM)` - `Android Virtual Device`### Instalando o Android SDKO Android Studio instala o último SDK do Android por padrão. Uma aplicação **React Native**, no entanto, requer o SDK do Android 6.0 (Marshmallow) em particular. SDKs Android adicionais podem ser instalados através do SDK Manager no Android Studio.O SDK Manager pode ser acessado em `Appearance & Behavior → System Settings → Android SDK`.Selecione a guia `Plataformas SDK` dentro do SDK Manager, em seguida marque a caixa ao lado de `Show Package Details` no canto inferior direito. Procure e expanda a entrada do Android 6.0 (Marshmallow), então verifique se os seguintes itens estão marcados:- `Google APIs` - `Android SDK Platform 23` - `Intel x86 Atom_64 System Image` - `Google APIs Intel x86 Atom_64 System Image`Em seguida, selecione a guia `SDK Tools` e marque a caixa ao lado de `Show Package Details` aqui também. Procure e expanda a entrada `Android SDK Build-Tools`, então verifique se o **23.0.1** está selecionado.## Variáveis de ambiente (Android)Se vai utilizar a plataforma **Android**, precisa ter algumas variáveis de sistema.No caso do **Mac** e **Linux** basta adicionar no arquivo `$HOME/.bash_profile`:``` export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/tools export PATH=$PATH:$ANDROID_HOME/platform-tools ```ou se for no **Windows**, configure a variavel `ANDROID_HOME`. [Veja aqui como configurar](https://www.java.com/pt_BR/download/help/path.xml) uma variavel de ambiente no windows.## Criando a aplicaçãoTendo os pré-requisitos instalados e no caso do **Android**, as variáveis de ambiente configuradas. Agora podemos criar o nosso **hello world** com o `cli` do **React native**.Se ainda não tem o `cli` instalado, basta instalar pelo `npm`.``` npm install -g react-native-cli ```Agora basta executar o comando `init`, com o nome do projeto.``` react-native init helloworld ```## Rodando a aplicação### IOSNo **IOS** é bem simples, basta entrar na pasta do projeto e executar `run-ios`.``` cd helloworld react-native run-ios ```### AndroidNo caso do **Android**, teremos que iniciar um dispositivo Android antes de executar `run-android`. Podendo ser um dispositivo físico ou você pode usar um dispositivo virtual que permite que você simule um dispositivo Android em seu computador.**Usando um dispositivo físico** - Se você tem um dispositivo físico, você pode usá-lo para o desenvolvimento no lugar de um AVD conectando-o ao seu computador usando um cabo USB e seguindo as [instruções aqui](https://facebook.github.io/react-native/docs/running-on-device.html).**Usando um dispositivo virtual** - Você pode ver a lista de dispositivos virtuais de Android (AVDs) disponíveis abrindo o `AVD Manager` no Android Studio. Procure um ícone que se pareça com isto: ![ícone AVD](/assets/tecnologia/artigos/icon-avd.png)**Android Studio AVD Manager** - Se você acabou de instalar o Android Studio, provavelmente será necessário criar um novo **AVD**. Selecione `Create Virtual Device`, depois escolha qualquer telefone na lista e clique em `Next`.Com o dispositivo pronto, podemos continuar.``` cd helloworld react-native run-android ```## ConclusãoPode parecer complicado no começo (me refiro ao Android :D). Mas tem uma solução mais rápida com o `Create React Native App`.É a maneira mais fácil de começar a criar um novo aplicativo **React Native**. Ele permite que você inicie um projeto sem instalar ou configurar ferramentas - não é necessária nenhuma instalação **Xcode** ou **Android Studio**.Precisará do **Node** instalado e instalar:``` npm install -g create-react-native-app ```E depois:``` create-react-native-app helloworldcd helloworld npm start ```Instale o aplicativo do [Expo client](https://expo.io/) no seu telefone [iOS](https://itunes.apple.com/us/app/expo-client/id982107779?mt=8) ou [Android](https://play.google.com/store/apps/details?id=host.exp.exponent&hl=pt_BR) e conecte-se à mesma rede sem fio que o seu computador. Usando o aplicativo **Expo**, analise o código QR do seu terminal para abrir seu projeto.
Na [ReactConf 2015](http://conf2015.reactjs.org/), que rolou nos dias 28 e 29 de janeiro de 2015, foi feito o anúncio do **React Native**. Tendo o seu [primeiro release no Github](https://github.com/facebook/react-native/releases/tag/v0.1.0) no dia 27 de Março de 2015.## Desenvolvimento móvel nativoAntes de tudo, precisamos escolher uma plataforma.A plataforma Android, por ter ferramentas gratuitas já oferece para muitos desenvolvedores que tem pouco dinheiro para investir, uma grande oportunidade.Mesmo que apps android contém 85% do mercado de usuários do planeta. Quando você cria apps iOS baseado-se em compras por meio no aplicativo, você tem como benefício a chance de gerar lucros de até 4 vezes maior do que Android.Temos que olhar as características de cada um..### Android- Utiliza a linguagem Java. - Apps Android são baixados com maior frequência e números do que outras plataformas. - Para Publicar seu trabalho, é cobrado uma taxa fixa de apenas US$ 25 dólares. - Muitos países emergentes estão adotando a desenvolvimento Android como Brasil, índia, África, China dentre outros. - Por se tratar de código aberto, você corre risco de sofrer com problemas de Malware. - Taxas altas de fragmentação da indústria por conta da grande quantidade de fornecedores e quantidade de aparelhos no mercado. - Lucratividade da loja Google Play menor em comparação ao iOS.### IOS- Utiliza linguagens de programação como Objective-C e Swift. - Usuários iOS são normalmente muito leais, significa uma base de usuários ativa e constante. - Usuários mais dispostos a gastar dinheiro. - Para publicar seu trabalho na plataforma, você terá que gastar cerca de US$ 99 dólares. - Seu app passará por um processo rigoroso que pode levar um bom tempo antes de ser aprovado. - A concentração desses usuários são de maioria dos EUA, um pouco na China e na Europa.### ResultadoSimplesmente a nível de desenvolvimento com uma pessoa, teríamos que escolher um. Pois seria um trabalho dobrado que demandaria muito tempo de aprendizado e desenvolvimento.E a nível de empresa, comparando com um desenvolvimento móvel web, os custos são mais altos no desenvolvimento e manutenção, demandando mais pessoal e tempo para manter os códigos iOS e Android separadamente. E consequentemente, linguagens diferentes em plataformas distintas geram comportamentos.## A solução(?)Surgiram os frameworks para desenvolvimento híbrido (ex: [Cordova](https://cordova.apache.org), [Xamarin](https://www.xamarin.com), [PhoneGap](http://phonegap.com), [Intel XDK](https://software.intel.com/en-us/intel-xdk), [Ionic](https://ionicframework.com) e [Sencha Touch](https://www.sencha.com/products/touch)). Eles permitem compilar o mesmo projeto em ambas as plataformas.Esses frameworks utilizam HTML, CSS e JavaScript. Eles operam em cima de uma **WebView** (página Web simulando uma aplicação nativa).Dessa forma, o desempenho é inferior e a interação gráfica com o usuário pode não ser satisfatória.## Arquitetura Nativo Aplicação Bibliotecas de terceiros SDK de desenvolvedores, bibliotecas padrão Sistema operacional móvel (IOS, Android, etc...) Híbrido Aplicação Framework para desenvolvimento móvel (ex: Cordova) Bibliotecas compatíveis com os Frameworks WebView API IOS SDKs Android SDKs IOS Android React native Aplicação Bibliotecas de terceiros Pacotes NPM (ex: React) Componentes RN de terceiros React native IOS / Android SDKs JS Runtime IOS / Android## ConclusãoO **React native** revolucionou, já que o código gerado pelo **React** pode ser reaproveitado em até 100% entre as plataformas, fazendo com que o custo e duração do projeto caia pela metade.Ele compila o projeto nativamente, aproveitando 100% dos recursos do dispositivo e sistema operacional. O desenvolvedor tem acesso nativamente a toda API.