Centralizar uma janela PopUp na aplicação Adobe Flex

Centralizar uma Janela com Popup em Flex

 

 

 

 

 

 

 

 

 

 

 

Um recurso muito utilizado nas aplicações Flex são as janelas do estilo PopUp, que são aquelas que abrem sobre sua aplicação, podendo inclusive serem movidas pelo usuário. Normalmente quando abrimos uma nova janela desse tipo queremos que a mesma apareça exatamente no centro da tela, ou seja, da aplicação.

Para isso utilizamos o seguinte código:

PopUpManager.addPopUp(myPopUp, this, true);
PopUpManager.centerPopUp(myPopUp);

Normalmente utilizamos estes três parâmetros:

window: Nossa janela que desejamos exibir
parent: Componente pai que será utilizado como referência para posicionar a nova janela
modal: Variável booleana que define se nossa janela será do tipo Modal (se irá inibir o restante da aplicação).

O método centerPopUp, como o próprio nome diz, é utilizado para centralizar a janela sobre o componente pai. Aqui começa nosso problema. Quando o “parent” é nosso Application, tudo fica perfeito, pois nossa janela ficará exatamente no centro da aplicação do usuário. Entretanto se estamos executando nosso código, a partir de um sub-componente, por exemplo um que esteja na parte de baixo da aplicação, nossa janela popup será centralizada sobre sobre este componente.

Para corrigir isso, utilizamos o seguinte código:

PopUpManager.addPopUp(concessionaria,
                      DisplayObject(this.parentApplication),true);
PopUpManager.centerPopUp(concessionaria);

Desta forma estaremos dizendo ao PopUpManager que o componente pai da nossa aplicação será nosso Application, fazendo com que nossas janelas PopUp sempre sejam centralizadas sobre nossa aplicação.

Que tal, ótima dica não? Abs!

 

Alerta PopUp deslizante em Adobe Flex

Para quem assim como eu se preocupa muito com a experiência do usuário no desenvolvimento de sistemas sabe como as janelas PopUp saltitantes que insistem em congelar a aplicação são desesperadoras. E se você tem essas mensagens programadas também para as falhas do sistema, tem que tratar muito bem as Exceptions para não encher a aplicação de mensagens do tipo modal e fazer o usuário ficar minutos e mais minutos clicando em ok.

Quando comecei a utilizar o twitter percebi algo diferente. As mensagens de confirmação de ações da área de configuração aparecem sempre no topo do browser, deslizando suavente da parte de cima e exibindo a mensagem, o que me pareceu muito interessante. Este tipo de mensagem não faz com que você tenha que clicar outra vez em um botão (normalmente OK), sendo que você já sabe que sua ação foi bem sucedida. Isso economiza tempo do usuário e causa um efeito mais clean e profissional no sistema.

A partir disso adotei essa técnica nos novos desenvolvimentos e vou compartilhar de forma geral como utilizo.

A mensagem é um componente baseado em um Canvas com uma imagem do lado esquerdo e um Label, onde será exibida a mensagem, sendo que o conteúdo será armazenado em uma variável de classe do tipo String.

<mx:Image id="imgAlert" source="imagens/ok.png" verticalCenter="0" left="10"/>
<mx:Label text="{mensagem}" left="98" verticalCenter="0" right="10" fontSize="16"/>

Também criei uma pasta com as imagens que utilizo para cada tipo de mensagem: Erro, Ajuda, Informativo, Ok, Alerta. De acordo com o tipo de mensagem será exibido a respectiva imagem.

No componente também foi criado um Timer, responsável por fazer com que a mensagem “feche”. Basicamente o efeito funciona da seguinte forma: O compomente inicialmente é criado com height igual a 0. Ao executar a mensagem, a altura do componente é setada por exemplo para 100 pixels e é iniciado o Timer. Ao final da contagem, novamente o tamanho do componente é setado para 0.

private var timer:Timer;

private function init():void
{
   this.height = 0;
   timer = new Timer(3000);
   timer.addEventListener(TimerEvent.TIMER, timerComplete);
}

private function timerComplete(event:TimerEvent):void
{
   this.height = 0;
   timer.stop();
}

