Dicas de UX para aplicações React Native

Antes de prosseguir para as dicas, deixa eu te apresentar o que é UX, ou Experiência do Usuário. A definição de UX segundo seus "criadores" é:

"Experiência do usuário" engloba todos os aspectos da interação do usuário final com a empresa, seus serviços e seus produtos.

Um conceito importante em UX é o processo pelo qual os usuários formam experiências, quando o usuário encontra um produto, forma uma impressão momentânea, que evolui ao longo do tempo.

Neste processo, a percepção, ação, motivação e cognição do usuário se integram para formar uma história memorável e coerente: a "experiência do usuário".

Esse processo é um dos mais importantes, pois é ele quem irá gerar respostas emocionais, que são as responsáveis por determinar se a experiência é positiva ou negativa.

UX no React Native

No React Native há várias diretivas de UX (Experiência do Usuário) que podem ser implementadas nas aplicações, mas a maioria de nós programadores se preocupa tanto com as funcionalidades que acabamos deixando passar esses detalhes.

E nesse post vou te dar algumas dicas de alguns conceitos, em sua maioria não são componentes visuais, mas que podem dar um UP na UX da sua aplicação.

Dicas

Todas as dicas que estarão abaixo podem ser encontradas também na documentação do React Native.

PixelRatio

O PixelRatio é uma API do React Native que nos dá acesso a Densidade de Pixel do dispositivo.


Mas afinal, o que é a Densidade de pixel?

https://medium.com/@sashaserg/a-mysterious-density-independent-pixel-a-quick-introduction-to-android-design-111d68be7cf5

Densidade de Pixel (e.g. Densidade Independente de Pixel) é uma unidade absoluta de medida, assim como polegadas, centímetros ou milímetros. O valor de 1dp é 1 polegada dividida por 160, que é aproximadamente 0.15875 milímetros (você pode ver mais sobre isso nesse link)


Essa API pode ser usada para escalar os elementos do layout da aplicação, tal como medidas de View's e Textos, para que funcione como se estivessem sendo estilizados com porcentagem.

Abaixo segue um exemplo de uso dessa API:

import {Dimensions, PixelRatio} from 'react-native';

const widthPercentageToDP = widthPercent => {
  const screenWidth = Dimensions.get('window').width;
  return PixelRatio.roundToNearestPixel(screenWidth * parseFloat(widthPercent) / 100);
};

const heightPercentageToDP = heightPercent => {
  const screenHeight = Dimensions.get('window').height;
return PixelRatio.roundToNearestPixel(screenHeight * parseFloat(heightPercent) / 100);
};

// Estilizando uma View com os métodos acima
const Tile = styled.View`
  width: ${widthPercentageToDP('98%')};
  height: ${heightPercentageToDP('10%')};
`;

ReturnKeyType

O returnKeyType é uma propriedade do componente TextInput do React  Native, e por padrão ele vem como nas imagens abaixo:

Teclado Padrão iOS / Teclado Padrão Android

Mas é possível modificar esse botão, os valores disponíveis são done, go, next, search e send.

Essa mudança faz toda diferença na experiência do usuário, principalmente em formulários contínuos, pois deixando o padrão a cada campo preenchido o teclado é fechado e quando clicar no próximo campo é aberto novamente.

Mas se essa propriedade for configurada para next é possível passar para os próximos campos sem fechar o teclado, para mais detalhes veja a próxima dica.

onSubmitEditing

Como apresentado acima, há maneiras de modificar o botão padrão que vem nos teclados dos dispositivos, mas apenas modificando o returnKeyType não é alterado o comportamento padrão do botão, e o método onSubmitEditing tem justamente essa função.

Imagine que há um formulário com 4 campos, o ideal para a experiência do usuário é que depois de selecionar o primeiro campo tenha um botão de próximo até chegar no último campo e ter um botão de enviar que tenha a mesma ação que um botão de entrar, por exemplo:

// Field 1
onSubmitEditing={() => this.field2.focus()}

// Field 2
onSubmitEditing={() => this.field3.focus()}

// Field 3
onSubmitEditing={() => this.field4.focus()}

// Field 4
onSubmitEditing={() => this.field5.focus()}

// Field 5
onSubmitEditing={() => this.callApi()}

KeyboardAvoidingView

Esse componente do React Native resolve o problema de quando o teclado virtual for aberto, os campos do seu formulário não fiquem escondidos ou saiam de vista, ele ajusta automaticamente a posição do campo ou o padding da parte inferior do mesmo baseado na posição do teclado.

https://facebook.github.io/react-native/docs/keyboardavoidingview#example

Mesmo sendo pouco utilizado ele é de extrema importância na questão da usabilidade, segue abaixo um exemplo de utilização:

// Implementação Convencional
<View style={styles.container}>
    // ...
</View>

// Implementação do KeyboardAvoidingView
import { Platform } from 'react-native';

<KeyboardAvoidingView
    style={styles.container}
    behavior={Platform.select({
        ios: 'padding',
        android: null,
    })}
>
    // ...
