Dev (Back & Front)ARTIGO

Criando um alerta de mensagens

É muito comum hoje em aplicações Flex/Air a necessidade de transpor informações entre a app e usuário. Grande parte dos usuários não fica satisfeita quando, ao realizar alguma tarefa, o sistema exibe uma caixa com texto e uns botões na parte central da aplicação. Há alguns fatores importantes que devem ser levados em consideração:

  1. Usuários não têm o costume de ler toda a informação contida em alertas.
  2. O usuário não quer ter seu fluxo de trabalho interrompido por um alerta, que na grande parte do tempo ele não quer ler.
  3. Fica difícil, em primeira instância visual, o usuário distinguir se o alerta é um erro ou apenas mensagens de rotina como “salvo com sucesso”.

Se pararmos para pensar melhor, poderemos encontrar outros fatores importantes.

Uma solução elegante para este problema é a criação de um componente que possa passar a mensagem ao usuário de uma forma que não impeça o fluxo de trabalho e, ao mesmo tempo, chame a atenção para a informação que o sistema esteja passando.

Para este propósito vamos um componente de mensagem similar ao que o msn e alguns clientes de twitter, entre outros aplicativos, utilizam.

Requisitos para o desenvolvimento do artigo:

  • Ter Flex/Flash Builder ou outra IDE.
  • Ter SDk 3 ou superior.
  • Conhecimento em ActionScript e Mxml.

Nivel de dificuldade: 5

Certo, agora vamos ao que realmente interessa.

Passo 1

Criar um projeto flex com o nome “AlertaCustomizado” ou outro qualquer e com a seguinte estrutura:

                                                                         

Passo 2

Criar a classe AlertaUI.as. Esta é a classe que será exibida para o usuário, ou seja, será o componente principal. Esta classe é relativamente simples, composta pelos seguintes componentes nativos do flex:

1. O componente base será um Canvas;

2. Teremos dois efeitos Parallel:

  • createEffect = responsável por exibir o componente alerta na tela, este será composto pelos efeitos Move e Fade;
  • removeEffect = responsável por ocultar o componente de alerta da tela pai, este também será composto por dois efeitos, o Move e o Fade. Poderíamos ter utilizado nos dois casos – tanto no create quanto no remove o efeito Move, contudo para dar um pouco mais de elegância utilizaremos o fade;

3. Um componente Label, que será definido como o título do nosso alerta.

4. Um componente Text, que terá o conteúdo do alerta que desejamos apresentar ao usuário.

5. Um componente Image, para ser exibido ao lado do título do alerta.

Segue a baixo o código da classe AlertaUI.mxml. Ele é relativamente simples, o único detalhe é a vinculação dos efeitos createEffect e removeEffect aos respectivos eventos do canvas.

