As caixas de alerta são um componente intrínseco da web e sua utilidade varia de acordo com seus casos de uso. Eles são usados ​​para exibir mensagens, avisos, alertas e consentimentos de confirmação.

Com uma caixa de diálogo de alerta, o usuário geralmente obtém as opções de botão para concordar, discordar e cancelar. Às vezes, os alertas também são usados ​​para registrar a entrada de um usuário, mas isso depende da plataforma.

Neste artigo, aprenderemos como criar uma caixa de diálogo de alerta personalizado no React Native para atender às necessidades do seu projeto.

Introdução

O React Native fornece uma API de alerta, que pode ser usada para exibir caixas de diálogo de alerta nativas no Android e iOS. Mas há limitações com as caixas de diálogo de alerta nativas.

Por exemplo, no Android não podemos mostrar mais do que três botões e nenhuma opção é fornecida para capturar as entradas dos usuários. Embora o iOS permita que tenhamos muitos botões e que os usuários insiram os dados, ainda não podemos mostrar imagens, gráficos ou ter qualquer tipo de personalização, exceto texto.

Para lidar com essas limitações, precisamos crie diálogos de alerta personalizados. Uma caixa de diálogo de alerta personalizado pode atuar como modal e oferecer suporte a componentes.

Propriedades de uma caixa de alerta

Antes de personalizar qualquer componente nativo, devemos ter um entendimento claro de sua arquitetura e tratamento de eventos.

Por exemplo, um botão contém várias propriedades, como rótulo e bulginess. Um botão também mantém eventos como pressionar, segurar, soltar, pairar e assim por diante. Quando o personalizamos, precisamos considerar todas essas propriedades. Caso contrário, perderemos a aparência, o comportamento e a funcionalidade.

Uma caixa de alerta nativa tem as seguintes propriedades:

Título-Um título de texto para indicar a finalidade do Alerta. Compatível com Android e iOS Mensagem-Uma mensagem de texto para explicar o aviso ou aviso. Compatível com botões Android e iOS-Android suporta um máximo de três botões, enquanto iOS suporta toque externo ilimitado-Alerta no Android pode ser fechado tocando fora do alerta onPress-Função para chamar com o pressionar de um botão. Tanto o Android quanto o iOS suportam onDismiss-Função para chamar quando um alerta é fechado. Apenas o Android suporta este Prompt-Permite que os usuários insiram dados nos campos de entrada. Apenas iOS suporta este botão Voltar-Por padrão, o Alerta fecha com o pressionamento de um botão Voltar no Android

Precisamos considerar todas essas propriedades ao personalizar a caixa de Alerta.

A IU e a arquitetura do caixas de diálogo de alerta

Vamos ver a aparência do Alerta nativo e a colocação de diferentes elementos nele. Os alertas do Android e do iOS são diferentes na aparência:

Especificações do Android

De acordo com Material conceitos de design , a tipografia e as cores das caixas de diálogo de alerta do Android são as seguintes:

Elemento Categoria Atributo Valor Largura máxima do contêiner
Raio da borda
Cor de fundo 280
2
#FAFAFA Texto do título na cor da superfície
Opacidade
Fonte Peso
Tamanho
Caixa # 000000
100%
Negrito
22
Caixa de frases Texto de suporte na cor da superfície
Opacidade
Fonte Peso
Tamanho
Caixa # 000000
100%
Regular
15
Sen Caixa do Texto do Botão da Caixa Cor primária
Opacidade
Peso da Fonte
Tamanho
Caixa # 387ef5
100%
500
16
Maiúsculas Scrim On Surface Color
Opacity # 232F34
32%

Outras propriedades como altura, largura, preenchimento, margem, etc. são as seguintes:

Para pequeno ações do botão:

Fonte: material.io

Para ações de botões longos:

Fonte: material.io

Outras propriedades incluem:
Elevação-24 dp
Posição-centro
Margem mínima dos lados-48dp

Especificações do iOS

Da mesma forma, para iOS, temos as seguintes especificações:

Elemento Categoria Atributo Valor Borda da superfície do contêiner
Largura máxima
Cor de fundo
Z-index 13px
270px
# f8f8f8
Texto do título 10 na cor da superfície
Preenchimento
Margem superior
Alinhar
Fonte
Tamanho
Caixa nº 000000
12px 16px 7px
8px
Centro
600
17px
Caixa de frases Texto de apoio na cor da superfície
Alinhar
Preenchimento
Fonte
Tamanho
Caixa nº 000000
Centro
0px 16px 21px
Regular
13
Propriedades comuns do recipiente do botão da caixa da frase
Botão Ok
Uma única linha Multi botões
-Comum
-Botões não ok Margem à direita
Altura mínima
Borda superior
Tamanho da fonte
Cor
Altura da linha
Peso da fonte
Largura mínima
Borda direita-0,55px
44px
0,55px sólido # dbdbdf
17px
# 387ef5
20px
700
50%
0,55px sólido #dbdbdf Scrim On Surface Color
Opacity # 000000
30%

Esta informação é coletada em Ionic Documentação do AlertController.

Bibliotecas e pacotes de alertas personalizados

Existem algumas bibliotecas no GitHub que permitem criar caixas de alerta personalizadas. Alguns deles são react-native-awesome-alerts, react-native-dialog e react-native-modal. Você pode experimentar essas bibliotecas, mas, neste artigo, iremos personalizar a caixa de alerta sem elas.

A diferença entre alerta e modal

Alerta e modal são semanticamente as mesmas coisas com uma diferença em complexidade e usabilidade.

Os diálogos de alerta foram criados para exibir mensagens curtas da maneira mais simples possível e é por isso que sua funcionalidade é limitada.

Por outro lado , os modais são usados ​​para exibições complexas. Eles exigem que definamos todo o conteúdo por nós mesmos. Por padrão, eles fornecem ouvintes de eventos como um manipulador de botão Voltar.

Personalizando a caixa de diálogo de alerta

Vamos primeiro verificar o que iremos personalizar. Devemos lembrar que os alertas são usados ​​para exibir mensagens importantes. Podem ser erros, avisos ou notificações. Eles não se destinam a mostrar imagens ou preencher formulários. Para isso, você deve usar modais.

Em Alerta, iremos personalizar:

A cor de fundo da caixa de diálogo A cor da fonte, tamanho, peso, etc. do título e da mensagem A cor da fonte , cor de fundo e estilo de borda dos botões

Como o React Native chama os componentes nativos de alerta do Android e iOS, ele não fornece um método direto para personalizá-los. Alertas são componentes fixos com finalidade definida e, portanto, não personalizáveis ​​no Android e iOS. Os desenvolvedores Android usam a classe Dialog para isso.

Em nosso caso, vamos usar a API Modal do React Native. As vantagens de usar esta API são:

Não precisamos nos preocupar com a colocação de nosso Alerta personalizado. Ele permanecerá na parte superior de todo o aplicativo. O evento do botão Voltar no Android e o botão de menu na Apple TV serão automaticamente tratados por ele

Breve introdução ao React Native Modal

A API React Native Modal fornece um contêiner que é exibido acima de sua visão envolvente. Uma propriedade booleana visível é passada ao componente modal para mostrá-la ou ocultá-la. Existem outros adereços, mas não estamos preocupados com eles porque não são úteis para um Alerta.

É assim que o Modal funciona:

import React, {useState} from’reagir’; import {modal, texto, prensável, visualização} de’react-native’; const App=()=> {const [modalVisible, setModalVisible]=useState (false); return ( {setModalVisible (! modalVisible);}}> /** * Qualquer coisa aqui será exibida no Modal. * Precisamos criar uma sobreposição de fundo e uma caixa de Alerta. */ /** * Conteúdo do aplicativo principal. Isso ficará oculto quando o modal for aberto */ ); }; exportar aplicativo padrão;

modalVisible é a variável de estado usada para mostrar ou ocultar o Modal. Você pode manter o modal em uma única página ou incluir todo o seu aplicativo em sua Visualização pai. É melhor usar uma biblioteca de gerenciamento de armazenamento e estado como o Redux porque ela ajudará você a alterar a variável modalVisible de qualquer lugar em um aplicativo.