</KeyboardAvoidingView>

AutoCorrect e AutoCapitalize

autoCapitalize e autoCorrect são dois atributos do componente TextInput, eles estão relacionados diretamente à digitação no Input, o autoCapitalize é o responsável por sempre deixar a primeira letra da digitação em maiúsculo, mas em um campo de email ou senha, por exemplo, essa propriedade não faz sentido estar ativada, diferente de um campo de Nome.

Já o autoCorrect tem um nome bastante sugestivo, ele é o responsável por ativar a correção automática de palavras, ele vem por padrão ativo, porém não é em todos os casos que ele é interessante, por isso deve ser analisado caso a caso nos formulários de uma aplicação, pois seu mau uso pode gerar uma experiência indesejada ao usuário.

KeyboardType

Essa é uma propriedade que está ligada ao teclado, que você viu um pouco acima, ela permite que o tipo de teclado que vai aparecer para o usuário seja modificado, seus valores possíveis (para Android e iOS) são: default, number-pad, decimal-pad, numeric, email-address e phone-pad .

https://lefkowitz.me/visual-guide-to-react-native-textinput-keyboardtype-options/

Você pode usar essa propriedade para melhorar a experiência do usuário no sentido de facilitar o preenchimento de um formulário, isso porque quando é preciso digitar em um campo que aceita números com o tipo de teclado padrão é um pouco trabalhoso, visto que é preciso mudar para a aba de símbolos.

Enquanto há uma propriedade no seu componente que cuida disso automaticamente, mudando para um layout que faz mais sentido em cada caso.

hitSlop

Essa é uma propriedade interessante de se utilizar, seja em botões ou qualquer outro componente que precise ter uma área de touch, pois ele permite definir uma área que vai além das barreiras (margin) do componente.

O interessante de se usar essa propriedade é que você consegue dar uma ótima experiência para o usuário ao inserir componentes pequenos mas que não são complicados de serem "acionados" .

https://facebook.github.io/react-native/docs/improvingux#make-tappable-areas-larger

Sua implementação é extremamente simples, mas com certeza irá agregar valor à sua aplicação, segue um exemplo:

<TouchableWithoutFeedback
    onPress={this.handleButtonPress}
    hitSlop={{ top: 20, bottom: 20, left: 50, right: 50 }}
>
    // ...
</TouchableWithoutFeedback>

Orientação da Tela

Ter suporte para várias Orientações de Tela é algo interessante, porém não é aplicável em todas as aplicações, o recomendado em aplicações comuns é deixar a Orientação travada em portrait , isso porque quando utilizamos Flexbox, o Layout pode "quebrar" por se adaptar a resolução da tela.

Com um Layout quebrado a experiência do usuário é "quebrada" junto, portanto na maioria dos casos a saída lógica e mais funcional para esse problema é travar a orientação do aplicativo, pois independente da posição do dispositivo as medidas não vão ser trocadas.

Fazer esse processo no Android é bem simples, basta adicionar a instrução abaixo no AndroidManifest.xml :

android:screenOrientation="portrait"

Tendo como opções portrait e landscape .

Já no iOS essa configuração é feita diretamente na aba General > Deployment Info no Xcode.

Loading sem Spinner

Essa dica não está diretamente ligada a um componente ou uma propriedade, mas sim a um conceito.

Uma das ações que mais acontece em uma aplicação é o carregamento, seja de qualquer coisa, e deixar essa ação acontecer sem um indicador é uma péssima ideia.

Pois a aplicação pode ficar com suas ações travadas por conta do carregamento e o usuário não saber o que está acontecendo, prejudicando em muito a Experiência desse usuário.

Existe uma lib que ajuda muito nesse ponto, é a react-native-shimmer-placeholder, com ela é possível implementar o conceito de Shimmer Effect, que nada mais é que a exibição de um esqueleto da página em forma de animação no lugar de um Spinner ou uma Barra de Progresso.

E para finalizar, tente evitar o uso do ActivityIndicator do React Native, ele prejudica na experiência relacionada aos carregamentos da aplicação, por exemplo:

Platform Touchable

Caso você já tenha experimentado o Android e o iOS, deve ter percebido que o comportamento dos botões nas aplicações de ambos são diferentes.

No Android o botão padrão tem um efeito de Ripple, que cria um background circular quando pressionado, já no iOS os botões por padrão não tem feedback nenhum ou com uma leve opacidade.

E para que você não sofra com isso, dando uma experiência diferente do que o usuário está acostumado na plataforma, recomendo fortemente o uso de uma lib que faz automagicamente essa seleção nos botões para cada plataforma.

Uma alternativa para esse caso é o react-native-platform-touchable, que é até recomendado na documentação do React Native.

Finalizando

Se você chegou até aqui, deixa um comentário sobre o que achou do post =)

E não esquece de passar pro seu/sua amigo(a) desenvolvedor(a) pra vocês poderem por em prática essas Dicas e melhorar a Experiência dos usuários das suas aplicações.

Um Forte Abraço!

E até o próximo post ;)