componentes de interface gráfica avançados

31
Capítulo 5: Componentes de UI Avançados Transições Animadas A partir da versão 5.0 da JDE do BlackBerry, ou seja, a partir da versão 5.0 do sistema operacional dos smartphones da canadense RIM, o desenvolvedor consegue criar transições animadas entre telas. Isso até é possível nas versões anteriores a 5.0, porém, o desenvolvedor precisa criar um extenso código para simular um componente deste porte. O exemplo que vamos criar aqui foi baseado no artigo Creating a screen transition, disponível no endereço http://docs.blackberry.com/en/developers/deliverab les/17971/Screen_transitions_detailed_overview_806 391_11.jsp . O aplicativo é muito simples, ele mostra basicamente duas telas, que terão uma transição animada quando acontece troca entre elas. Veja as Figuras com as duas telas da aplicação:

Upload: ricardo-ogliari

Post on 31-Mar-2016

222 views

Category:

Documents


0 download

DESCRIPTION

Neste capítulo do Curso BlackBerry Development, aprenda como criar componentes de interface gráfica avançados com a BlackBerry API.

TRANSCRIPT

Page 1: Componentes de Interface Gráfica Avançados

Capítulo 5: Componentes de UI Avançados

Transições Animadas

A partir da versão 5.0 da JDE do BlackBerry, ou seja, a partir da versão 5.0 do sistema operacional dos smartphones da canadense RIM, o desenvolvedor consegue criar transições animadas entre telas. Isso até é possível nas versões anteriores a 5.0, porém, o desenvolvedor precisa criar um extenso código para simular um componente deste porte.

O exemplo que vamos criar aqui foi baseado no artigo Creating a screen transition, disponível no endereço http://docs.blackberry.com/en/developers/deliverables/17971/Screen_transitions_detailed_overview_806391_11.jsp.

O aplicativo é muito simples, ele mostra basicamente duas telas, que terão uma transição animada quando acontece troca entre elas.

Veja as Figuras com as duas telas da aplicação:

Figura 28: Primeira tela do aplicativo de transição animada.

Page 2: Componentes de Interface Gráfica Avançados

Figura 29: Segunda tela do aplicativo de transição animada.

Veja a listagem de código abaixo:

1: public class TransitionSample extends UiApplication implements FieldChangeListener {2: private Screen segundaTela;3: private Runnable _popRunnable;4: 5: public static void main(String[] args) {6: TransitionSample theApp = new ScreenTransitionSample ();7: theApp.enterEventDispatcher();8: }9:10: public TransitionSample () { 11: segundaTela = new FullScreen();12:

segundaTela.setBackground( BackgroundFactory.createSolidBackground(Color.LIGHTBLUE) );13: 14: LabelField labelField = new LabelField("Esta tela fecha automaticamente depois de 2 segundos.");

Page 3: Componentes de Interface Gráfica Avançados

15: segundaTela.add(labelField);16: 17: MainScreen baseScreen = new MainScreen();18: baseScreen.setTitle("Primeira Tela"); 19: 20: ButtonField buttonField = new ButtonField("Ver Transição", ButtonField.CONSUME_CLICK) ;21: buttonField.setChangeListener(this);22: baseScreen.add(buttonField);23: 24: pushScreen(baseScreen);25: 26: _popRunnable = new Runnable() { 27: public void run() {28: popScreen(segundaTela);29: }30: };31: }32: 33: public void fieldChanged(Field field, int context)34: {35: pushScreen(segundaTela);36: invokeLater(_popRunnable, 2000, false);37: }38: }

Logo na primeira linha estamos trabalhando com uma nova interface: FieldChangeListener. Por isso, devemos implementar obrigatoriamente o método fieldChanged(linha 33). Este método é chamado quando ocorre uma mudanda de tela no aplicativo.

O resto da codificação já deve ser bem familiar ao leitor. Porém, ao criar o componente ButtonField, percebemos que estamos passando como estilo a constante ButtonField.CONSUME_CLICK. Esta constante indica que o botão irá auto-consumir o evento de clique. Na linha seguinte, adicionamos o listener de mudança de tela ao botão, logo, quando clicarmos no mesmo, o método fieldChange será acionado.

