Se você estiver criando um aplicativo móvel multiplataforma, é uma boa ideia basear a UI/UX do seu aplicativo em Material Design , a linguagem de design do Google, que é usada em todos os seus aplicativos móveis. Por quê? Um dos melhores motivos é que muitos dos aplicativos móveis mais populares usam intensamente os conceitos de material design: Whatsapp, Uber, Lyft, Google Maps, SpotAngels etc. Isso significa que seus usuários já estão familiarizados com a aparência do material design e eles entenderão de forma rápida e fácil como usar seu aplicativo se você aderir à linguagem de design de seus aplicativos favoritos e mais usados.

O grande criador das bibliotecas de componentes do Material Design no React Native é react-native-paper , e este guia irá concentre-se no uso do react-native-paper para configurar um aplicativo inicial com alguns dos recursos mais proeminentes e reconhecíveis do material design: menu de hambúrguer, navegação de gaveta, FAB (botão de ação flutuante) e barra de ação contextual.

Demonstração

É assim que o aplicativo inicial que vou construir acabará se parecendo. Ao ler o guia, você pode consultar o código completo desta demonstração, que reside no seguinte repositório GitHub: material-ui-em-reagir-nativo .

Gif da IU do material na demonstração do aplicativo React Native

Configuração

Primeiro, inicializarei meu aplicativo React Native usando Expo . Você não precisa usar o Expo, ele apenas me ajuda a começar para que eu possa me concentrar na IU neste exemplo.

Se você não tiver o expo-cli instalado, execute primeiro:

 npm install-g expo-cli
<

Agora execute o seguinte:

 expo init material-ui-in-react-nativo-t expo-template-blank-typescript
cd material-ui-in-react-native
fio adicionar reagir-papel nativo

Você também pode seguir estas instruções adicionais de instalação para habilitar a agitação da árvore , reduza o tamanho do pacote, etc. com react-native-paper.

Também estou adicionando react-navigation a este projeto. Eu recomendo que você use também. É a biblioteca de navegação mais popular do React Native, e há mais suporte para executá-la junto com o react-native-paper em comparação com outras bibliotecas de navegação. Siga as instruções de instalação para a navegação reativa , pois elas são ligeiramente diferentes dependendo se você usa Expo ou React Native.

Telas iniciais

Crie os dois arquivos a seguir no diretório principal do seu aplicativo (se quiser que os estilos sejam usados, lembre-se de que tudo neste exemplo está disponível em este repositório GitHub ):

MyFriends.tsx

 import React from'react';
import {View} from'react-native';
import {Title} from'react-native-paper';
importar base de'./styles/base'; interface IMyFriendsProps {} const MyFriends: React.FunctionComponent =(props)=> { Retorna (   Meus amigos   );
};
exportar MyFriends padrão;

Profile.tsx

 import React from'react';
import {View} from'react-native';
import {Title} from'react-native-paper';
importar base de'./styles/base'; interface IProfileProps {} Perfil const: React.FunctionComponent =(props)=> { Retorna (   Perfil   );
};
exportar Perfil padrão;

Ao longo deste guia, vincularei essas telas umas às outras usando uma gaveta de navegação (ou menu Hambúrguer) e adicionarei componentes de IU de material a cada uma delas.

Menu Hambúrguer/Navegação na gaveta

O material design promove o uso de uma gaveta de navegação, então usarei esse tipo de IU para tornar as telas Meus amigos e Perfil navegáveis ​​entre si.

Primeiro, adicionarei a biblioteca drawer do React Navigation:

 yarn add @ react-navigation/native @ react-navigation/drawer

Agora vou adicionar o seguinte em meu App.tsx para habilitar a navegação de gaveta. Deve ser parecido com o seguinte:

App.tsx

 import React from'react';
import {createDrawerNavigator} de'@ react-navigation/drawer';
importar {NavigationContainer} de'@ react-navigation/native';
import {StatusBar} de'expo-status-bar';
importar {SafeAreaProvider} de'react-native-safe-area-context';
importar MyFriends de'./MyFriends';
importar Perfil de'./Profile'; função padrão de exportação App () { const Drawer=createDrawerNavigator (); Retorna (          );
}