<?xml version="1.0" encoding="utf-8"?><br /><mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="200" height="100"<br />           styleName="fundoAlertaSucesso" paddingBottom="5" paddingLeft="5" paddingTop="5" paddingRight="5"<br />           verticalScrollPolicy="off" horizontalScrollPolicy="off"<br />           creationCompleteEffect="{createEffect}" removedEffect="{removeEffect}"><br /><br />    <mx:Style><br />        .fundoAlertaSucesso{<br />            borderStyle: applicationControlBar;<br />            fill-colors: #03A438, #6FCE8F;<br />            fillAlphas: 1, 1;<br />            highlightAlphas: 0, 0;<br />            drop-shadow-enabled: true;<br />            corner-radius: 5;<br />        }<br /><br />        .fundoAlertaErro{<br />            borderStyle: applicationControlBar;<br />            fill-colors: #E43434, #FCA5A5;<br />            fillAlphas: 1, 1;<br />            highlightAlphas: 0, 0;<br />            drop-shadow-enabled: true;<br />            corner-radius: 5;<br />        }<br />    </mx:Style><br /><br />    <mx:Script><br />        <![CDATA[<br />            [Bindable]<br />            protected var _titulo:String;<br /><br />            [Bindable]<br />            protected var _conteudo:String;<br /><br />            [Bindable]<br />            protected var _icone:String;<br />        ]]><br />    </mx:Script><br /><br />    <!-- Criando e configurando os efeitos --><br />    <mx:Parallel id="createEffect" duration="700"><br />        <mx:Move id="mvExibirAlerta"/><br />        <mx:Fade/><br />    </mx:Parallel><br /><br />    <mx:Parallel id="removeEffect" duration="700"><br />        <mx:Move id="mvOcultarAlerta"/><br />        <mx:Fade/><br />    </mx:Parallel><br /><br />    <mx:Label id="lbTitulo" width="100%" text="{_titulo}" fontFamily="Courier New" fontSize="14"<br />              fontWeight="bold" color="#FFFFFF" left="5" top="5"/><br /><br />    <mx:Text id="tConteudo" htmlText="{_conteudo}" fontFamily="Courier New" fontSize="12" left="5"<br />             top="30" right="5" bottom="5"/><br /><br />    <mx:Image width="20" height="20" right="5" top="5" id="imgIcon" source="{_icone}" visible="{_icone != null}"/><br /><br /></mx:Canvas>

Passo 3

Com o esqueleto do nosso alerta pronto, agora iremos definir as funcionalidades para ele. Para isso, vamos criar uma classe que estenda AlertaUI.mxml. Esta classe, sim, pode parecer complexa, mas é muito simples. Requer apenas um pouco de atenção para alguns detalhes, vamos a eles:

1. Método show – tem o mesmo intuito do método Alert.show, ou seja, exibir o componente na tela. Pode receber até 5 parâmetros:

  • Título = Define o título que será exibido no componente.
  • Conteúdo = Define o conteúdo que será exibido dentro do componente Text.
  • TipoAlerta = irá definir qual o style que será utilizado no Alerta. Digamos que você queira que, quando ocorrer um erro na aplicação, seja exibido um alerta com um estilo diferente para chamar a atenção do usuário, ou que quando ocorra algo rotineiro, como “cadastro salvo com sucesso” etc., seja exibido um alerta também com um estilo diferente. Nessa situação, esse parâmetro é de suma importância, pois aqui você poderá criar diferentes Style.css e defini-los da forma que bem entender. Neste artigo, para exemplo didático, irei criar apenas dois Style, um identificando ERRO e outro SUCESSO.
  • Duração = Define o tempo, em segundos, que o alerta ficará disponível para o usuário, o padrão será 3s.
  • Ícone = Define um ícone a ser mostrado ao lado do título.

Assim, o método show terá as seguintes responsabilidades:

  • instanciar uma nova variável Alerta;
  • configurar o alerta criado baseado nos argumentos passados, como: Título, Ìcone, tipo do style etc.;
  • executar o método PopUpManager.addPopUp passando como parâmetro o alerta criado;
  • e, por último e muito importante: avisar ao Gerenciador de Alerta (falarei disso em breve) que foi criado um novo alerta e ele está sendo exibido na tela.

2. Método onCreate: é o segundo método mais importante do componente. O onCreate está vinculado ao CREATION_COMPLETE; assim, quando todos os componentes do alerta forem criados, ele terminará de realizar algumas configurações que somente são possíveis nesse estágio. São elas:

  • definir o X e o Y do alerta, ou seja, definir onde o alerta será exibido na tela. Para efeito didático, irei abordar a mesmo localização do MSN, no canto inferior direito, mas esta é uma funcionalidade que você poderá, futuramente, customizar para ser exibida em outros locais;
  • configurar o efeito Move do createEffetc. Assim, se já estiver sendo exibido um alerta na tela, deverá ser levado em consideração a posição Y do novo alerta para que ele não fique sobreposto ao antigo. Precisamos apenas configurar o yFrom e o yTo;
  • configurar o efeito Move do removeEffetc para indicar o yTo do mesmo, com ele definirei sempre o Y da altura do Application;
  • Serão adicionados dois listeners: MouseEvent.ROLL_OVER e MouseEvent.ROLL_OVER. Neles estará a jogada do alerta. Será bem comum o sistema exibir um alerta e o usuário não conseguir ler todo o seu conteúdo, ou até mesmo fechá-lo. Para resolver este problema, iremos fazer com que quando o usuário colocar o mouse em cima do alerta, ele não será ocultado, mesmo que o tempo de 3 segundos seja atingido, e que quando o usuário remover o mouse do alerta, ele será ocultado imediatamente;
  • criar e configurando um timer para o Alerta. Isso vai marcar quando o alerta deverá ser ocultado.

3. Método fecharAlerta: apenas remove da tela o alerta e avisa isso ao gerenciador de alerta.

Segue o código do Alerta.as

package com.fabielprestes.views.impl {<br />    import com.fabielprestes.views.AlertaUI;<br /><br />    import flash.display.DisplayObject;<br />    import flash.events.MouseEvent;<br />    import flash.events.TimerEvent;<br />    import flash.utils.Timer;<br /><br />    import mx.core.Application;<br />    import mx.events.FlexEvent;<br />    import mx.managers.PopUpManager;<br /><br /><br />    /**<br />     * Responsavel por exibir e controlar o componente de alerta na tela.<br />     *<br />     * @author Fabiel Prestes<br />     */<br />    public class Alerta extends AlertaUI {<br /><br />        private var _novaAltura:int;<br /><br />        private var _duracao:int = 3000;<br /><br />        private var _timerOcultarAlerta:Timer;<br /><br />        public static var ALERTA_SUCESSO:int = 0;<br />        public static var ALERTA_ERRO:int = 1;<br /><br />        public function Alerta() {<br />            super();<br /><br />            this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreate);<br />        }<br /><br />        /**<br />         * @private<br />         * Espera o alerta ser totalmente criado para seguir o fluxo de configuraçao de posicionamento.<br />         * @param evt<br />         */<br />        private function onCreate(evt:FlexEvent):void {<br /><br />            /* Definindo o local onde o alerta será exibido,<br />             * Por simplicidade irei adotar o mesmo padrao do MSN, Twitter e outros, ou seja,<br />             * no canto inferior direito da tela<br />             *<br />             * Define o X, para isso pega-se o tamanho total da tela - o tamanho do nosso alerta - um gap qualquer.<br />             * Define o Y, para isso pega-se a (altura total da tela - um gap qualquer) - (a altura do nosso alerta * total de alerta visiveis na tela)  */<br />            this.x = Application.application.width - this.width - 5;<br />            this.y = (Application.application.height - 5) - (this.height * GerenciadorAlerta.getInstance().totalAlertaVisivel);<br /><br />            /* Configurando os efeitos de MOVE. */<br />            this.mvExibirAlerta.yFrom = Application.application.height;<br />            this.mvExibirAlerta.yTo = y;<br /><br />            this.mvOcultarAlerta.yTo = Application.application.height;<br /><br />            /* Configurando o eventos do MOUSE<br />             *<br />             * Apos o alerta ser exibido o mesmo ficará visivel apenas por um determinado tempo.<br />             * Desta maneira caso o demore para ler a msg o alerta será ocultado, para que isso nao aconteça<br />             * iremos definir que quando o usuario colocar o mouse em cima o alerta o mesmo fica disponivel ate<br />             * que o usuario retire o mouse de cima do alerta. */<br />            this.addEventListener(MouseEvent.ROLL_OVER, function():void {<br />                _timerOcultarAlerta.removeEventListener(TimerEvent.TIMER_COMPLETE, fecharAlerta);<br />            });<br /><br />            this.addEventListener(MouseEvent.ROLL_OUT, function():void {<br />                fecharAlerta(null);<br />            });<br /><br />            /* Configurando o Tempo 'Timer' no qual o alerta ficará disponivel antes de ser ocultado */<br />            _timerOcultarAlerta = new Timer(_duracao, 1);<br />            _timerOcultarAlerta.addEventListener(TimerEvent.TIMER_COMPLETE, fecharAlerta);<br />            _timerOcultarAlerta.start();<br /><br />            /* Ao sair deste metodo o efeito Parallel que nos deixamos como Bindable no creationCompleteEffect da Tela<br />             * será ativado */<br />        }<br /><br />        /**<br />         * @private<br />         * Remove o alerta da Tela.<br />         * Neste momento o efeito Parallel que nos deixamos como Bindable no removedEffect da Tela<br />         * será ativado<br />         * @param evt<br />         */<br />        private function fecharAlerta(evt:TimerEvent):void{<br />            PopUpManager.removePopUp( this );<br /><br />            /* Avisa o gerenciador que foi removido um Alerta */<br />            GerenciadorAlerta.getInstance().alertaRemovido();<br />        }<br /><br />        /**<br />         * Responsavel por criar, configurar e exibir o Alerta tendo como base os argumentos como referencia.<br />         *<br />         * @param titulo Define o titulo a ser exibido no componente<br />         * @param conteudo Define o conteudo do alerta<br />         * @param tipoAlerta Define o style do alerta<br />         * @param duracao Define a duracao em segundos que o alerta ficará visivel para o usuario. Padra 3000 '3s'<br />         * @param icone Define um icone para ser exibido no alerta<br />         * @return a instancia do alerta criado e exibido;<br />         */<br />        public static function show(titulo:String, conteudo:String, tipoAlerta:int = 0, duracao:int = 3000, icone:String = null):Alerta {<br />            var alerta:Alerta = new Alerta();<br />            alerta._titulo = titulo;<br />            alerta._conteudo = conteudo;<br />            alerta._icone = icone;<br />            alerta._duracao = duracao;<br /><br />            /* Define o Style do Alerta pelo tipo.<br />             * O padrao será sempre o fundoAlertaSucesso */          <br />            if(tipoAlerta == ALERTA_ERRO)<br />                alerta.setStyle('styleName', 'fundoAlertaErro');<br /><br />            /* Exibe o alerta na tela */<br />            PopUpManager.addPopUp(alerta, DisplayObject(Application.application), false);<br /><br />            /* Avisa o gerenciador que foi criado um novo alerta */<br />            GerenciadorAlerta.getInstance().alertaCriado();<br /><br />            return alerta;<br />        }<br />    }<br />}

