Desenvolvimento

7 out, 2009

Criando um alerta de mensagens

Publicidade

É 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"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="200" height="100"
styleName="fundoAlertaSucesso" paddingBottom="5" paddingLeft="5" paddingTop="5" paddingRight="5"
verticalScrollPolicy="off" horizontalScrollPolicy="off"
creationCompleteEffect="{createEffect}" removedEffect="{removeEffect}">

<mx:Style>
.fundoAlertaSucesso{
borderStyle: applicationControlBar;
fill-colors: #03A438, #6FCE8F;
fillAlphas: 1, 1;
highlightAlphas: 0, 0;
drop-shadow-enabled: true;
corner-radius: 5;
}

.fundoAlertaErro{
borderStyle: applicationControlBar;
fill-colors: #E43434, #FCA5A5;
fillAlphas: 1, 1;
highlightAlphas: 0, 0;
drop-shadow-enabled: true;
corner-radius: 5;
}
</mx:Style>

<mx:Script>
<![CDATA[
[Bindable]
protected var _titulo:String;

[Bindable]
protected var _conteudo:String;

[Bindable]
protected var _icone:String;
]]>
</mx:Script>

<!-- Criando e configurando os efeitos -->
<mx:Parallel id="createEffect" duration="700">
<mx:Move id="mvExibirAlerta"/>
<mx:Fade/>
</mx:Parallel>

<mx:Parallel id="removeEffect" duration="700">
<mx:Move id="mvOcultarAlerta"/>
<mx:Fade/>
</mx:Parallel>

<mx:Label id="lbTitulo" width="100%" text="{_titulo}" fontFamily="Courier New" fontSize="14"
fontWeight="bold" color="#FFFFFF" left="5" top="5"/>

<mx:Text id="tConteudo" htmlText="{_conteudo}" fontFamily="Courier New" fontSize="12" left="5"
top="30" right="5" bottom="5"/>

<mx:Image width="20" height="20" right="5" top="5" id="imgIcon" source="{_icone}" visible="{_icone != null}"/>

</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 {
import com.fabielprestes.views.AlertaUI;

import flash.display.DisplayObject;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;

import mx.core.Application;
import mx.events.FlexEvent;
import mx.managers.PopUpManager;


/**
* Responsavel por exibir e controlar o componente de alerta na tela.
*
* @author Fabiel Prestes
*/
public class Alerta extends AlertaUI {

private var _novaAltura:int;

private var _duracao:int = 3000;

private var _timerOcultarAlerta:Timer;

public static var ALERTA_SUCESSO:int = 0;
public static var ALERTA_ERRO:int = 1;

public function Alerta() {
super();

this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreate);
}

/**
* @private
* Espera o alerta ser totalmente criado para seguir o fluxo de configuraçao de posicionamento.
* @param evt
*/
private function onCreate(evt:FlexEvent):void {

/* Definindo o local onde o alerta será exibido,
* Por simplicidade irei adotar o mesmo padrao do MSN, Twitter e outros, ou seja,
* no canto inferior direito da tela
*
* Define o X, para isso pega-se o tamanho total da tela - o tamanho do nosso alerta - um gap qualquer.
* 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) */
this.x = Application.application.width - this.width - 5;
this.y = (Application.application.height - 5) - (this.height * GerenciadorAlerta.getInstance().totalAlertaVisivel);

/* Configurando os efeitos de MOVE. */
this.mvExibirAlerta.yFrom = Application.application.height;
this.mvExibirAlerta.yTo = y;

this.mvOcultarAlerta.yTo = Application.application.height;

/* Configurando o eventos do MOUSE
*
* Apos o alerta ser exibido o mesmo ficará visivel apenas por um determinado tempo.
* Desta maneira caso o demore para ler a msg o alerta será ocultado, para que isso nao aconteça
* iremos definir que quando o usuario colocar o mouse em cima o alerta o mesmo fica disponivel ate
* que o usuario retire o mouse de cima do alerta. */
this.addEventListener(MouseEvent.ROLL_OVER, function():void {
_timerOcultarAlerta.removeEventListener(TimerEvent.TIMER_COMPLETE, fecharAlerta);
});

this.addEventListener(MouseEvent.ROLL_OUT, function():void {
fecharAlerta(null);
});

/* Configurando o Tempo 'Timer' no qual o alerta ficará disponivel antes de ser ocultado */
_timerOcultarAlerta = new Timer(_duracao, 1);
_timerOcultarAlerta.addEventListener(TimerEvent.TIMER_COMPLETE, fecharAlerta);
_timerOcultarAlerta.start();

/* Ao sair deste metodo o efeito Parallel que nos deixamos como Bindable no creationCompleteEffect da Tela
* será ativado */
}

/**
* @private
* Remove o alerta da Tela.
* Neste momento o efeito Parallel que nos deixamos como Bindable no removedEffect da Tela
* será ativado
* @param evt
*/
private function fecharAlerta(evt:TimerEvent):void{
PopUpManager.removePopUp( this );

/* Avisa o gerenciador que foi removido um Alerta */
GerenciadorAlerta.getInstance().alertaRemovido();
}

/**
* Responsavel por criar, configurar e exibir o Alerta tendo como base os argumentos como referencia.
*
* @param titulo Define o titulo a ser exibido no componente
* @param conteudo Define o conteudo do alerta
* @param tipoAlerta Define o style do alerta
* @param duracao Define a duracao em segundos que o alerta ficará visivel para o usuario. Padra 3000 '3s'
* @param icone Define um icone para ser exibido no alerta
* @return a instancia do alerta criado e exibido;
*/
public static function show(titulo:String, conteudo:String, tipoAlerta:int = 0, duracao:int = 3000, icone:String = null):Alerta {
var alerta:Alerta = new Alerta();
alerta._titulo = titulo;
alerta._conteudo = conteudo;
alerta._icone = icone;
alerta._duracao = duracao;

/* Define o Style do Alerta pelo tipo.
* O padrao será sempre o fundoAlertaSucesso */
if(tipoAlerta == ALERTA_ERRO)
alerta.setStyle('styleName', 'fundoAlertaErro');

/* Exibe o alerta na tela */
PopUpManager.addPopUp(alerta, DisplayObject(Application.application), false);

/* Avisa o gerenciador que foi criado um novo alerta */
GerenciadorAlerta.getInstance().alertaCriado();

return alerta;
}
}
}

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