Esta gaveta também precisa de um botão para abri-la. Esse botão deve se parecer com o ícone clássico de hambúrguer (≡) e deve abrir a gaveta de navegação quando pressionado. Esta é a aparência desse botão:

components/MenuIcon.tsx

 import React from'react';
import {IconButton} de'react-native-paper';
import {DrawerActions, useNavigation} de'@ react-navigation/native';
import {useCallback} de'react'; função padrão de exportação MenuIcon () { navegação const=useNavigation (); const openDrawer=useCallback (()=> { Navigation.dispatch (DrawerActions.openDrawer ()); }, []); return ;
}

Algumas coisas a serem observadas aqui:

O gancho useNavigation do React-navigation é como vamos executar a maioria das ações de navegação, desde a mudança de telas até a abertura de gavetas.

O componente é do react-native-paper. Ele oferece suporte a todos os ícones do Material Design por nome e, opcionalmente, oferece suporte a qualquer Node React que você deseja transmitir, o que permite adicionar qualquer ícone de qualquer biblioteca de terceiros.

Agora vou adicionar meu à minha gaveta de navegação substituindo-o de App.tsx :

  ... 

Com o seguinte:

 importar MenuIcon de'./components/MenuIcon.tsx';
...  }} > ... 

Por último, posso personalizar minha gaveta de navegação usando o objeto drawerContent do mesmo componente que acabei de alterar.

Vou mostrar um exemplo que adiciona uma imagem de cabeçalho ao topo da gaveta. Fique à vontade para personalizar com o que quiser colocar na gaveta:

components/MenuContent.tsx

 import React from'react';
import { DrawerContentComponentProps, DrawerContentScrollView, DrawerItemList,
} de'@ react-navigation/drawer';
import {Image} from'react-native';
const MenuContent: React.FunctionComponent =( adereços
)=> { Retorna (     );
};
exportar MenuContent padrão;

Agora vou passar para . Para fazer isso, farei a seguinte alteração em App.tsx a partir deste:

 importar MenuIcon de'./components/MenuIcon.tsx';
...  }} > ... 

para isso:

 importar MenuIcon de'./components/MenuIcon.tsx';
importar MenuContent de'./components/MenuContent.tsx';
...  }} drawerContent={(props)=> } > ... 

E agora, eu tenho o Drawer Navigation totalmente funcional com um cabeçalho de imagem personalizado. Aqui está o resultado:

Gif de navegação de gaveta

A seguir, vou detalhar as telas principais com mais conceitos de material design.

Botão de ação flutuante (FAB)

Uma das marcas do Material Design é o botão de ação flutuante (ou FAB). Os componentes e fornecem uma implementação útil do Botão de ação flutuante de acordo com os princípios do Material Design. Com configuração mínima, adicionarei isso à tela Meus amigos agora mesmo.

Primeiro, vou precisar adicionar o componente do react-native-paper e envolver esse componente em torno do > no App.tsx da seguinte forma:

App.tsx

 import {Provider} from'react-native-paper';
...   ...  

Agora vou adicionar meu botão de ação flutuante à tela Meus amigos. Para fazer isso, preciso do seguinte:

  • Os componentes e do react-native-paper
  • Uma variável de estado fabIsOpen para acompanhar se o FAB está aberto ou fechado
  • Algumas informações sobre se esta tela está ou não visível para o usuário ( isScreenFocused ). Preciso do isScreenFocused porque sem ele, posso acabar com o FAB sendo visível em outras telas além da tela Meus amigos

Esta é a aparência da tela Meus amigos com tudo o que foi adicionado em:

MyFriends.tsx

 import {useIsFocused} de'@ react-navigation/native';
import React, {useState} de'react';
import {View} from'react-native';
importar {FAB, Portal, Title} de'react-native-paper';
importar base de'./styles/base'; interface IMyFriendsProps {} const MyFriends: React.FunctionComponent =(props)=> { const isScreenFocused=useIsFocused (); const [fabIsOpen, setFabIsOpen]=useState (false); Retorna (   Meus amigos    setFabIsOpen (abrir)} ícone={fabIsOpen?'fechar':'conta-múltipla'} ações={[ { ícone:'mais', rótulo:'Adicionar novo amigo', onPress: ()=> {}, }, { ícone:'exportar arquivo', rótulo:'Exportar lista de amigos', onPress: ()=> {}, }, ]} />   );
};
exportar MyFriends padrão;