Este método, por sua vez, irá mostrar a segunda tela ao usuário, além disso, invoca a Thread criada na linha 26, depois de 2 segundos. A _popRunnable apenas remove a segunda tela da pilha de Screen´s.

Finalizando, porque já estava esquecendo, nossa segunda tela tem um fundo totalmente azul, e nem usamos um Canvas para definir esta coloração como background. Veja a linha 2. Estamos usando a classe BackgroundFactory e seu método createSolidBackgournd para criar este efeito.

Porém, mesmo que o leitor testar este aplicativo vai perceber que a mudança de telas não trouxe nenhuma transição animada, fique calmo, vamos programar esta funcionalidade agora.

Page 4: Componentes de Interface Gráfica Avançados

O primeiro passo é a criação de uma instância da classe TransitionContext. Esta define todas as características de uma transição animada entre duas telas.

A tabela abaixo é de suma importância, porque mostra todas as opções de animação e as propriedades que cada uma delas pode ter:

Transição AtributosTransitionContext.TRANSITION_FADE TransitionContext.ATTR_DURATION e

TransitionContext.ATTR_KIND

.TRANSITION_SLIDE TransitionContext.ATTR_DURATION, TransitionContext.ATTR_KIND, TransitionContext.ATTR_DIRECTION e TransitionContext.ATTR_STYLE

.TRANSITION_WIPE TransitionContext.ATTR_DURATION, TransitionContext.ATTR_KIND e TransitionContext.ATTR_DIRECTION

.TRANSITION_ZOOM TransitionContext.ATTR_DURATION e TransitionContext.ATTR_KIND

.TRANSITION_NONE nenhum

Coloco as linhas de código abaixo no final do construtor da classe:

1:TransitionContext transition = new TransitionContext(TransitionContext.TRANSITION_SLIDE);2: transition.setIntAttribute(TransitionContext.ATTR_DURATION, 500);3: transition.setIntAttribute(TransitionContext.ATTR_DIRECTION, TransitionContext.DIRECTION_RIGHT);4: transition.setIntAttribute(TransitionContext.ATTR_STYLE, TransitionContext.STYLE_PUSH);

Na primeira linha criamos a instância de TransitionContext. Seu construtor aceita um único parâmetro, uma constante que define qual será o efeito de transição. Como escolhemos SLIDE podemos definir qualquer um de seus quatro parâmetros (veja a tabela novamente).

A definição das propriedades é feita com o método setIntAttribute ou setAttribute. A única diferença é que no primeiro o segundo parâmetro é um inteiro e no último, o segundo parâmetro é um Object.

Perceba que a definição das propriedades é muito simples, os dois parâmetros são bem legíveis. No primeiro definimos qual a propriedade e no segundo seu valor. Sempre usando as constantes da própria classe. Não tem erro.

Page 5: Componentes de Interface Gráfica Avançados

Mas ainda não é o bastante para animar nossa transição.Depois do código anterior adicione as duas linhas de código abaixo:

UiEngineInstance engine = Ui.getUiEngineInstance(); engine.setTransition(baseScreen, segundaTela, UiEngineInstance.TRIGGER_PUSH, transition);

O primeiro passo é criar uma instância de UiEngineInstance. Esta classe está presente desde a versão 4.7 do sistema operacional do BlackBerry. Porém, o método setTransition usado logo a seguir está presente só a partir da versão 5.0

Os quatro parâmetros são: Tela de origem; Tela de destino; Trigger: pode ser umas das duas constantes

UiEngineInstance.TRIGGER_PUSH ou UiEngineInstance.TRIGGER_POP;

Instância de TransitionContext.

Agora sim, teste novamente o aplicativo e verás que na mudança da primeira para a segunda tela a animação slide está presente.

Para completar nosso exemplo, adicone as linhas de código da listagem abaixo, elas farão com a transição da segunda para a primeira tela também seja animada:

transition = new TransitionContext(TransitionContext.TRANSITION_FADE);transition.setIntAttribute(TransitionContext.ATTR_DURATION, 500);transition.setIntAttribute(TransitionContext.ATTR_KIND, TransitionContext.KIND_OUT);engine.setTransition(segundaTela, null, UiEngineInstance.TRIGGER_POP, transition);

Para saber mais sobre a classe TransitionContext, visite o link http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/TransitionContext.html.

PictureScrollField

Page 6: Componentes de Interface Gráfica Avançados

Este componente permite criar um scroll de imagens horizontal, muito comum nas plataformas Android e iPhone, porém, ainda faltava este componente na BlackBerry API.

Infelizmente este componente está presente somente na versão 5.0, ou superior, do sistema operacional do BlackBerry.

Para começar a brincadeira, vamos criar uma aplicação PictureApp, tendo como classe principal, um arquivo com o mesmo nome. Sendo assim, veja a listagem abaixo:

public class PictureApp extends UiApplication{

public static void main(String[] args) {PictureApp theApp = new PictureApp ();

theApp.enterEventDispatcher(); }

public PictureApp () { MainScreen baseScreen = new MainScreen(); baseScreen.setTitle("Scroll de Minhas Fotos"); pushScreen(baseScreen);

}

}

Obviamente, ainda não estamos utilizando nosso componente. Para tanto, vamos seguir alguns passos. Primeiro, vamos criar quatro instância de Bitmap:

Bitmap b1 = Bitmap.getBitmapResource("img1.jpg");Bitmap b2 = Bitmap.getBitmapResource("img2.jpg");Bitmap b3 = Bitmap.getBitmapResource("img3.jpg");Bitmap b4 = Bitmap.getBitmapResource("img4.jpg");

Será necessário que o leitor adicione quatro imagens em seu contexto, chamadas: img1, img2, img3 e img4.

O próximo passo é criar uma instância de PictureScrollField e adicioná-lo a tela:

PictureScrollField pField = new PictureScrollField(150, 150);baseScreen.add(pField);

Page 7: Componentes de Interface Gráfica Avançados

O construtor da classe aceita somente dois parâmetros, a largura e altura das imagens que serão mostradas ao usuário. Bem, mas ainda não veremos nada de mais, porque temos que definir quais são as imagens que o componente irá mostrar.

Para isso criamos as quatro instâncias de Bitmap logo no início do processo. Agora, teremos que criar quatro objetos ScrollEntry:

ScrollEntry i0 = new ScrollEntry(b1, "Img 1", "A");ScrollEntry i1 = new ScrollEntry(b2, "Img 2", "B");ScrollEntry i2 = new ScrollEntry(b3, "Img 3", "C");ScrollEntry i3 = new ScrollEntry(b4, "Img 4", "D");

O construtor de ScrollEntry está utilizando 3 parâmetros: uma instância de Bitmap, um texto de chamada e um texto que servirá como rótulo da imagem.

Para entender a funcionalidade desses três parâmetros, veja a interface do nosso aplicativo de exemplo na Figura 30:

Page 8: Componentes de Interface Gráfica Avançados

Figura 30: PictureApp em ação.

A diferença dos textos “B” e “Img 2” é que, no primeiro caso, ele fica visível apenas por alguns segundos, já o segundo, fica visível depois de alguns segundos mas depois ficará sempre visível até que o usuário selecione outra foto.

Porém, para visualizar a interface da Figura 30, temos que dizer que estas imagens e instâncias de ScrollEntry serão acopladas ao componente de scroll. Sendo assim, adicione a linha de código abaixo:

pField.setData(new ScrollEntry[]{i0, i1, i2, i3}, 0);

O método setData recebe dois parâmetros, o primeiro é um vetor de instâncias de ScrollEntry e, o segundo, o índice da imagem que estará selecionada inicialmente.

Page 9: Componentes de Interface Gráfica Avançados

Podemos também adicionar dois métodos para deixar a interface 100% fiel a da Figura 30. Adicione as duas linhas de código abaixo logo depois do setData().