package com.fabielprestes.views.impl {

/**
* Classe responsavel por gerenciar os alertas que estao visiveis ao usuario.
* Esta classe será um Singleton.
*
* @author Fabiel Prestes
*/
public class GerenciadorAlerta {

private static var _instance:GerenciadorAlerta;

private var _totalAlertaVisivel:int = 0;

private var _totalAlertaVisivelAux:int = 0;

public function GerenciadorAlerta(type:PrivateGerenciadorAlerta) {
if (type == null) {
throw new Error("Erro: Não é possivel instancia GerenciadorAlerta, já que este é um Singleton.");
}
}

/**
* Retorna a instancia unica da classe GerenciadorAlerta
*/
public static function getInstance():GerenciadorAlerta {
if (_instance == null)
_instance = new GerenciadorAlerta(new PrivateGerenciadorAlerta());
return _instance;
}

public function alertaCriado():void {
_totalAlertaVisivel++;
_totalAlertaVisivelAux++;
}

public function alertaRemovido():void {
_totalAlertaVisivel--;

if(_totalAlertaVisivel <= 0)
_totalAlertaVisivelAux = 0;
}

/**
* Retorna o total de alerta que esta visivel para o usuario na tela
*/
public function get totalAlertaVisivel():int {
return _totalAlertaVisivelAux;
}
}
}

internal class PrivateGerenciadorAlerta {
public function PrivateGerenciadorAlerta() {
}
}

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"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal">
<mx:Script>
<![CDATA[
import com.fabielprestes.views.impl.Alerta;

]]>
</mx:Script>

<mx:Button click="Alerta.show('Teste Sucesso', 'Conteudo teste')" label="Alerta Sucesso"/>
<mx:Button click="Alerta.show('Teste Sucesso', 'Conteudo teste', Alerta.ALERTA_SUCESSO, 3000, 'assets/user.gif')" label="Alerta Sucesso Com Imagem"/>
<mx:Button click="Alerta.show('Teste Erro', 'Conteudo teste', Alerta.ALERTA_ERRO)" label="Alerta Erro"/>
<mx:Button click="Alerta.show('Teste Erro', 'Conteudo teste', Alerta.ALERTA_ERRO, 3000, 'assets/user.gif')" label="Alerta Erro Com Imagem"/>
</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