Agora, a tela Meus amigos se comporta da seguinte forma:

Gif de demonstração do botão de ação flutuante

A seguir, adicionarei uma barra de ação contextual, que pode ser ativada sempre que um item em uma das telas for pressionado por muito tempo.

Barra de ação contextual

Aplicativos como Gmail e Google Fotos usam um conceito de design de material denominado Barra de ação contextual . Vou implementar uma versão disso rapidamente no aplicativo atual.

Primeiro, vou construir o próprio componente ContextualActionBar usando o componente Appbar de react-native-paper . Deve ser parecido com isto, para começar com:

./components/ContextualActionBar.tsx

 import React from'react';
import {Appbar} de'react-native-paper'; interface IContextualActionBarProps {} const ContextualActionBar: React.FunctionComponent =( adereços
)=> { Retorna (   {}}/>   {}}/>  {}}/>  {}}/>  {}}/>  );
};
exportar ContextualActionBar padrão;

Agora quero que este componente seja renderizado no topo do cabeçalho da tela fornecida sempre que um item for pressionado por muito tempo De volta à tela Meus amigos, adicionei alguns itens para essa finalidade. Nessa tela, aqui está como vou renderizar a barra de ação contextual sobre o cabeçalho da tela:

MyFriends.tsx

 import {useNavigation} de'@ react-navigation/native';