pField.setLabelsVisible(true); pField.setHighlightStyle(HighlightStyle.ILLUMINATE_WITH_MAGNIFY_LENS);

O primeiro método identifica que os rótulos das imagens serão apresentados ao usuário. O segundo método define o estilo do componente. Brinque com as opções disponíveis na classe HighlightStyle e veja seus desdobramentos.

Para saber mais sobre a PictureScrollField visite a página http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/extension/component/PictureScrollField.html.

AutoComplementField

A classe AutoComplementField permite que o programador apresente um campo de entrada de texto para o usuário, porém, diferentemente de um simples EditFied, este, traz um ato complemento.

Além disso, a classe nos traz uma série de possibilidades, podendo pesquisar em tempo de execução os contatos, lista de fotos e vídeos. Estes, servirão de parâmetro para o auto complemento.

Iniciando nossos trabalhos com este novo componente, veja a listagem de código abaixo:

public class ExAutoComplete extends UiApplication{

public static void main(String[] args) {ExAutoComplete theApp = new ExAutoComplete ();

theApp.enterEventDispatcher(); }

public ExAutoComplete () { 1: MainScreen baseScreen = new MainScreen();2: baseScreen.setTitle("Campos Auto-Complemento");

3: BasicFilteredList diasSemana = new BasicFilteredList();4: String[] dias = {"Segunda","Terça","Quarta",

"Quinta","Sexta","Sábado","Domingo"};5: int uniqueID2 = 0;6: diasSemana.addDataSet(uniqueID2, dias, "dias", BasicFilteredList.COMPARISON_IGNORE_CASE);

Page 10: Componentes de Interface Gráfica Avançados

7: AutoCompleteField edit1 = new AutoCompleteField(diasSemana);8: baseScreen.add(edit1); 9: pushScreen(baseScreen); }}

Nas linhas 3 e 7 estão as duas classes protagonistas: BasicFilteredList e AutoCompleteField. O componente de auto complemento necessita de uma lista com a fonte de dados, que servirá de base para a pesquisa que será feita a partir do momento que o usuário começa a digitar caracteres no campo.

Na linha 3 criamos a instância de BasicFilteredList. Na linha 4 criamos um vetor de Strings com os dias da semana. Na linha 6 estamos adicionando um conjunto de dados a este objeto. A classe apresente dois importantes métodos, um deles é justamente o addDataSet, o outro será visto logo mais.

O addSet apresenta várias versões, sendo assim, para uma visão mais ampla desta classe, por favor, visite o link http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/collection/util/BasicFilteredList.html.

Nesta versão do método que usamos na nossa listagem estamos passando 4 parâmetros, sendo eles:

Um inteiro que serve como identificador único; Um vetor de instâncias de Object que serve como conjunto de

dados a ser pesquisado; String que define o nome do conjunto de dados; Definição de estilo do conjunto de dados. Utiliza-se uma das

constantes long que a própria classe oferece.

O construtor da AutoCompleteField é bem mais simples e tem somente duas versões. Nesta que utilizamos o único parâmetro é uma instância de BasicFilteredList. Na outra versão, passamos um segundo parâmetro que será o estilo do componente (atributo long).

O restante do código já é trivial para o leitor. Teste este código no emulador, deverá ver uma interface semelhante

à mostrada na Figura 31:

Page 11: Componentes de Interface Gráfica Avançados

Figura 30: Primeiro campo de auto complemento em ação.

Mas este componente nos traz uma opção muito interessante, em vez de definir um conjunto de dados para ele, podemos informar uma fonte de dados, como a lista de contatos por exemplo. E mais, o programador não precisa se preocupar com a interação com estes aplicativos nativos, isso é feito de forma transparente para o mesmo.

Para deixarmos nosso exemplo ainda mais interessante, adicione a listagem de código abaixo no final do construtor da classe ExAutoComplete:

1:BasicFilteredList contatos = new BasicFilteredList();2:int uniqueID = 0;3:int tipo = BasicFilteredList.DATA_SOURCE_CONTACTS;4:long campoBusca = BasicFilteredList.DATA_FIELD_CONTACTS_NAME_FULL;

Page 12: Componentes de Interface Gráfica Avançados

5:long camposRequisitados = BasicFilteredList.DATA_FIELD_CONTACTS_NAME_FULL|BasicFilteredList.DATA_FIELD_CONTACTS_EMAIL|BasicFilteredList.DATA_FIELD_CONTACTS_PHONE_ALL;6:long campoPrimario = BasicFilteredList.DATA_FIELD_CONTACTS_NAME_FULL;7:long campoSecundario = BasicFilteredList.DATA_FIELD_CONTACTS_NAME_FIRST;

8:contatos.addDataSource(uniqueID, tipo, campoBusca, camposRequisitados, campoPrimario, campoSecundario, "Contato");

10:AutoCompleteField edit2 = new AutoCompleteField(contatos, AutoCompleteField.LIST_EXPAND_ON_HIGHLIGHT;);11:baseScreen.add(edit2);

Nesta codificação, estamos criando uma instância de BasicFilteredList logo na primeira linha, depois, vamos pular para a linha 8, onde, utilizamos o outro método importante desta classe que citei anteriormente.

Na listagem anterior usamos addDataSet, agora, chamamos addDataSource. A principal diferença entre os dois é que, no primeiro caso informaremos um vetor de String que serão pesquisados pelo motor de busca do componente, no último caso, informaremos uma fonte de dados externa ao aplicativo, no nosso caso, a lista de contatos.

O método addDataSource apresenta somente duas versões, esta que utilizamos e outra que aceita somente mais um parâmetro, um long que define o estilo da fonte de dados.

Vamos ver cada um dos sete parâmetros deste método de forma separada.

O primeiro é somente um identificador único.O segundo parâmetro define o tipo da fonte de dados, mas, para ser

mais exato, define de onde o conjunto de dados será formado. No nosso exemplo passamos a variável tipo, que foi valorizada na linha 3:

3:int tipo = BasicFilteredList.DATA_SOURCE_CONTACTS;

Além da opção de contatos, existem outras sete alternativas: BasicFilteredList.DATA_SOURCE_MEMOS; BasicFilteredList.DATA_SOURCE_MUSIC; BasicFilteredList.DATA_SOURCE_PICTURE; BasicFilteredList.DATA_SOURCE_RINGTONES;

Page 13: Componentes de Interface Gráfica Avançados

BasicFilteredList.DATA_SOURCE_TASKS; BasicFilteredList.DATA_SOURCE_VIDEOS; BasicFilteredList.DATA_SOURCE_VOICENOTES;

O terceiro parâmetro define qual valor será pesquisado pelo motor de busca do componente. Ou seja, o contato tem várias informações, o AutoCompleteField precisa saber qual campo deve ser comparado.

Perceba que no nosso exemplo passamos como terceiro parâmetro a variável campoBusca, valorizada na linha 4:

4:long campoBusca = BasicFilteredList.DATA_FIELD_CONTACTS_NAME_FULL;

Da mesma forma que aconteceu anteriormente também estamos usando uma constante da própria classe. Na documentação da classe, citada anteriormente, o leitor encontrará todas as constantes que poderão ser utilizadas. Por hora, é importantíssimo que fique claro, dependendo da definição do tipo do data source, o campo de busca deverá ser escolhido entre um conjunto restrito de opções.

Por exemplo, os contatos têm vários campos, todos definidos com constantes (no total são 24), porém, se escolhêssemos o tipo DATA_SOURCE_MUSIC, o conjunto de constantes que poderíamos trabalhar se restringe a apenas 5: DATA_FIELD_MUSIC_ALBUM, DATA_FIELD_MUSIC_ALL, DATA_FIELD_MUSIC_ARTIST, DATA_FIELD_MUSIC_GENRE e DATA_FIELD_MUSIC_SONG.