Criando um botão para abrir o Alerta

Primeiro de tudo, precisaremos de um evento para alterar o valor de modalVisible. Em nosso código, usaremos um botão. Ao pressionar este botão, modalVisible se tornará verdadeiro e um Modal será exibido. Para criar o botão, usaremos o componente Pressable:

import React, {useState} from’react’; import {modal, texto, prensável, visualização} de’react-native’; const App=()=> {const [modalVisible, setModalVisible]=useState (false); return ( {setModalVisible (! modalVisible);}}> /** * Qualquer coisa aqui será exibida no Modal. * Precisamos criar uma sobreposição de plano de fundo e uma caixa de alerta. */ setModalVisible (true)}> Mostrar modal ); }; const styles=StyleSheet.create ({centeredView: {flex: 1, justifyContent:”center”, alignItems:”center”, marginTop: 22}, botão: {borderRadius: 20, padding: 10, elevation: 2}, buttonOpen: {backgroundColor:”# F194FF”,}, textStyle: {color:”white”, fontWeight:”bold”, textAlign:”center”},}); exportar aplicativo padrão;

Neste código, adicionamos alguns estilos para melhorar a aparência do botão e outras partes do aplicativo. Atualmente, ele mostrará um botão. Tocar neste botão abrirá o modal. A saída renderizada será semelhante a:

Criando a IU da caixa de diálogo de alerta

A próxima etapa é criar a IU modal. Mas, primeiro, precisamos definir uma maneira de diferenciar entre a IU padrão de ambos os sistemas operacionais. O iOS tem uma visão diferente do Android. Para reconhecer o sistema operacional, o React Native fornece a API da plataforma.

Vamos começar criando o pano de fundo. Conforme discutimos na seção IU e arquitetura, a cor de fundo e a opacidade no Android são # 232F34 e 0,32, respectivamente. Para iOS, esses valores são # 000000 e 0,3 respectivamente:

import React, {useState} from’react’; import {Modal, Texto, Pressionável, Visualização, Plataforma} de’react-nativo’; const App=()=> {const [modalVisible, setModalVisible]=useState (false); return ( {setModalVisible (! modalVisible);}}> setModalVisible (false)}/> /** * Tudo aqui será exibido no Modal. * Precisamos criar sobreposição de plano de fundo e caixa de alerta. */ setModalVisible (true)}> Mostrar modal ); }; const styles=StyleSheet.create ({centeredView: {flex: 1, justifyContent:”center”, alignItems:”center”, marginTop: 22}, botão: {borderRadius: 20, padding: 10, elevation: 2}, buttonOpen: {backgroundColor:”# F194FF”,}, textStyle: {color:”white”, fontWeight:”bold”, textAlign:”center”}, iOSBackdrop: {backgroundColor:”# 000000″, opacidade: 0.3}, androidBackdrop: { backgroundColor:”# 232f34″, opacidade: 0,32}, pano de fundo: {position:’absoluto’, top: 0, left: 0, right: 0, bottom: 0,}}); exportar aplicativo padrão;

A saída renderizada ficará assim:

Observe que usamos o componente Pressable para criar o cenário. Isso porque queríamos adicionar a funcionalidade de fechar o modal ao pressionar o pano de fundo.

Em seguida, criaremos uma caixa de diálogo de alerta sobre esse pano de fundo. Mas primeiro, devemos colocar o Modal em um componente separado. Isso ajudará a chamar nosso Alerta personalizado com estilos diferentes:

import React, {useState} de”react”; import {Alert, Modal, StyleSheet, Text, Pressable, View, Platform} de”react-native”; const CustomAlert=(props)=> {return ( {props.setModalVisible (false);}}> props.setModalVisible (false)}/> )} const App=()=> {const [modalVisible, setModalVisible]=useState (false); return ( setModalVisible (true)}> Mostrar modal ); }; const styles=StyleSheet.create ({centeredView: {flex: 1, justifyContent:”center”, alignItems:”center”, marginTop: 22}, botão: {borderRadius: 20, padding: 10, elevation: 2}, buttonOpen: {backgroundColor:”# F194FF”,}, textStyle: {color:”white”, fontWeight:”bold”, textAlign:”center”}, iOSBackdrop: {backgroundColor:”# 000000″, opacidade: 0.3}, androidBackdrop: { backgroundColor:”# 232f34″, opacidade: 0,32}, pano de fundo: {position:’absoluto’, top: 0, left: 0, right: 0, bottom: 0,}}); exportar aplicativo padrão;

Criamos um componente diferente com o nome CustomAlert e colocamos nosso Modal nele.

O estado modalVisible é mantido em App.js, mas lembre-se de que a melhor abordagem é usar um gerenciamento de armazenamento central biblioteca como Redux. Redux tornará o estado modalVisible acessível a todos os componentes em todo o aplicativo e não haverá a necessidade de passar modalVisible como adereços.

É hora de definir os valores padrão para Modal. Esses valores projetarão a caixa semelhante à caixa de alerta nativa para Android e iOS.

Já definimos todos os valores na seção de IU e arquitetura. Vamos começar com o Android.

Diálogo de alerta personalizado do Android

Os valores padrão são:

Style Property Value Caixa
Cor do fundo
Largura máxima
Margem
Elevação
Raio da borda transparente
280
48
24
2 Título
Margem
Cor
Tamanho da fonte
Peso da fonte 24
# 000000
22
Mensagem em negrito
Margem esquerda
Margem direita
Margem inferior
Cor
Tamanho da fonte
Peso da fonte 24
24
24
# 000000
15
Grupo de botões normais
Margem 0 0 8 24 Botão
Margem superior
Margem direita
Preenchimento
Cor
Tamanho da fonte
Fonte Peso
Transformação do texto
Cor de fundo 12
8
10
# 387ef5
16
500
caixa alta
transparente

Esses valores padrão são definidos no componente CustomAlert. Eles são usados ​​nos casos em que um usuário não fornece valores.

Diferentes props para o componente CustomAlert são:

Prop Values ​​ Usar modalVisible true | false Obrigatório Para exibir/ocultar a função setModalVisible modal Obrigatório Para alterar o valor de modalVisible title String Opcional Defina o título da mensagem da caixa de Alerta String Opcional Defina a mensagem android {container: {backgroundColor: String}, title: {color: String, fontFamily: String, fontSize: Number, fontWeight: String,}, message: {color: String, fontFamily: String, fontSize: Number, fontWeight: String},} Todos os campos opcionais Definir o estilo da caixa de alerta, título e mensagem para o aplicativo Android ios {container: {backgroundColor: String}, title: {color: String, fontFamily: String, fontSize: Number, fo ntWeight: String,}, message: {color: String, fontFamily: String, fontSize: Number, fontWeight: String},} Todos os campos opcionais Defina o estilo da caixa de Alerta, título e mensagem para botões de aplicativos iOS [{text: String, func: Função, estilos: {color: String, fontSize: Number, fontWeight: String, fontFamily: String, textTransform: String, backgroundColor: String}}] Todos os campos opcionais Defina as propriedades dos botões. Existem alguns pontos:

Android suporta no máximo três botões. Se o texto do botão não for fornecido, ele usará OK, CANCELAR, PERGUNTAR MAIS TARDE. Todos os botões fecharão a caixa de alerta e executarão as funções fornecidas. fornecido, ele mostrará o botão OK por padrão

Verifique este código para entender como CustomAlert está definindo os padrões:

const CustomAlert=(props)=> {const [androidDefaults, setAndroidDefaults]=useState ({container: {backgroundColor: (props.android && props.android.container && props.android.container.backgroundColor) ||’#FAFAFA’,}, title: {color: (props.android && props.android. title && props.android.title.color) ||’# 000000′, fontFamily: (props.android && props.android.title && props.android.title.fontFamily) ||’initial’, fontSize: (props.android && props.android.title && props.android.title.fontSize) || 22, fontWeight: (props.android && props.android.title && props.android.title.fontWeight) ||’negrito’,}, mensagem: {color: (props.android && props.android.message && props.android.message.color) ||’# 000000′, fontFamily: (props.android && props.android.message && props.android.message.fontFamily) ||’initial’, fontSize: (props.android && props.android.message && props.android.message.fontSize) || 15, fontWeight: (props.android && props.android.message && props.android.message.fontWeight) ||’normal’,}, botão: {color:’# 387ef5′, fontFamily:’initial’, fontSize: 16, fontWeight:’500′, textTransform:’uppercase’, backgroundColor:’transparent’,},}); return ( {props.setModalVisible (false);}}> props.setModalVisible (false)}/> {Platform.OS===”ios”? null: {props.title ||’Message’} {props.message ||”} } )}

Alguns estilos são para o layout e é por isso que não oferecemos a opção de alterá-los. Eles são declarados no objeto StyleSheet:

const styles=StyleSheet.create ({centeredView: {flex: 1, justifyContent:”center”, alignItems:”center”, marginTop: 22}, botão: {borderRadius: 20 , preenchimento: 10, elevação: 2}, buttonOpen: {backgroundColor:”# F194FF”,}, textStyle: {color:”white”, fontWeight:”bold”, textAlign:”center”}, iOSBackdrop: {backgroundColor:”# 000000″, opacidade: 0,3}, androidBackdrop: {backgroundColor:”# 232f34″, opacidade: 0,4}, pano de fundo: {position:’absoluto’, top: 0, left: 0, bottom: 0, right: 0}, alertBox: {flex: 1, justifyContent:’center’, alignItems:’center’}, androidAlertBox: {maxWidth: 280, width:’100%’, margin: 48, elevation: 24, borderRadius: 2,}, androidTitle: {margin: 24,}, androidMessage: {marginLeft: 24, marginRight: 24, marginBottom: 24,}, androidBut tonGroup: {marginTop: 0, marginRight: 0, marginBottom: 8, marginLeft: 24,}, androidButton: {marginTop: 12, marginRight: 8,}, androidButtonInner: {preenchimento: 10,}});

Se executarmos isso usando configurações diferentes, obteremos os seguintes resultados:

É hora de adicionar os botões à caixa de diálogo de alerta. Existem algumas especificações do Android:

Um único botão está sempre OK Dois botões são CANCELAR e OK Três botões são PERGUNTAR MAIS TARDE, CANCELAR e OK No máximo, três botões são suportados Dois botões flutuam no lado direito da caixa enquanto o terceiro botão flutua no lado esquerdo. Os botões longos são exibidos em linhas separadas

Para cumprir todas essas condições, decidimos declarar um componente separado para um grupo de botões. Vamos chamá-lo de AndroidButtonBox. Verifique o código:

const AndroidButtonBox=()=> {const [buttonLayoutHorizontal, setButtonLayoutHorizontal]=useState (1); const buttonProps=props.buttons && props.buttons.length> 0? props.buttons: [{}] return ( {if (e.nativeEvent.layout.height> 60) setButtonLayoutHorizontal (0);}}> {buttonProps.map ((item, index)=> {if (index> 2) return null; const alignSelfProperty=buttonProps.length> 2 && index===0 && buttonLayoutHorizontal===1?’flex-start’:’flex-end’; let defaultButtonText=’OK’if (buttonProps.length> 2) {if (index===0) defaultButtonText=’PERGUNTE MAIS TARDE’else if (index===1) defaultButtonText=’CANCEL’;} else if (buttonProps.length===2 && index===0) defaultButtonText=’CANCEL’; return ( {props.setModalVisible (false) if (item.func && typeof (item.func)===’função’) item.func ( ); }} style={[{alignSelf: alignSelfProperty,}]}> {item.text || defaultButtonText} )})} ); }

Neste código, declaramos uma variável de estado, buttonLayoutHorizontal. Isso será usado para alterar o layout do grupo de botões de colunas para linhas. Se todos os botões forem curtos, eles serão exibidos em uma única linha.

O evento onLayout é usado para determinar se há necessidade de alterar esta variável de estado. Em seguida, executamos um loop sobre a matriz de botões fornecida por meio de adereços e criamos botões com estilo adequado.

O código inteiro (para Android) será semelhante a este:

import React, {useState} from”reagir”; import {Alert, Modal, StyleSheet, Text, Pressable, View, Platform} de”react-native”; const CustomAlert=(props)=> {const [androidDefaults, setAndroidDefaults]=useState ({container: {backgroundColor: (props.android && props.android.container && props.android.container.backgroundColor) ||’#FAFAFA’, }, título: {cor: (props.android && props.android.title && props.android.title.color) ||’# 000000′, fontFamily: (props.android && props.android.title && props.android. title.fontFamily) ||’inicial’, fontSize: (props.android && props.android.title && props.android.title.fontSize) || 22, fontWeight: (props.android && props.android.title && props. android.title.fontWeight) ||’bold’,}, mensagem: {color: (props.android && props.android.message && props.android.message.color) ||’# 000000′, fontFamily: (props. android && props.android.message && props.android.message.fontFamily) ||’initial’, fontSize: (props.android && props.android.message && props.android.message.fontSize) || 15, fontWeight: ( suporte s.android && props.android.message && props.android.message.fontWeight) ||’normal’,}, botão: {color:’# 387ef5′, fontFamily:’initial’, fontSize: 16, fontWeight:’500′, textTransform:’uppercase’, backgroundColor:’transparent’,},}); const AndroidButtonBox=()=> {const [buttonLayoutHorizontal, setButtonLayoutHorizontal]=useState (1); const buttonProps=props.buttons && props.buttons.length> 0? props.buttons: [{}] return ( {if (e.nativeEvent.layout.height> 60) setButtonLayoutHorizontal (0);}}> {buttonProps.map ((item, index)=> {if (index> 2) return null; const alignSelfProperty=buttonProps.length> 2 && index===0 && buttonLayoutHorizontal===1?’flex-start’:’flex-end’; let defaultButtonText=’OK’if (buttonProps.length> 2) {if (index===0) defaultButtonText=’PERGUNTAR MAIS TARDE’else if (index===1) defaultButtonText=’CANCEL’;} else if (buttonProps.length===2 && index===0) defaultButtonText=’CANCEL’; return ( {props.setModalVisible (false) if (item.func && typeof (item.func)===’função’) item.func ( ); }} style={[{alignSelf: alignSelfProperty,}]}> {item.text || defaultButtonText} )})} ); } return ( {props.setModalVisible (false);}}> props.setModalVisible (false)}/> {Platform.OS===”ios”? null: {props.title ||’Message’} {props.message ||”} } ) } const App=()=> { const [modalVisible, setModalVisible]=useState(false); return ( {console.log(‘Yes Pressed’)}, styles: { color:’#FFFFFF’, fontSize: 18, fontWeight:’bold’, fontFamily:’Roboto’, textTransform:’none’, backgroundColor:’#000000′ } }]} /> setModalVisible(true)} > Show Modal ); }; const styles=StyleSheet.create({ centeredView: { flex: 1, justifyContent:”center”, alignItems:”center”, marginTop: 22 }, button: { borderRadius: 20, padding: 10, elevation: 2 }, buttonOpen: { backgroundColor:”#F194FF”, }, textStyle: { color:”white”, fontWeight:”bold”, textAlign:”center” }, iOSBackdrop: { backgroundColor:”#000000″, opacity: 0.3 }, androidBackdrop: { backgroundColor:”#232f34″, opacity: 0.4 }, backdrop: { position:’absolute’, top: 0, left: 0, bottom: 0, right: 0 }, alertBox: { flex: 1, justifyContent:’center’, alignItems:’center’ }, androidAlertBox: { maxWidth: 280, width:’100%’, margin: 48, elevation: 24, borderRadius: 2, }, androidTitle: { margin: 24, }, androidMessage: { marginLeft: 24, marginRight: 24, marginBottom: 24, }, androidButtonGroup: { marginTop: 0, marginRight: 0, marginBottom: 8, marginLeft: 24, }, androidButton: { marginTop: 12, marginRight: 8, }, androidButtonInner: { padding: 10, } }); export default App;

The rendered output for different values of CustomAlert are:

iOS custom alert dialog

The code for an iOS alert box will be similar to Android with changes in styling.

In iOS, all the entities like the title, message, and buttons are center aligned. There can be any number of buttons. The complete code for an iOS and Android CustomAlert box is:

import React, { useState } from”react”; import { Alert, Modal, StyleSheet, Text, Pressable, View, Platform } from”react-native”; const CustomAlert=(props)=> { const [androidDefaults, setAndroidDefaults]=useState({ container: { backgroundColor: (props.android && props.android.container && props.android.container.backgroundColor) ||’#FAFAFA’, }, title: { color: (props.android && props.android.title && props.android.title.color) ||’#000000′, fontFamily: (props.android && props.android.title && props.android.title.fontFamily) ||’initial’, fontSize: (props.android && props.android.title && props.android.title.fontSize) || 22, fontWeight: (props.android && props.android.title && props.android.title.fontWeight) ||’bold’, }, message: { color: (props.android && props.android.message && props.android.message.color) ||’#000000′, fontFamily: (props.android && props.android.message && props.android.message.fontFamily) ||’initial’, fontSize: (props.android && props.android.message && props.android.message.fontSize) || 15, fontWeight: (prop s.android && props.android.message && props.android.message.fontWeight) ||’normal’, }, button: { color:’#387ef5′, fontFamily:’initial’, fontSize: 16, fontWeight:’500′, textTransform:’uppercase’, backgroundColor:’transparent’, }, }); const [iOSDefaults, setIOSDefaults]=useState({ container: { backgroundColor: (props.ios && props.ios.container && props.ios.container.backgroundColor) ||’#F8F8F8′, }, title: { color: (props.ios && props.ios.title && props.ios.title.color) ||’#000000′, fontFamily: (props.ios && props.ios.title && props.ios.title.fontFamily) ||’initial’, fontSize: (props.ios && props.ios.title && props.ios.title.fontSize) || 17, fontWeight: (props.ios && props.ios.title && props.ios.title.fontWeight) ||’600′, }, message: { color: (props.ios && props.ios.message && props.ios.message.color) ||’#000000′, fontFamily: (props.ios && props.ios.message && props.ios.message.fontFamily) ||’initial’, fontSize: (props.ios && props.ios.message && props.ios.message.fontSize) || 13, fontWeight: (props.ios && props.ios.message && props.ios.message.fontWeight) ||’normal’, }, button: { color:’#387ef5′, fontFamily:’init ial’, fontSize: 17, fontWeight:’500′, textTransform:’none’, backgroundColor:’transparent’, }, }); const AndroidButtonBox=()=> { const [buttonLayoutHorizontal, setButtonLayoutHorizontal]=useState(1); const buttonProps=props.buttons && props.buttons.length > 0 ? props.buttons: [{}] return ( { if(e.nativeEvent.layout.height > 60) setButtonLayoutHorizontal(0); }}> { buttonProps.map((item, index)=> { if(index > 2) return null; const alignSelfProperty=buttonProps.length > 2 && index===0 && buttonLayoutHorizontal===1 ? ‘flex-start’:’flex-end’; let defaultButtonText=’OK’ if(buttonProps.length > 2){ if(index===0) defaultButtonText=’ASK ME LATER’ else if(index===1) defaultButtonText=’CANCEL’; } else if (buttonProps.length===2 && index===0) defaultButtonText=’CANCEL’; return ( { props.setModalVisible(false) if(item.func && typeof(item.func)===’function’) item.func(); }} style={[{ alignSelf: alignSelfProperty, }]}> {item.text || defaultButtonText} ) }) } ); } const IOSButtonBox=()=> { const buttonProps=props.buttons && props.buttons.length > 0 ? props.buttons: [{}] const [buttonLayoutHorizontal, setButtonLayoutHorizontal]=useState(buttonProps.length===2 ? 1: 0); return ( { if(e.nativeEvent.layout.height > 60) setButtonLayoutHorizontal(0); }}> { buttonProps.map((item, index)=> { let defaultButtonText=’OK’ if(buttonProps.length > 2){ if(index===0) defaultButtonText=’ASK ME LATER’ else if(index===1) defaultButtonText=’CANCEL’; } else if (buttonProps.length===2 && index===0) defaultButtonText=’CANCEL’; const singleButtonWrapperStyle={} let singleButtonWeight=iOSDefaults.button.fontWeight; if(index===buttonProps.length-1){ singleButtonWeight=’700′; } if(buttonLayoutHorizontal===1){ singleButtonWrapperStyle.minWi dth=’50%’; if(index===0){ singleButtonWrapperStyle.borderStyle=’solid’; singleButtonWrapperStyle.borderRightWidth=0.55; singleButtonWrapperStyle.borderRightColor=’#dbdbdf’; } } return ( { props.setModalVisible(false) if(item.func && typeof(item.func)===’function’) item.func(); }}> {item.text || defaultButtonText} ) }) } ); } return ( { props.setModalVisible(false); }} > props.setModalVisible(false)}/> { Platform.OS===”ios”? {props.title ||’Message’} {props.message ||”} : {props.title ||’Message’} {props.message ||”} } ) } const App=()=> { const [modalVisible, setModalVisible]=useState(false); return ( {console.log(‘Yes Pressed’)}, styles: { color:’#FFFFFF’, fontSize: 18, fontWeight:’bold’, fontFamily:’Roboto’, textTransform:’none’, backgroundColor:’#000000′ } }]} /> setModalVisible(true)} > Show Modal ); }; const styles=StyleSheet.create({ centeredView: { flex: 1, justifyContent:”center”, alignItems:”center”, marginTop: 22 }, button: { borderRadius: 20, padding: 10, elevation: 2 }, buttonOpen: { backgroundColor:”#F194FF”, }, textStyle: { color:”white”, fontWeight:”bold”, textAlign:”center” }, iOSBackdrop: { backgroundColor:”#000000″, opacity: 0.3 }, androidBackdrop: { backgroundColor:”#232f34″, opacity: 0.4 }, backdrop: { position:’absolute’, top: 0, left: 0, bottom: 0, right: 0 }, alertBox: { flex: 1, justifyContent:’center’, alignItems:’center’ }, androidAlertBox: { maxWidth: 280, width:’100%’, margin: 48, elevation: 24, borderRadius: 2, }, androidTitle: { margin: 24, }, androidMessage: { marginLeft: 24, marginRight: 24, marginBottom: 24, }, androidButtonGroup: { marginTop: 0, marginRight: 0, marginBottom: 8, marginLeft: 24, }, androidButton: { marginTop: 12, marginRight: 8, }, androidButtonInner: { padding: 10, }, iOSAlertBox: { maxWidth: 270, width:’100%’, zIndex: 10, borderRadius: 13, }, iOSTitle: { paddingTop: 12, paddingRight: 16, paddingBottom: 7, paddingLeft: 16, marginTop: 8, textAlign:”center”, }, iOSMessage: { paddingTop: 0, paddingRight: 16, paddingBottom: 21, paddingLeft: 16, textAlign:”center” }, iOSButtonGroup: { marginRight:-0.55 }, iOSButton: { borderTopColor:’#dbdbdf’, borderTopWidth: 0.55, borderStyle:’solid’, }, iOSButtonInner: { minHeight: 44, justifyContent:’center’ } }); export default App;

The rendered output for different CustomAlert values are:

Live Demo

Conclusion

In this article, we learned about alert dialogs in both Android and iOS. We also saw the difference between their UI, specifications, and properties.

These alert dialogs have a defined purpose and they should not be overused. Use them only when the message is unavoidable for users, because they block the UI.

There are a lot of scope of enhancements in our custom alert. You can change the paddings, margins, add background images, icons, SVG, etc. If you try this code in your projects, then please let me know how it worked through comments. Thank you.