Para executar o alerta criei o seguinte método:

private var HEIGHT:int = 100;

public function show(tipo:String, mensagem:String):void
{
   this.height = HEIGHT;
   timer.start();
   this.mensagem = mensagem;
   if (tipo==ERROR) {
      imgAlert.source = "imagens/error.png";
   } else if (tipo==HELP) {
      imgAlert.source = "imagens/help.png";
   } else if (tipo==INFO) {
      imgAlert.source = "imagens/info.png";
   } else if (tipo==OK) {
      imgAlert.source = "imagens/ok.png";
   } else if (tipo==WARNING) {
      imgAlert.source = "imagens/warning.png";
   }
}

Dessa forma ao executar o método show() o tamanho do componente será setado para 100 pixels, executando o efeito de transição de cima para baixo e será iniciado a contagem do timer e de acordo com o tipo de mensagem informado no parâmetro “tipo”, será exibido um ícone diferente.

Para não ter que escrever sempre a string do tipo de mensagem, criei variáveis de classe do tipo static.

public static const ERROR:String = "error";
public static const HELP:String = "help";
public static const INFO:String = "info";
public static const OK:String = "ok";
public static const WARNING:String = "warning";

Para completar o componente, o tipo de efeito foi definido nos parâmetros do Canvas. É utilizado um efeito simples do tipo Resize.

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas
   xmlns:mx="http://www.adobe.com/2006/mxml"
   width="100%" height="{HEIGHT}"
   backgroundColor="#E0EBF1"
   initialize="init()"
   resizeEffect="Resize">

Para utilizar o componente, crio uma variável de classe no Application, que chamarei de toda parte do sistema e no init defino onde deverá ficar o componente de alerta, ancorado na parte superior e nas laterais do Application.

public static var alert:MeuAlerta;

private function init():void {
   alert = new MeuAlerta();
   alert.setStyle("top",0);
   alert.setStyle("left",0);
   alert.setStyle("rigth",0);
   addChild(alert);
}

Defini a variável do tipo static para não ter que sempre fazer referência ao Application.application, dessa forma pose-se executar realizando referência a classe principal (Application) que no meu projeto se chama AlertaDeslizante, e a variável alert.

AlertaDeslizante.alert.show(MeuAlerta.OK, "Texto da mensagem");

O primeiro parâmetro é o tipo de mensagem, passado através das variáveis estáticas do componente MeuAlerta, e o segundo parâmetro a string da mensagem. Dessa forma essa chamada pode ser executada de qualquer parte da aplicação.

Segue código completo do componente MeuAlerta:

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas
xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="{HEIGHT}"
backgroundColor="#E0EBF1"
initialize="init()"
resizeEffect="Resize">

<mx:Script>
<![CDATA[

private var HEIGHT:int = 100;
[Bindable]
private var mensagem:String;

public static const ERROR:String = "error";
public static const HELP:String = "help";
public static const INFO:String = "info";
public static const OK:String = "ok";
public static const WARNING:String = "warning";

private var timer:Timer;

private function init():void
{
this.height = 0;
timer = new Timer(3000);
timer.addEventListener(TimerEvent.TIMER, timerComplete);
}

public function show(tipo:String, mensagem:String):void
{
this.height = HEIGHT;
timer.start();
this.mensagem = mensagem;
if (tipo==ERROR) {
imgAlert.source = "imagens/error.png";
} else if (tipo==HELP) {
imgAlert.source = "imagens/help.png";
} else if (tipo==INFO) {
imgAlert.source = "imagens/info.png";
} else if (tipo==OK) {
imgAlert.source = "imagens/ok.png";
} else if (tipo==WARNING) {
imgAlert.source = "imagens/warning.png";
}
}

private function timerComplete(event:TimerEvent):void
{
this.height = 0;
timer.stop();
}
]]>
</mx:Script>

<mx:Image id="imgAlert" source="imagens/ok.png" verticalCenter="0" left="10"/>
<mx:Label text="{mensagem}" left="98" verticalCenter="0" right="10" fontSize="16"/>

</mx:Canvas>

E aqui podem ver o resultado final:

Espero que esta dica seja útil e fiquem abertos a contribuir com melhorias!