O quarto parâmetro define os campos que serão retornados quando existir uma equivalência entre os caracteres digitados pelo usuário e um dos contatos do smartphone, utilizando como parâmetro de comparação o parâmetro anterior. Aqui também existe a dependência em relação ao tipo do data source.

No nosso exemplo estamos usando a variável camposRequisitados, valorizado na linha 5:

5:long camposRequisitados = BasicFilteredList.DATA_FIELD_CONTACTS_NAME_FULL|BasicFilteredList.DATA_FIELD_CONTACTS_EMAIL|BasicFilteredList.DATA_FIELD_CONTACTS_PHONE_ALL;

Os outros três parâmetros são: definição do campo primário (usando constantes), definição do campo secundário (usando constantes) e uma

Page 14: Componentes de Interface Gráfica Avançados

String que nomeia o data source. Os dois primeiros parâmetros também estão vinculados ao tipo que foi definido no segundo parâmetro.

Acho que já é hora de testarmos este aplicativo. Veja o resultado na Figura 31:

Figura 31: Segundo campo de auto complemento em ação.

Deve ter ficado bem claro que a classe AutoComplementField é a menor dor de cabeça do programador, porém, para maiores informações sobre a mesma, visite o link http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/component/AutoCompleteField.html.

Picker

Page 15: Componentes de Interface Gráfica Avançados

Os componentes Picker fornecem uma maneira mais sofisticada e rica de escolher uma data ou um arquivo do smartphone. Disponível somente a partir da versão 5.0 do sistema operacional dos BlackBerry.

Nosso aplicativo de exemplo será muito simples, apenas dois botões e dois campos, um para arquivo e outro para data. Veja a Figura 32:

Figura 32: Interface do aplicativo Picker.

O leitor deve ter achado estranho o fato de não ter visto os componentes na tela, porém, fique tranqüilo, pois os mesmos serão apresentados quando o usuário interagir com os botões.

Antes de entrar na codificação dos componentes, vamos mostrar o código inicial da aplicação. Veja a listagem de código abaixo:

public class Picker extends UiApplication {

public static void main(String[] args) {Picker theApp = new Picker ();

Page 16: Componentes de Interface Gráfica Avançados

theApp.enterEventDispatcher(); }

public Picker () { pushScreen(new Tela());

}

}