Passo 4

Criando o Gerenciador de Alertas. Ele tem a finalidade de armazenar todos os alertas que estão sendo exibidos no momento. Isso deve ser feito para que quando o método onCreate for configurar os eventos, ele calcule exatamente a posição onde o novo alerta será exibido. O gerenciador será um Singletom para estas informações estarem visíveis e únicas para toda a aplicação.

Segue o código GerenciadorAlerta.as

<br />package com.fabielprestes.views.impl {<br /><br />    /**<br />     * Classe responsavel por gerenciar os alertas que estao visiveis ao usuario.<br />     * Esta classe será um Singleton.<br />     *<br />     * @author Fabiel Prestes<br />     */<br />    public class GerenciadorAlerta {<br /><br />        private static var _instance:GerenciadorAlerta;<br /><br />        private var _totalAlertaVisivel:int = 0;<br /><br />        private var _totalAlertaVisivelAux:int = 0;<br /><br />        public function GerenciadorAlerta(type:PrivateGerenciadorAlerta) {<br />            if (type == null) {<br />                throw new Error("Erro: Não é possivel instancia GerenciadorAlerta, já que este é um Singleton.");<br />            }<br />        }<br /><br />        /**<br />         * Retorna a instancia unica da classe GerenciadorAlerta<br />         */<br />        public static function getInstance():GerenciadorAlerta {<br />            if (_instance == null)<br />                _instance = new GerenciadorAlerta(new PrivateGerenciadorAlerta());<br />            return _instance;<br />        }<br /><br />        public function alertaCriado():void {<br />            _totalAlertaVisivel++;<br />            _totalAlertaVisivelAux++;<br />        }<br /><br />        public function alertaRemovido():void {<br />            _totalAlertaVisivel--;<br /><br />            if(_totalAlertaVisivel <= 0)<br />                _totalAlertaVisivelAux = 0;<br />        }<br /><br />        /**<br />         * Retorna o total de alerta que esta visivel para o usuario na tela<br />         */<br />        public function get totalAlertaVisivel():int {<br />            return _totalAlertaVisivelAux;<br />        }<br />    }<br />}<br /><br />internal class PrivateGerenciadorAlerta {<br />    public function PrivateGerenciadorAlerta() {<br />    }<br />}

