* Artigo do site iConnect.
Neste novo artigo irei demonstrar como criar um componente de paginação. Sabemos que em grande parte dos projetos é necessário amostrar diversos tipos de informação seguindo os padrões de Master Detail (Grid, List, etc.). Para este tipo de amostragem de dados, a paginação é um componente super importante, pois previne alguns problemas básicos, como:
- Problemas de performance na busca e listagem dos dados.
- Problemas de usabilidade com relação ao scroll vertical que é criado devido ao montante de dados.
A criação deste componente será dividida em dois artigos, sendo este o primeiro da série. Assim, neste primeiro desenvolveremos um componente que irá apenas paginar um montante de dados estáticos armazenados em um ArrayCollection, ou seja, criaremos toda a lógica para percorrer a lista e paginá-la em um componente do tipo lista (DataGrid, List, etc).
Já na segunda parte, faremos com que o servidor fique responsável pela tarefa de buscar e calcular o total de dados referentes à pesquisa. Desta maneira, nosso componente ficará responsável apenas por enviar qual a quantidade de dados a ser retornada e qual a faixa em que se encontra a sequência.
O principal motivo deste artigo estar dividido em duas partes é fazer com que o desenvolvedor entenda o funcionamento interno da paginação de dados, possibilitando a realização de melhorias durante a utilização do server-side se necessário.
Requisitos:
- Ter Flex/Flash Builder ou outra IDE.
- Ter SDK 3 ou superior.
- Conhecimento em ActionScript e Mxml.
Nivel de dificuldade: 7.5
Agora vamos ao que interessa.
Passo 1
Iremos criar um componente customizado que estenda o Button, este será responsável por referenciar e exibir os dados referentes a uma página. Este componente é muito simples, o que realmente devemos observar são os seguintes pontos:
- Propriedade "pagina", a qual indica qual pagina será exibida.
- Propriedade "intervaloInicial", indica qual o ponto inicial em que teremos que buscar os dados da coleção.
- Evento "clickHandler", realizaremos um override neste método para que seja disparado um evento personalizado que avisará nosso componente principal que o usuário deseja ir para a página x.
Segue o código:
package com.imaster.impl {
import com.imaster.event.PaginacaoEvent;
import flash.events.MouseEvent;
import mx.controls.Button;
/**
*
* @author Fabiel Prestes
*
*/
[Event(name="exibirPagina", type="com.imaster.event.PaginacaoEvent")]
public class BotaoPagina extends Button {
[Bindable]
private var _pagina:int;
[Bindable]
private var _intervaloInicial:int;
private var _evtPaginacao:PaginacaoEvent;
public function BotaoPagina() {
super();
}
override protected function childrenCreated():void{
super.childrenCreated();
this.buttonMode = true;
this.useHandCursor = true;
/* Define a label do botao com o mesmo numero de pagina */
if(this.label == '')
this.label = String(_pagina);
}
/**
* Define a pagina a qual este botao deve amostrar os dados para o usuario.
* @param int Numero da pagina
*/
public function set pagina(value:int):void {
_pagina = value;
}
/**
* Retorna o numero da pagina na qual este botao deve amostrar os dados.
* @return
*/
public function get pagina():int {
return _pagina;
}
/**
* Define o intervalo Inicial que deverá ser amostrado na noav listagem
* @param int Numero da pagina
*/
public function set intervaloInicial(value:int):void {
_intervaloInicial = value;
}
/**
* @return
*/
public function get intervaloInicial():int {
return _intervaloInicial;
}
override protected function clickHandler(event:MouseEvent):void {
super.clickHandler(event);
if(this.selected){
_evtPaginacao = new PaginacaoEvent(PaginacaoEvent.EXIBIR_PAGINA);
_evtPaginacao.botaoPagina = this;
this.dispatchEvent(_evtPaginacao);
}
}
}
}
Passo 2
Agora, com o componente BotaoPagina criado, iremos desenvolver nosso evento personalizado, que irá delegar e orquestrar as requisições feitas entre o BotaoPagina e nosso componente principal.
package com.imaster.event {
import com.imaster.impl.BotaoPagina;
import flash.events.Event;
/**
*
* @author Fabiel Prestes
*
*/
public class PaginacaoEvent extends Event {
public static const EXIBIR_PAGINA:String = "exibirPagina";
public var botaoPagina:BotaoPagina;
public function PaginacaoEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false) {
super(type, bubbles, cancelable);
}
}
}
Passo 3
Abaixo está o código mxml que será a capa do componente de paginação principal, neste teremos os seguintes componentes:
- Dois Buttons: um será responsável por avançar e outro para retroceder uma página, sempre baseados na página atual.
- Um HBox, este container será responsável por armazenar e identar o componente BotaoPagina.
- Por último um ComboBox, que irá definir os intervalos de dados que cada página deverá amostrar.
Segue o código abaixo
[ExcludeClass]
Passo 4
Agora daremos início à criação do componente que orquestrará toda a tarefa de manipulação da paginação. Este componente é bem simples, contudo requer atenção em alguns pontos, já que nesta primeira parte do artigo iremos criar toda a lógica de paginação e, no próximo artigo, será de responsabilidade do server-side.
Métodos principais:
- childrenCreated: Iremos realizar um override para adicionar todos os listener necessários, quando todos os componentes da tela forem criados, para os botões de avançar e retroceder e para o ComboBox de retroceder.
- invalidateProperties: Iremos realizar um override para as propridedades quando o commitProperties for chamada.
- configurarBotoesPagina: Este é um dos principais métodos, já que é responsável por calcular a quantidade de páginas necessárias, baseado no montante de dados, e depois criar os BotesPagina e adicioná-los no container.
- configurarListaNaPagina: Método chamado sempre que uma nova página for requisitada. Assim o método recupera a página selecionada e qual intervalo foi selecionado pelo usuário para, assim, realizar a coleta dos dados na coleção.
Há outros métodos na classe, contudo os citados acima são os mais importantes, deixei todo o código comentado, assim ficará mais fácil tirar as dúvidas.
Segue o código:
package com.imaster.impl {
import com.imaster.PaginacaoUI;
import com.imaster.event.PaginacaoEvent;
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.controls.listClasses.ListBase;
import mx.events.ListEvent;
/**
*
* @author Fabiel
*
*/
public class Paginacao extends PaginacaoUI {
[Bindable]
private var _totalPorPagina:int = 5;
[Bindable]
private var _totalDados:int;
[Bindable]
private var _listaBase:ArrayCollection;
[Bindable]
private var _listaBaseAux:ArrayCollection;
private var _bpAux:BotaoPagina;
private var _bpAtual:BotaoPagina;
private var _listaAlvo:ListBase;
private var _botoesPagina:Array = [];
private var totalBotoes:int;
public function Paginacao() {
super();
}
override protected function childrenCreated():void{
super.childrenCreated();
/* Adicionando os Listeners */
this.bpPaginaAnterior.addEventListener(MouseEvent.CLICK, trateExibirPaginaAnterior, false, 0, true);
this.bpProximaPagina.addEventListener(MouseEvent.CLICK, trateExibirProximaPagina, false, 0, true);
this.cbIntevalo.addEventListener(ListEvent.CHANGE, trateTrocaIntervalo, false, 0, true);
}
override public function invalidateProperties():void{
super.invalidateProperties();
/* Inicializa a configuração da paginação */
configurarBotoesPagina();
}
/**
* @private
* Fica escutando quando o usuario trocou o total de interva de dados a ser amostrado na lista
* @param evt
*/
private function trateTrocaIntervalo(evt:ListEvent):void{
_totalPorPagina = cbIntevalo.selectedItem.value;
/* Inicializa a configuração da paginação */
configurarBotoesPagina();
}
/**
* @private
* Responsavel por configurar os botoes de paginação na tela.
*/
private function configurarBotoesPagina():void{
/* Calcula a quantidade de botoes que deverao ser criados baseado no total de dados e total de dados por pagina */
totalBotoes = Math.ceil(totalDados/totalPorPagina);
/* Se houver BotoesPagina ja configurado no container, deve-se removelos para
* recalcular o total de paginas */
if(containerBpIntermadiarios != null && containerBpIntermadiarios.getChildren() != null){
containerBpIntermadiarios.removeAllChildren();
_botoesPagina = [];
}
/* Realiza um loop criando os botoes */
for(var i:int = 1; i <= totalBotoes; i++){
/* Cria e configura o BotaoPagina */
_bpAux = new BotaoPagina();
_bpAux.toggle = true;
_bpAux.pagina = i;
_bpAux.intervaloInicial = (i - 1) * _totalPorPagina;
_bpAux.addEventListener(PaginacaoEvent.EXIBIR_PAGINA, trateExibirPagina);
_botoesPagina[i] = _bpAux;
/* Se for o primeiro BotaoPagina criado deve-se configurar a lista de dados na componente tipo ListBase */
if(i == 1){
_bpAux.selected = true;
_bpAtual = _bpAux;
configurarListaNaPagina(_bpAux);
}
/* Adiciona os botoes no container */
containerBpIntermadiarios.addChild(_bpAux);
}
}
/**
* @private
* Configura e renderiza os dados Base para ser amostrado na tela levendo-se em consideração
* o intervalo passado.
* @param intervloIncial
*
*/
private function configurarListaNaPagina(bpAtual:BotaoPagina):void{
_listaBaseAux = new ArrayCollection();
/* para cada Loop é copiado o objeto que se encontra no intervalo passado como parametro */
for(var j:int = 0; j < _totalPorPagina; j++){
if(bpAtual.intervaloInicial + j < _totalDados)
_listaBaseAux.addItem(_listaBase.getItemAt(bpAtual.intervaloInicial + j));
}
/* Configurando os botoes de avançar e retornar */
if(bpAtual.pagina > 1){
configBpPaginaAnterior();
} else {
configBpPaginaAnterior(false);
}
if(bpAtual.pagina == totalBotoes){
configBpProximaPagina(false);
} else {
configBpProximaPagina();
}
/* Define o provider clonado e define na ListBase */
this._listaAlvo.dataProvider = _listaBaseAux;
}
/**
* @private
* Responsavel por ficar escutando quando o usuario deseja visualizar o conteudo de cada pagina
*/
private function trateExibirPagina(evt:PaginacaoEvent):void{
_bpAtual.selected = false;
_bpAtual = evt.botaoPagina;
configurarListaNaPagina(_bpAtual);
}
/**
* @private
* Responsavel por exibir os dados da paragina anterior.
*/
private function trateExibirPaginaAnterior(evt:MouseEvent):void{
/* Verifica qual a pagina em que esta para pegar a anterior */
var i:int = (_bpAtual.pagina >= 1) ? _bpAtual.pagina - 1 : 0;
_bpAtual.selected = false;
_bpAtual = _botoesPagina[i];
_bpAtual.selected = true;
configurarListaNaPagina(_bpAtual);
}
/**
* @private
* Responsavel por amostrar os dados da proxima pagina
*/
private function trateExibirProximaPagina(evt:MouseEvent):void{
/* Verifica qual a pagina em que esta para pegar a proxima */
var i:int = (_bpAtual.pagina < (_botoesPagina.length - 1)) ? _bpAtual.pagina + 1 : _botoesPagina.length;
if(i < _botoesPagina.length){
/* Desmarca o botao atual */
_bpAtual.selected = false;
/* Recupera o proximo botao e marca o mesmo */
_bpAtual = _botoesPagina[i];
_bpAtual.selected = true;
/* Configura a lista na pagina */
configurarListaNaPagina(_bpAtual);
}
}
/**
* Define o total de dados que serão amostrados em cada pagina
* @param value
*
*/
public function set totalPorPagina(value:int):void{
_totalPorPagina = value;
}
/**
* Retorna o numero de dados que esta/serão amostrados na tela.
* @return
*/
public function get totalPorPagina():int{
return _totalPorPagina;
}
/**
* Define o total de dados que serão amostrados em cada pagina
* @param value
*
*/
public function set totalDados(value:int):void{
_totalDados = value;
}
/**
* Retorna o numero de dados que esta/serão amostrados na tela.
* @return
*/
public function get totalDados():int{
return _totalDados;
}
public function set listaAlvo(value:ListBase):void{
_listaAlvo = value;
}
public function get listaAlvo():ListBase{
return _listaAlvo;
}
/**
* Define a lista que será utilizada para exibir na paginacao
* @param value
*
*/
public function set listaBase(value:ArrayCollection):void{
_listaBase = value;
if(_listaBase){
_totalDados = _listaBase.length;
}
}
public function get listaBase():ArrayCollection{
return _listaBase;
}
private function configBpPaginaAnterior(value:Boolean = true):void {
this.bpPaginaAnterior.enabled = value;
}
private function configBpProximaPagina(value:Boolean = true):void {
this.bpProximaPagina.enabled = value;
}
}
}
Fonte: iMasters
0 comentários:
Postar um comentário