class Tela extends MainScreen{

private LabelField lblArquivo;private LabelField lblData;

public Tela(){setTitle("Picker");

lblArquivo = new LabelField("<< >>");lblData = new LabelField("<< >>");

ButtonField btnArquivo = new ButtonField("Abrir Arquivo", ButtonField.CONSUME_CLICK);

btnArquivo.setChangeListener(new FieldChangeListener() {

public void fieldChanged(Field field, int context) {

}});add(btnArquivo);

ButtonField btnData = new ButtonField("Escolha Data", ButtonField.CONSUME_CLICK);

btnData.setChangeListener(new FieldChangeListener() {

public void fieldChanged(Field field, int context) {

}});

add(btnData);add(lblArquivo);add(lblData);

}

Nesta altura do campeonato, não preciso mais explicar o código de uma aplicação deste nível. Veja somente que as duas ações dos cliques nos botões estão em branco. É agora que começa nosso trabalho com o FilePicker e DatePicker.

O primeiro passo é criar duas variáveis de instância globais. Sendo assim, coloque as duas linhas de código na sua classe Tela:

...class Tela extends MainScreen{

FilePicker filePicker = FilePicker.getInstance();

Page 17: Componentes de Interface Gráfica Avançados

DateTimePicker datePicker = DateTimePicker.createInstance();

...

Sim, nenhuma das classes possui construtor, apenas os métodos getInstance() e createInstance(), respectivamente.

Vamos trabalhar primeiro com o botão de arquivo. Para mostrar o picker que navegará pelos arquivos do aparelho e permite uma escolha amigável, basta uma linha de código, veja:

btnArquivo.setChangeListener(new FieldChangeListener() {public void fieldChanged(Field field, int context) {

UiApplication.getUiApplication().invokeLater(new Runnable(){

public void run(){ filePicker.show();}

});}

});

A única linha necessária está até em negrito. Devido a restrições de Threads, o método show da classe FielPicker deve ser lançado em um thread única, por isso estamos usando o método invokeLater da classe UiApplication.

Depois disso podemos testar a aplicação. Clique no botão “Abrir Arquivo” e deverá ver uma tela modal que permite a navegação pela árvore de diretórios e arquivos. Assim como mostrado na Figura 33:

Page 18: Componentes de Interface Gráfica Avançados

Figura 32: FilePicker acionado.

Mas depois de selecionarmos um arquivo nada aconteceu, qual o problema? Acontece que não programamos essa funcionalidade. Para tanto, faça com que a classe Tela implemente a classe Listener, como conseqüência, forneça uma implementação do método selectionDone. Veja a listagem de código abaixo:

...class Tela extends MainScreen implements Listener{

...

public void selectionDone(String selected) {lblArquivo.setText(selected);

}

...

Page 19: Componentes de Interface Gráfica Avançados

Também é necessário adicionar o listener ao objeto filePicker:

public Tela(){filePicker.setListener(this);...

Agora repita o processo, e, ao clicar no botão e escolher um arquivo, perceba que o LabelField irá alterar seu conteúdo:

A classe FilePicker (consulte mais sobre a mesma no link http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/picker/FilePicker.html) ainda possui dois métodos interessantes:

setFilter(String filtro): filtro de arquivos apresentados ao usuário. Por exempo: setFilter(“jpg”);

setPath(String path): indica o caminho que será indicado como default na hora que o componente for apresentado ao usuário.

Agora vamos partir para o DatePicker. Vamos alterar o listener do botão “Escolha Data”. Veja a listagem

abaixo:

...btnData.setChangeListener(new FieldChangeListener() { public void fieldChanged(Field field, int context) {

UiApplication.getUiApplication().invokeLater(new Runnable(){public void run(){

1: datePicker.doModal();2: Calendar cal = datePicker.getDateTime();3: int mes = cal.get(Calendar.MONTH);4: int ano = cal.get(Calendar.YEAR);5: int dia = cal.get(Calendar.DAY_OF_MONTH);6:

Page 20: Componentes de Interface Gráfica Avançados

7: lblData.setText((dia < 10?"0"+dia:""+dia) + "/" + (mes < 10?"0"+mes:""+mes) + "/" + ano);

}});

}});

...

No código estamos apresentando o componente e também tratando da escolha. Poderíamos ter usado um Listener? Sim, mas é legal conhecer todas as nuances dos componentes.

Na primeira linha apresentamos o componente. Veja na Figura 34 como ele deve ser apresentado na interface:

Figura 34: DatePicker acionado.

Page 21: Componentes de Interface Gráfica Avançados

Quando o usuário escolher uma data, a linha 2 da listagem de código será acionada, recuperando justamente o datetime escolhido. Nas linhas 3, 4 e 5 usamos o método get da classe Calendar para recuperar o dia, mês e ano escolhido. Depois disso é só configurar o lblData.

Muito fácil não é?Bem, para finalizar, vamos falar de mais alguns métodos

interessantes da DatePicker. Para saber tudo sobre esta classe, visite o link http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/picker/DateTimePicker.html.

setMaximumDate(Calendar data) e setMinimumDate(Calendar data): define os limites de escolha do usuário;

reset(): reseta o componente para a data inicial; setDateTime(Calendar data): especifica a data do componente; setIncrement(int campo, int incremento): define o valor de

incremento para um determinado campo.

SpinBoxField

Spin pode ser traduzido por girar, ou seja, este campo nada mais é do que uma caixa de seleção giratória.

Vamos fazer um aplicativo de fixação bem simples. O SpinBoxApp apenas mostra duas opções giratórias, um mês do ano e um dia do referido mês. Por não ser o foco aqui, não vamos fazer o código de tratamento verificando se a data é válida. Ex: 31 de Fevereiro.

Veja a listagem abaixo com o escopo básico do nosso aplicativo:

public class SpinBoxApp extends UiApplication {public static void main(String[] args) {

SpinBoxApp app = new SpinBoxApp();app.enterEventDispatcher();

}

public SpinBoxApp() {HomeScreen homeScreen = new HomeScreen();pushScreen(homeScreen);

}}

class HomeScreen extends MainScreen {TextSpinBoxField spinBoxDias;TextSpinBoxField spinBoxMeses;SpinBoxFieldManager spinBoxMgr;

Page 22: Componentes de Interface Gráfica Avançados

public HomeScreen() {final String[] dias = { "Janeiro", ... "Dezembro" };final String[] meses = { "01", ... "31" };

}

public void close() {}}

A listagem ainda não nos apresentou nenhuma informação nova. Apenas declaramos os objetos TextSpinBoxField e SpinBoxFieldManager na classe HomeScreen.

O título desta seção, SpinBoxField, é a super classe de TextSpinBoxField.

Para termos uma rolagem vamos criar dois conjuntos de dados. O primeiro traz os dias do mês e o segundo os meses (duas primeiras linhas do construtor de HomeScreen).

Existem apenas três construtores para a classe TextSpinBoxField. O primeiro recebe um vetor de Object, o segundo aceita um segundo parâmetro com um long representado o estilo do componente. Há ainda aquele que não recebe nenhum parâmetro. Vamos criar as instâncias destas classes logo abaixo das declarações dos objetos dias meses:

spinBoxDias = new TextSpinBoxField(dias);spinBoxMeses = new TextSpinBoxField(meses);

Se o leitor testar este código verá que os componentes ficam separados, não deixando claro para o usuário sua ligação (Acredite, os usuários são capazes de coisas inimagináveis).

Para consertar isso, vamos utilizar a classe SpinBoxFieldManager, que, como o próprio nome indica, funciona como um gerenciador automatizados para estes componentes.

Para completar nosso exemplo, insira as línguas de código abaixo no final do construtor de HomeScreen:

spinBoxMgr = new SpinBoxFieldManager();spinBoxMgr.setVisibleRows(3);spinBoxMgr.setRowHeight(30);

spinBoxMgr.add(spinBoxDias);spinBoxMgr.add(spinBoxMeses);

Page 23: Componentes de Interface Gráfica Avançados

add(spinBoxMgr);

Logo após a inicialização do componente spinBoxMgr, chamados dois de seus métodos para definir a quantidade de linhas visíveis e, para indicar o tamanho das listas apresentadas.

Posteriormente, usamos o método add da referida classe para indicar os componentes giratórios que o Manager irá controlar. Finalmente, na última linha, adicionamos o componente à tela principal do aplicativo.

Teste o aplicativo novamente, deverá visualizar uma interface como a mostrada na Figura 35:

Figura 35: SpinBoxField.

Como bônus, vamos mostrar um diálogo ao usuário assim que ele sair da aplicação, apresentando a seleção dos componentes da interface:

public void close() {

Page 24: Componentes de Interface Gráfica Avançados

Dialog.alert((String) spinBoxDias.get(spinBoxDias.getSelectedIndex())+ " de " + (String) spinBoxMeses.get(spinBoxMeses.getSelectedIndex()));

super.close();}

Para saber mais sobre a classe SpinBoxField visite a página http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/component/SpinBoxField.html.

Para saber mais sobre a classe TextSpinBoxField visite a página http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/component/TextSpinBoxField.html.

Para saber mais sobre a classe SpinBoxFieldManager vistea página http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/SpinBoxFieldManager.html.

Sobre MimGraduado em Ciência da Computação, pós-graduando em Web:

Estratégias de Inovação e Tecnologia. Analista de sistemas mobile na MobMidia | Grupo Pontomobi, Ricardo da Silva Ogliari é autor de dezenas de artigos que foram publicados em anais de congressos nacionais e internacionais, sites especializados e revistas. Palestrante em eventos nacionais e internacionais, como JustJava, Java Day, GeoLivre, ExpoGPS, FISL e FITE, sempre aborda temas relacionados a computação móvel.