Passo 5

É o último. Criaremos uma classe teste que vai exibir quatro tipos de alerta: de sucesso com e sem imagem, e de erro com e sem imagem.

<?xml version="1.0" encoding="utf-8"?><br /><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"><br />    <mx:Script><br />        <![CDATA[<br />            import com.fabielprestes.views.impl.Alerta;<br /><br />        ]]><br />    </mx:Script><br /><br />    <mx:Button click="Alerta.show('Teste Sucesso', 'Conteudo teste')" label="Alerta Sucesso"/><br />    <mx:Button click="Alerta.show('Teste Sucesso', 'Conteudo teste', Alerta.ALERTA_SUCESSO, 3000, 'assets/user.gif')" label="Alerta Sucesso Com Imagem"/><br />    <mx:Button click="Alerta.show('Teste Erro', 'Conteudo teste', Alerta.ALERTA_ERRO)" label="Alerta Erro"/><br />    <mx:Button click="Alerta.show('Teste Erro', 'Conteudo teste', Alerta.ALERTA_ERRO, 3000, 'assets/user.gif')" label="Alerta Erro Com Imagem"/><br /></mx:Application>

É isso aí, pessoal! Uma maneira simples e fácil de se criar alertas. Agora é só você customizar da melhor maneira. Este componente é bem parecido com o Notification e Gragle.

Qualquer dúvida ou sugestão, é só deixar nos comentários ou mandar um email.

Arquivos

trabalha a desde 2005 em desenvolvimento e integração de sistemas WEB JEE. Começou a trabalhar com desenvolvimento de aplicações RIA Flex/Air em 2007. Atualmente é analista de sistemas pela JExperts, participa de fóruns e listas de discussões como Anddev, Adroid.org, GUJ, FlexDev, FloripaFlex e PortalAndroid.

Ver perfil