importar ContextualActionBar de'./components/ContextualActionBar';
... const [cabIsOpen, setCabIsOpen]=useState (false); navegação const=useNavigation (); const openHeader=useCallback (()=> { setCabIsOpen (! cabIsOpen); }, [cabIsOpen]); useEffect (()=> { if (cabIsOpen) { Navigation.setOptions ({ //tem que usar props: any já que essa é a assinatura de tipo //da navegação de reação... cabeçalho: (props: any)=> (), }); } senão { Navigation.setOptions ({header: undefined}); } }, [cabIsOpen]);
... Retorna ( ...  {}} onLongPress={openHeader} /> ... );

Acima, estou alternando um valor booleano de estado ( cabIsOpen ) sempre que um determinado item é pressionado por muito tempo. Com base nesse valor, eu alterno o cabeçalho React Navigation para renderizar a ou retorno para renderizar o cabeçalho React Navigation padrão.

Agora, devo ter uma barra de ação contextual exibida quando pressiono longamente o item “Amigo nº 1”. No entanto, o título ainda está vazio e não posso fazer nada em nenhuma das ações porque a não tem conhecimento do estado do item “Amigo # 1” ou do item maior de Meus amigos tela como um todo.

Assim, a próxima etapa é adicionar um título na e passar uma função que pode fechar a barra e ser acionada por um dos botões na barra.

Para fazer isso, preciso adicionar outra variável de estado à tela Meus amigos:

 const [selectedItemName, setSelectedItemName]=useState ('');

Também preciso criar uma função que feche o cabeçalho e redefina a variável de estado acima:

 const closeHeader=useCallback (()=> { setCabIsOpen (false); setSelectedItemName (''); }, []);

Então, preciso passar selectedItemName e closeHeader como adereços para :

 useEffect (()=> { if (cabIsOpen) { Navigation.setOptions ({ cabeçalho: (adereços: qualquer)=> (  ), }); } senão { Navigation.setOptions ({header: undefined}); } }, [cabIsOpen, selectedItemName]);

Por último, preciso definir selectedItemName como o título do item que foi pressionado por muito tempo:

... const openHeader=useCallback ((str: string)=> { setSelectedItemName (str); setCabIsOpen (! cabIsOpen); }, [cabIsOpen]); ... Retorna ( ...  openHeader ('Amigo # 1')} /> );

E agora posso usar as propriedades title e close em da seguinte maneira:

./components/ContextualActionBar.tsx

 interface IContextualActionBarProps { título: string; fechar: ()=> vazio;
}
... Retorna ( ...   ... );

Agora, eu tenho uma barra de ação contextual inspirada no Material Design, utilizando react-native-paper e react-navigation, que se parece com o seguinte:

Barra de ação contextual, ativa quando o usuário pressiona longamente um item
Barra de ação contextual, ativa quando o usuário pressiona longamente um item

Temas

A última coisa que quero fazer é definir um tema para meu aplicativo para que eu possa alterar a cor primária, a cor secundária, as cores do texto etc.

O tema é um pouco complicado porque tanto react-navigation quanto react-native-paper têm seus próprios componentes ThemeProvider e podem entrar em conflito facilmente. Felizmente, há um ótimo guia disponível sobre como criar um tema para um aplicativo que usa ambos react-Native-paper e react-navigation . Se você seguir isso, estará pronto para ir.

Adicionarei uma ajudinha extra para aqueles que usam o Typescript e se deparariam com erros esotéricos ao tentar seguir o guia acima.

Primeiro, criarei um arquivo de tema semelhante ao seguinte. Algumas coisas a serem observadas são:

  • O tipo de retorno de combineThemes abrange ReactNavigationTheme e ReactNativePaper.Theme
  • Eu mudei as cores primária e acentuação , que afetarão o CAB e o FAB respectivamente
  • Eu adicionei uma nova cor ao tema chamada animationColor . Se você não quiser adicionar uma nova cor, não precisa declarar o namespace global

theme.ts

 import { DarkTheme as NavigationDarkTheme, DefaultTheme as NavigationDefaultTheme, Tema,
} de'@ react-navigation/native';
import {ColorSchemeName} de'react-native';
import { DarkTheme as PaperDarkTheme, DefaultTheme as PaperDefaultTheme,
} de'react-native-paper';
declare global { namespace ReactNativePaper { interface ThemeColors { animationColor: string; } interface Theme { statusBar:'light'|'escuro'|'auto'|'invertido'| Indefinido; } }
}
interface ReactNavigationTheme extends Theme { statusBar:'light'|'escuro'|'auto'|'invertido'| Indefinido;
}
função de exportação combineThemes ( themeType: ColorSchemeName
): ReactNativePaper.Theme | ReactNavigationTheme { const CombinedDefaultTheme: ReactNativePaper.Theme={ ... NavigationDefaultTheme, ... PaperDefaultTheme, statusBar:'dark', cores: { ... NavigationDefaultTheme.colors, ... PaperDefaultTheme.colors, animationColor:'# 2922ff', primário:'# 079c20', sotaque:'# 2922ff', }, }; const CombinedDarkTheme: ReactNativePaper.Theme={ ... NavigationDarkTheme, ... PaperDarkTheme, modo:'adaptativo', statusBar:'light', cores: { ... NavigationDarkTheme.colors, ... PaperDarkTheme.colors, animationColor:'# 6262ff', primário:'# 079c20', sotaque:'# 2922ff', }, }; return themeType==='dark'? CombinedDarkTheme: CombinedDefaultTheme;
}

Então, de volta ao App.tsx , adicionarei meu tema ao componente react-native-paper Provider e ao NavigationContainer componente da navegação de reação da seguinte maneira:

App.tsx

 import {useColorScheme} de'react-native';
importar {NavigationContainer, Theme} de'@ react-navigation/native';
import {combineThemes} de'./theme';
... const colorScheme=useColorScheme () as'light'|'Sombrio'; tema const=combineThemes (colorScheme); ...    

Estou usando o Expo, então também preciso adicionar o seguinte no app.json para habilitar o modo escuro. Você pode não precisar, no entanto.

"userInterfaceStyle":"automático",

E agora, um aplicativo com tema personalizado e modo escuro ativado, inspirado no Material Design! Parece ótimo!

Barra de ação contextual e botão de ação flutuante com cores personalizadas, claro tema Gaveta aberta, mostrando imagem de cabeçalho, modo de luz Barra de ação contextual e botão de ação flutuante com cores personalizadas, tema escuro Gaveta aberta, mostrando imagem de cabeçalho, modo escuro

Conclusão

Se você me acompanhou até o fim aqui, então você deve ter seu próprio aplicativo de plataforma cruzada com elementos de design de material da biblioteca de papel nativo react, como Drawer Navigation (com designs personalizados no menu de gaveta), Floating Botões de ação e barras de ação contextuais. Você também deve ter o tema ativado, o que funciona bem com as bibliotecas react-native-paper e react-navigation. Essa configuração deve permitir que você crie seu próximo aplicativo móvel de forma rápida e elegante com facilidade.

A postagem Using Material UI in React Native apareceu primeiro no LogRocket Blog .

Source link