Caso prefira, você encontrará todo esse material, em inglês, no site do Developer Android. A tradução e comentários dos materiais eu faço livremente para ajudar a comunidade que fala português.

quarta-feira, 16 de março de 2011

1 comentários

Interface de Usuários - Construindo Componentes Customizados

O Android oferece um sofisticado e poderoso modelo componentizado para construir sua interface de usuário, baseado nas classes fundamentais de layout: View e ViewGroup. Para começar, a plataforma inclui uma variedade de Views e ViewGroup chamadas widgets e layouts, respectivamente, que você pode usar para construir sua interface.

Uma lista parcial dos widgets disponíveis incluem Button, TextView, EditText, ListView, CheckBox, RadioButton, Gallery, Spinner e alguns com propostas mais específicas, como AutoCompleteTextView, ImageSwitcher e TextSwitcher.

Entre os layouts disponíveis estão o LinearLayout, FrameLayout, RelativeLayout e outros. Para outros exemplos, veja Common Layout Objects.

Se nenhum dos widgets padrão ou layouts atendem suas necessidades, você pode criar sua própria subclasse View. Você precisará fazer apenas pequenos ajustes no widget ou layout e você pode simplesmente criar uma subclasse do widget ou layout e fazer o override de seus métodos.

Criar sua própria subclasse View dá o controle preciso sobre a aparência e função de um elemento de tela. Para dar uma idéia do controle que você tem com uma view customizada, aqui vão alguns dos exemplos do que você pode fazer com eles:
  • Você pode criar um tipo View completamente customizado como, por exemplo, um controle de volume renderizado usando gráficos 2D que se assemelhe ao controle analógico real.
  • Você pode combinar um grupo de componentes View em um único componente, talvez para fazer algo como uma combobox (uma combinação de lista em popup e um campo text), um controle dual-pane (com paineis do lado esquerdo e direito onde você pode assinalar de qual lista um item faz parte) e assim por diante.
  • Você pode fazer o override na forma como um EditText é renderizado na tela.
  • Você pode capturar outros eventos como keypress e retornar alguma interação de acordo com a maneira como desejar (como em um jogo).

Abordagem básica

Aqui está um overview do que é necessário para começar a criar seus próprios componentes View customizados:
  1. Extenda uma classe View existente ou subclasse em sua própria classe.
  2. Faça o override de alguns dos métodos da superclasse. Os métodos da superclasse a serem feitos override começam com 'on'. Por exemplo, onDraw(), onMeasure(), on KeyDown(). 
  3. Use sua nova classe de extensão. Uma vez completada, a nova classe pode ser usada no lugar da classe na qual ela é baseada.
Dica: Classes de extensão podem ser definidas como classes internas às atividades que as usam. Isso é particularmente útil já que o controle de acesso à classe é feito automaticamente.

Componentes Customizados Completos

Componentes customizados completos podem ser usados para criar componentes gráficos da maneira como desejar. Talvez um medidor gráfico que se pareça com um medidor analógico ou qualquer outra coisa que você tenha em mente. De qualquer forma, você vai querer algo que os componentes padrão ainda não façam, não importa a maneira como você os combine.

Felizmente, você pode facilmente criar componentes que tem o visual e se comportam da maneira que você quer limitado, talvez, apenas pela sua imaginação, o tamanho da tela e o poder de processamento disponível (lembre-se que sua aplicação vai rodar em um dispositivo que terá muito menos poder de processamento que seu desktop onde está criando o app).

Para criar um componente customizado completo:
  1. A View mais genérica da qual você pode extender é, sem surpresa nenhuma, a View. Então, você vai começar, normalmente, extendendo seu código a partir dessa classe e criar seu novo super componente a partir dela.
  2. Você pode suprir um construtor que poderá receber atributos e parâmetros a partir de um arquivo XML.
  3. Você vai querer, provavelmente, criar seus próprios event listeners, property accessors e modifiers e possivelmente comportamentos mais sofisticados dentro da sua classe de componente.
  4. Você vai certamente querer fazer o override do método onMeasure() e também de onDraw() se você quiser que seu componente mostre alguma coisa. Mesmo tendo comportamentos padrão, o onDraw() padrão não faz nada e o onMeasure() padrão vai sempre colocar o tamanho como 100x100.
  5. Outros métodos on... deverão ser overriden.
Extendendo onDraw() e onMeasure()

O método onDraw() cria um Canvas sobre o qual você pode implementar qualquer coisa que queira: gráficos 2D, outros componentes padrão ou customizados, texto estilizado ou qualquer coisa que você possa imaginar. Imagine um pintor que vai criar sua obra. Ele pega as tintas e a tela onde vai pintar. Canvas é a tela onde você poderá criar o que imaginar. Em tecnologia, o termo canvas significa isso: o local onde você poderá criar o que deseja.

Nota: O canvas não se aplica a gráficos 3D. Se quiser usar gráficos dessa natureza, você deve extender SurfaceView ao invés da View, e desenhar o gráfico em uma thread separada. Você pode checar por GLSurfaceViewActivity para mais detalhes.

Já o método onMeasure() é um pouco mais complexo. onMeasure() é uma peça critica para o contrato de renderização do seu componente e o seu container. onMeasure() deve ser overriden para eficientemente e corretamente reportar as medidas de seu container para que a renderização seja perfeita na tela. O onMeasure() foi feito para ser mais complexo por conta dos requerimentos de limites dos componentes pais onde eles estão posicionados e pelo requerimento de chamar o método setMeasuredDimension() com a medida em largura e altura que foi calculada. Se você falhar em chamar esse método de um onMeasure() que foi overriden, o resultado é que uma exceção será chamada.

Implementar o onMeasure() seria algo assim:
  1. O método onMeasure() que foi overriden é chamado com as especificações de largura e altura (parâmetros widthMeasureSpec e heightMeasureSpec, ambos com valores em inteiro representando as dimensões do componente pai onde ele está sendo criado) que deve ser tratado como um requerimento para as restrições de largura e altura a serem produzidas. 
  2. O método onMeasure() do componente calcula as medidas de largura e altura necessárias para renderizar o componente. Ele vai tentar se manter dentro das especificações enviadas.
  3. Uma vez que a largura e altura foram calculadas, o método setMeasuredDimension(int width, int height) deve ser chamado com as medidas calculadas. Se houver uma falha em conseguir um resultado e uma exceção será lançada.
Aqui está um sumário de alguns dos outros métodos padrões que a framework chama nas views:

CategoryMethodsDescription
CreationConstrutoresExiste uma forma do construtor que é chamado quando a View é criada no código ou quando a View é inflada a partir de um arquivo de layout. A segunda forma passa quaisquer atributos definidos no arquivo de layout.
onFinishInflate()Chamado após a view e todos os itens filhos serem inflados da XML.
LayoutonMeasure(int, int)Chamado para determinar os requerimentos de tamanho para  a View e todos os seus filhos.
onLayout(boolean, int, int, int, int)Chamado quando a View deve assinalar o tamanho e posição de todos os seus filhos.
onSizeChanged(int, int, int, int)Chamado quando o tamanho da View foi mudado.
DrawingonDraw(Canvas)Chamado quando uma View deve renderizar seu conteúdo.
Event processingonKeyDown(int, KeyEvent)Chamado quando um novo evento de tecla ocorre.
onKeyUp(int, KeyEvent)Chamado quando um novo evento key up ocorre.
onTrackballEvent(MotionEvent)Chamado quando um evento de movimentação do trackball ocorre.
onTouchEvent(MotionEvent)Chamado quando um evento touch screen ocorre.
FocusonFocusChanged(boolean, int, Rect)Chamado quando uma View ganha ou perde o foco.
onWindowFocusChanged(boolean)Chamado quando uma janela contendo views ganha ou perde foco.
AttachingonAttachedToWindow()Chamado quando uma View é anexada a uma janela.
onDetachedFromWindow()Chamado quando uma View é desanexada de uma janela.
onWindowVisibilityChanged(int)Chamado quando a visibiliadde da janela contendo a View é modificada.
Na página de Demonstração de APIs existem vários exemplos de componentes customizados. Dê uma olhada lá para ver como é o código.

No próximo post, Controles Compostos e como modificar um View Type existente 

Interface de Usuários - Aplicando estilos e Temas na interface

É isso ai pessoal, mesmo com dengue, cá estou eu não deixando-os na mão. Pelo menos a febre baixou, mas o corpo ainda está todo dolorido. Nada que me impedisse de vir aqui escrever mais esse post.

-----

Existem duas maneiras de se aplicar um estilo:

  • Aplicando o estilo a uma View individual, onde você adiciona o atributo style no elemento View dentro da XML responsável pelo seu layout ou;
  • Aplicando um estilo para uma atividade ou aplicação, onde você adiciona o atributo android:theme em <activity> ou <application> dentro do manifesto do Android.
Quando você aplica um estilo a uma View em particular dentro do layout, as propriedades definidas pelo estilo são aplicadas apenas aquela View. Se um estilo é aplicado a um ViewGroup, os elementos View filhos NÃO vão herdar as propriedades de estilo - apenas o elemento no qual é aplicado diretamente o estilo terá as propriedades mostradas. Contudo, se você quer que um estilo se aplique a todos os elementos View, você terá de usar um tema.

Para aplicar uma definição de estilo como um tema, você deve aplicá-lo à atividade ou aplicação dentro do manifesto do Android. Quando você faz dessa maneira, cada View dentro da atividade ou aplicação vai aplicar as propriedades que suportadas. Por exemplo, se você aplicar o estilo CodeFont do post anterior a uma atividade, então todas os elementos View que suportam o estilo de texto descrito dentro do arquivo de estilo vão aplicá-lo. Quaisquer Views que não suportem alguma das propriedades não a terão aplicada. Se uma View suporte apenas uma das propriedades, apenas essa propriedade será aplicada.

Aplicando um estilo a uma View

Aqui está como aplicar um estilo para uma View no layout XML:
<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />
Agora esse TextView terá um estilo definido pelo estilo de nome CodeFont.

Nota: O atributo style NÃO usa o prefixo android: como visto em android:text.

Aplicando um tema a uma atividade ou aplicação

Para aplicar um tema para todas as atividades de sua aplicação, abra o arquivo AndroidManifest.xml e edite a tag <application> inserindo o atributo android:theme com o nome do estilo. Por exemplo:
<application android:theme="@style/CustomTheme">
Se você quer um tema aplicado apenas a uma atividade de sua aplicação, então adicione o atributo android:theme à tag <activity>.

Assim como o Android provê outros recursos já built-in (ou, de fábrica, por assim dizer), existem outros temas pré-definidos que você pode usar para evitar escrever tudo você mesmo. Por exemplo, você pode usar o tema Dialog e fazer com que uma atividade fique com a cara de uma caixa de diálogo:
<activity android:theme="@android:style/Theme.Dialog">
Ou, se você pode querer que o fundo seja transparente, você pode usar o tema Translucent:
<activity android:theme="@android:style/Theme.Translucent">
Se você gostou de algum tema, você ainda pode modificá-lo e, por que não, melhorá-lo. Para tal, adicione o tema como parent de seu tema customizado. Por exemplo, você pode modificar o tema e inserir suas próprias cores:
<color name="custom_theme_color">#b0b0ff</color><style name="CustomTheme" parent="android:Theme.Light">    <item name="android:windowBackground">@color/custom_theme_color</item>    <item name="android:colorBackground">@color/custom_theme_color</item></style>
Note que a cor precisa ser suprida como um recurso separado aqui pois o atributo android:windowBackground apenas suporta a referência para outro recurso, diferente de android:colorBackground, que a ele pode ser dado um literal representando uma cor.

Agora, para usar o tema customizado ao invés de Theme.Light dentro do manifesto Android, basta fazer isso:
<activity android:theme="@style/CustomTheme">
Selecione o tema baseado na versão de plataforma

Novas versões do Android tem temas adicionais aplicáveis às aplicações e você pode querer usá-los quando estiver rodando suas aplicações nessas plataformas enquanto elas se mantém, mesmo assim, compatíveis com versões anteriores. Você pode conseguir isso através de um tema customizado que usa uma seleção de recursos para definir diferentes temas pais, baseados na versão da plataforma.

Por exemplo, aqui está uma declaração de um tema customizável que é simplesmente a versão padrão Theme.Light que se encontraria dentro de um arquivo XML na pasta res/values (tipicamente res/values/styles.xml):
<style name="LightThemeSelector" parent="android:Theme.Light">    ...</style>
Para que esse tema use o tema holográfico do Android 3.0 (API 11), você pode colocar uma declaração alternativa para o tema dentro de um arquivo XML em res/values-v11, mudando apenas o valor de parent:
<style name="LightThemeSelector" parent="android:Theme.Holo.Light">    ...</style>
Assim, ele saberá qual tema pai usar baseado na versão da API. Caso seja a API 11 ou maior, usará o android:Theme.Holo.Light. Caso seja menor, usará android:Theme.Light.

Uma lista de atributos padrão que você pode usar em temas pode ser encontrado em R.stylable.Theme.

Usando uma plataforma de estilos e temas

A plataforma Android provê uma larga coleção de estilos e temas que você pode usar em suas aplicações. Você poderá encontrar referências para estilos disponíveis na classe R.style. Para usar os estilos listados dentro de R.style, substitua todos os caracteres underscore _ com um ponto. Por exemplo, você pode aplicar o tema Theme_NoTitleBar com "@android:style/Theme.NoTitleBar".

No entanto, a referência contida em R.style não é bem documentada e não descreve no todo os estilos, então ver o código desses estilos dá um melhor entendimento de como ele é. Para uma melhor referência dos estilos e temas do Android, veja esses códigos fontes:

Intervalo para cuidar de mim

Pessoal, se não houver posts por esses dias, a razão é que estou com dengue. Mas assim que tiver condições de escrever, eu posto mais material.

segunda-feira, 14 de março de 2011

0 comentários

Interface de Usuários - Estilos e Temas

Um estilo é uma coleção de propriedades que especificam o visual e formato de uma View ou janela. Um estilo por especificar propriedades como altura, padding, cor de fonte, tamanho da fonte, cor de fundo e muito mais. Um estilo é definido em um recurso XML que é reparado do XML que especifica o layout.

Estilos em Android compartilham uma filosofia similar ao que é o CSS para web design - eles permitem a você separar o design do conteúdo.

Por exemplo, usando um estilo, você pode pegar esse XML de layout...

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="#00FF00"
    android:typeface="monospace"
    android:text="@string/hello" />

...e torná-lo em algo como isso:

<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />
Todos os atributos relacionados a estilo foram removidos do XML de layout e colocados em um estilo definido pelo nome CodeFont, que é então aplicado com o atributo style.

Um tema é um estilo aplicado em toda uma atividade ou aplicação, ao invés de apenas em uma View individual (como no exemplo acima). Quando um estilo é aplicado como um tema, cada View na atividade vai ter o estilo aplicado onde for suportao. Por exemplo, você pode aplicar o mesmo estilo CodeFont como um tema para uma atividade e então todo o texto dentro da atividade vai ter uma fonte mono espaçada de cor verde.

Definindo Estilos

Para criar um conjunto de estilos, salve um arquivo XML na pasta res/values dentro do seu projeto. O nome do arquivo XML é arbitrário, mas você deverá usar a extensão .xml e salvá-lo na pasta indicada acima.

O nó raiz do arquivo XML de estilo deverá ser <resources>.

Para cada estilo que você queira criar adicione um elemento <style> ao arquivo com um name que identifique unicamente o estilo. Então adicione elementos <item> para cada propriedade do estilo, com o name que declare a propriedade de estilo e o valor a ser usado. O valor para o <item> pode ser uma string, um código hexadecimal para cor, uma referência para outro recurso ou outro valor dependendo das propriedades do estilo. Aqui está um exemplo de um estilo:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>
</resources>
Cada filho do elemento <resources> é convertido em um objeto de recurso da aplicação em tempo de compilação, que pode ser referenciada pelo valor do atributo name dentro do elemento <style>. Esse estilo de exemplo pode ser referenciado a partir de um XML de layout usando @style/CodeFont.


O atributo parent dentro do elemento <style> é opcional e especifica o ID de recurso de um outro estilo a partir do qual esse estilo deverá herdar propriedades. Você pode, se quiser, fazer o override de propriedades de estilo.

Lembre-se, um estilo que você quer usar como aplicação ou tema de aplicação é definido no XML da mesma maneira que um estilo para uma View. Um estilo como o que definimos acima pode ser aplicado como estilo para uma View única ou como um tema para uma atividade ou aplicação.

Herança

O atributo parent dentro do elemento <style> permite a você especificar de qual outro estilo seu estilo deverá herdar propriedades. Você pode usar esse atributo para herdar propriedades de um estilo existente e então definir suas próprias propriedades que você quer mudar ou adicionar. Você pode herdar de estilos que você mesmo criou ou de estilos que são definidos na plataforma. Por exemplo, você pode herdar o estilo de aparência padrão do Android para textos e depois modificá-lo:

<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
Se você quer herdar de estilos que você definiu pessoalmente, você não precisa usar o atributo parent. Ao invés disso, apenas use o prefixo do nome do estilo de onde deseja que haja a herança, separada por pontos. Por exemplo, para criar um novo estilo que herda do estilo CodeFont mas deseja que a cor das letras sejam vermelhas, você pode criar um novo estilo como abaixo:

<style name="CodeFont.Red">
        <item name="android:textColor">#FF0000</item>
</style>
Note que não existe o atributo parent dentro da tag <style>, mas como o atributo name começa com a palavra CodeFont e este é o nome de um estilo, esse novo estilo herda as propriedades de CodeFont. Então o novo estilo faz um override nas características do texto fazendo-o ficar na cor vermelha. Você pode então referenciar esse novo estilo como @style/CodeFonte.Red.

Você pode continuar fazendo heranças quantas vezes entender ser necessário. Por exemplo, você pode extender CodeFont.Red para ser do format Bigger.

<style name="CodeFont.Red.Big">
        <item name="android:textSize">30sp</item>
</style>
Nota: Esse formato de herança em que vamos separando os nomes por pontos só funciona com seus próprios estilos. Não é possível fazer dessa maneira com os estilos padrão do Android.

Propriedades de Estilo

Agora que você entendeu como um estilo é definido, você precisará aprender que tipos de propriedades de estilo - definidas no elemento <item> - estão disponíveis.

O melhor local para encontrar propriedades para aplicar a uma View é a classe de referência da View em específico, que lista todos os atributos XML suportados. Por exemplo, todos os atributos listados na tabela dos atributos de TextView podem ser usados em um estilo de definição para o elemento TextView (ou qualquer de suas subclasses). Como existe um atributo chamado android:inputType na classe de referência, você poderá inserir o atributo android:inputTyle dentro do elemento <EditText>, que é subclasse de TextView:

<EditText
    android:inputType="number"
    ... />
Você pode ao invés disso criar um estilo para o EditText:

<style name="Numbers">
  <item name="android:inputType">number</item>
  ...
</style>
E então seu XML para o layout precisará apenas implementar o estilo como abaixo:

<EditText
    style="@style/Numbers"
    ... />
Esse exemplo acima pode parecer que dá mais trabalho, mas verá que, com o tempo, a reutilização de tais estilos dará maior controle sob o estilo de sua aplicação.

Para uma referência de todas as propriedades de estilo disponíveis, vá na referência de R.attr. Tenha em mente que nem todos os objetos View aceitam todos os mesmos atributos de estilo, então você deve sempre observar os estilos de propriedades suportados pela View. Contudo, se você aplicar um estilo a uma View que não a suporta, a View apenas usará os estilos suportados e ignorará todos os outros.

Algumas propriedades de estilo, contudo, não são suportadas por nenhum elemento View e pode ser aplicado apenas como um tema. Essas propriedades de estilo são aplicadas para toda a janela e não para um tipo de View. Por exemplo, propriedades de estilo para um tema podem esconder o título da aplicação, esconder o status bar ou mudar o fundo da janela. Esses tipos de propriedades de estilo não pertencem a nenhum objeto View. Para descobrir mais sobre essas propriedades que são suportadas apenas nos temas, procure pelos atributos que começam com window dentro de R.attr.

No próximo post, falarei sobre como aplicar estilos e temas para a interface.

Interface de Usuários - Notificando o usuário

Vários tipos de situação podem surgir que necessitarão que você notifique o usuário sobre eventos que ocorrem em sua aplicação. Alguns desses eventos vão requerir que o usuário responda à notificação e outros não. Por exemplo:
  • Quando um evento como salvar um arquivo foi completado, uma mensagem poderá aparecer confirmando que o arquivo foi salvo com sucesso.
  • Se sua aplicação está rodando em background e precisa da atenção do usuário, a aplicação poderá criar uma notificação que permita ao usuário responder convenientemente.
  • Se sua aplicação está efetuando uma ação na qual o usuário deverá aguardar ser completada, a aplicação poderá mostrar uma barra de progresso ou roda de progresso.
Cada uma dessas tarefas de notificação podem ser alcançadas usando uma técnica diferente:
  • Um Toast Notification, para mensagens rápidas.
  • Um Status Bar Notification, para lembretes persistentes que requerem a resposta do usuário.
  • Um Dialog Notification, para notificações relacionadas à atividade.
Toast Notification

Um toast notification (Notificação Torrada. Aliás, é um nome terrível se a gente parar para pensar nele) é uma mensagem que aparece na superfície da janela. É apenas ocupa o espaço necessário para que seja exibida a mensagem. A notificação automaticamente desaparece e não recebe nenhum evento de interação. Como um toast pode ser criado a partir de um serviço rodando em background, ele aparece mesmo que a aplicação não esteja visível.

Um toast é melhor usado para mensagens curtas, tal como "Arquivo salvo com sucesso" quando você tem quase certeza que o usuário está dando atenção à tela.

Status Bar Notification

Um Status Bar Notification adiciona um ícone ao status bar do sistema (com uma mensagem de horário opcional) e uma mensagem expandida na tela de notificação. Quando o usuário seleciona a mensagem expandida, o Android abre um intent que é definido pelo usuário (usualmente quando lança uma atividade). Você também pode configurar a notificação para alertar o usuário com um som, uma vibração ou fazer com que luzes do dispositivo sejam piscadas.

Esse tipo de notificação é ideal quando sua aplicação está trabalhando como serviço em background e precisa notificar o usuário sobre um evento. Se você precisar alertar o usuário para um evento que ocorrer enquanto uma atividade ainda está em foco, considere o uso do Dialog Notification.

Dialog Notification

Um diálogo é usualmente uma janela pequena que aparece na frente da atividade corrente. A atividade perde o foco e o diálogo aceita todas as interações do usuário. Diálogos são normalmente usados para notificações e atividades curtas que diretamente são relacionadas à aplicação em progresso.

Já falei desse tópico aqui. Para maior referência, basta acessar a parte 1 e parte 2 sobre esse tipo de notificações.

sexta-feira, 11 de março de 2011

1 comentários

Interface de Usuários - App Inventor Beta

No Twitter o Carlos @fcarlosmonteiro veio me dizer sobre um aplicativo da Google que se chama App Inventor Beta. Basicamente, ele é um site onde você pode criar apps para Android. Veja, não são aplicativos complexos, mas simples. Mesmo assim, dá para brincar bastante por lá.

Para tal, acesse http://appinventor.googlelabs.com/about/

Nesse link, você encontrará algumas informações básicas sobre o que é o AppInventor.

Mas, e como eu uso o software? Simples, basta entrar em http://appinventor.googlelabs.com e se logar com uma conta do Google válida. Na 1a tela, ele pedirá que você concorde com os termos de uso do App Inventor. Para tal, basta clicar no botão que aparecerá.

Com isso, você voltará para a tela inicial do App Inventor. Clique no link My Projects que uma nova janela se abrirá. É nela que você vai criar seus apps.


Depois, você verá que existirão alguns botões de ações no canto esquerdo superior:


Ao clicar em New, uma janela se abrirá e você será perguntado pelo nome do App. Vou colocar o projeto de praxe: HelloWorld e depois clicar em OK


Dai é só começar a brincar. No canto esquerdo há a paleta de itens que poderão ser inseridos na tela. No centro, à esquerda, existe a simulação da tela do smartphone. No centro, à direita, serão mostrados hierarquicamente os itens que forem sendo inseridos na tela. E, por fim, no canto direito serão mostradas as propriedades dos componentes que estiver com o foco.


Você poderá brincar a beça. E, depois, poderá baixar o seu código. A partir da tela inicial dos seus projetos, selecione o projeto e clique no botão More Actions > Download Source.

Um arquivo ZIP com o código será baixado e você poderá abrí-lo para entender como ele foi criado.

Bacana, né? Nem tanto. Se você abrir o código fonte do HelloWorld.zip perceberá que a estrutura criada nela não é tão parecida com a que é criada no Eclipse.



Ou seja, apesar dele ser mais uma maneira de se criar código, não é tão completo quanto a integração do Eclipse com o Android, mas ajuda bastante para quem teve uma excelente idéia em um PC que não tem o Eclipse e quer colocar em prática a sua idéia.

A questão é: vale a pena criar apps nessa interface web? Que cada um de vocês tirem suas próprias conclusões.

Interface de Usuários - Manipulando eventos

No Android, existe mais de uma maneira de interceptar eventos de interação de usuário em sua aplicação. Quando consideramos eventos dentro de sua interface de usuário, a abordagem deve ser a de capturar os eventos do objeto de View específica na qual o usuário está interagindo. A classe View provê todo o necessário para fazê-lo.

Dentro das várias classes View que vão compor o seu layout, você vai notar diversos métodos públicos que contém eventos muito úteis para a interface. Esses métodos são chamados pelo framework Android quando a ação correspondente ocorre no objeto. Por exemplo, quando uma View (como um botão) é tocado, o método onTouchEvent() é chamado no objeto. Contudo, para que possa ser interceptado, você deve extender a classe e fazer o override do método. Mas, extender cada um dos objetos View seria impraticável. É por esse motivo que a classe View também contém uma coleção de interfaces aninhadas com callbacks que você pode definir de maneira muito mais fácil. Essas interfaces, chamadas event listeners, são seu ticket para capturar quaisquer interações de usuários dentro de sua interface.

Mesmo que usualmente você use os event listeners mais comuns para fazer a interação da aplicação com o usuário, chegará um momento em que você vai querer extender a classe View para criar um componente customizado. Talvez você queira extender uma classe Button para fazer algo mais bonito de se ver. Nesse caso, você será capaz de definir eventos padrão de comportamento para sua classe usando os event handlers.

Event Listeners

Um event listener é uma interface da classe View que contém um método simples de callback. Esse método pode ser chamado pela framework Android quando a View à quando o listener está registrado é chamado por uma interação de usuário com um item da interface.

Incluído nas interfaces de event listener estão os seguintes métodos callback:

onClick()
Vem de View.OnClickListener. É chamado quando o usuário toca o item (quando estiver em modo de toque) ou foca o item através de teclas de navegação ou trackball e pressiona o botão de enter correspondente ou pressiona o trackbak (que também serve como enter).

onLongClick()
Vem de View.OnLongClickListener. É chamado quando o usuário toca um item e o segura (quando estiver em modo de toque) ou foca o item através de teclas de navegação ou trackball e pressiona o botão de enter correspondente e o segura ou pressiona o trackbak por pelo menos um segundo.

onFocusChange()
Vem de View.OnFocusChangeListener. É chamado quando o usuário navega para dentro ou para fora de um item, usando as teclas de navegação ou trackball.

onKey()
Vem de View.OnKeyListener. É chamado quando o usuário foca em um item e pressiona ou solta uma tecla no dispositivo. Exemplo: quando se está escrevendo uma mensagem, você pode tocar no botão virtual (ou físico) da letra A e, ao soltá-lo, a letra A é mostrada na tela.

onTouch()
Vem de View.OnTouchListener. É chamado quando o usuário performa uma ação qualificada como um evento de toque, incluindo pressionar, soltar ou qualquer movimento de gesto na tela (dentro dos limites do item).

onCreateContextMenu()
Vem de View.OnCreateContextMenuListener. É chamado qunado um menu de contexto está sendo criado (como resultado de um long click).

Esses métodos habitam apenas suas respectivas interfaces. Para definir um ou mais desses métodos para interceptar seus eventos, implemente a interface aninhada em sua Atividade e a defina como uma classe anônima. Então, passe uma instância de sua implementação para o método respectivo View.set[]Listener (onde [] pode ser substituido por OnClick, OnKey, etc, gerando setOnClickListener, setOnKeyListener, etc).

O exemplo abaixo mostra como registrar um listener onClick para um botão.

// Cria uma implementação anônima de OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
    public void onClick(View v) {
      // faz algo quando o botão é clicado
    }
};
protected void onCreate(Bundle savedValues) {
    ...
    // Cria o botão para o layout
    Button button = (Button)findViewById(R.id.corky);
    // Registra o listener onClick listener com a implementação acima
    button.setOnClickListener(mCorkyListener);
    ...
}
Você vai achar mais conveniente implementar um OnClickListener como parte de sua atividade. Dessa maneira você evitará uma classe extra apenas para carregar os listeners. Por exemplo:

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }
    // Implementa o callback OnClickListener
    public void onClick(View v) {
      // Faz algo quando o botão é clicado
    }
    ...
}
Note que o callback onClick() do exemplo acima não tem valor de retorno, mas alguns outros event listeners devem retornar um valor booleano, dependendo do evento chamado.

onLongClick() e onClick()
Retorna um booleano indicando se você consumiu o evento e se ele deve ser continuado. Ou seja, retorna true para indicar que o processo já foi interceptado e que deve ser terminado ou retorna false se não foi interceptado e o evento deve continuar.

onTouch()
Retorna um booleano indicando se seu listener já consumiu o evento. A coisa importante aqui é que o evento pode ter multiplas ações que seguem uma à outra. Então, se for retornado false quando um evento for recebido é indicado que você não consumiu o evento e que você não está interessado nos eventos subsequentes a partir desse evento.

Lembre-se que os eventos são sempre disponibilizados para a View em foco no momento. Eles são despachados começando do topo da hierarquia de View até chegar ao destino apropriado. Se sua View (ou um filho de uma View) perde o foco, então você poderá ver toda o histórico dos eventos usando o método dispatchKeyEvent(). Como uma alternativa a captura de eventos de tecla através de sua View, você também pode receber todos os eventos dentro de sua atividade usando onKeyDown() e onKeyUp().

Event Handlers

Se você estiver construindo um componente customizado para sua View, então você terá de definir os métodos de callback a serem usados como handlers padrão para o evento. Quando chegarmos no tópico de construção de componentes customizados, veremos como fazer essa configuração.

Modo de Toque

Quando um usuário está navegando pela interface com teclas direcionais ou trackball, é necessário dar foco aos itens que contém ações (como botões) para que o usuário possa saber com quais itens pode interagir e que oferecem ação. Se o seu dispositivo tem capacidade de toque, contudo, o usuário começa a interagir com a interface bastando tocá-la, não sendo mais necessário dar foco a esses itens. Esse modo de interação é chamado de touch mode.

Para um dispositivo de toque, uma vez que o usuário toque a tela o dispositivo entrará em modo de toque. A partir desse ponto em diante, apenas as Views para as quais o método isFocusableInTouchMode estiver como true é que poderão ser focados, como edição de texto em widgets. Outras Views que são tocáveis, como botões, não obterão foco quando tocadas; elas simplesmente vão disparar os listeners onClick quando pressionados.

A qualquer momento que o usuário toque as teclas direcionais ou ande pela tela com um trackball, o dispositivo vai sair do modo de toque e tentará encontrar uma View que possa gerenciar focos.

O modo de toque é mantido pelo sistema. Para verificar se ele está em modo toque, basta chamar isInTouchMode para checar.

Gerenciando Foco

A framework vai gerenciar rotinas de focos em resposta às entradas do usuário. Isso inclui mudar o foco quando as Views são removidas ou escondidas ou quando novas Views se tornarem disponíveis. Views indicam a sua capacidade de ter foco através do método isFocusable(). Para mudar essa característica na View, você pode chamar setFocusable(). Quando estiver em modo toque, você poderá pesquisar para saber se a View aceita foco com isFocusableInTouchMode(). Você pode mudar essa característica usando setFocusableInTouchMode().

Normalmente o Android entende qual é o próximo item a ter foco, verificando qual o item mais próximo. No entanto, em casos raros, é necessário que você insira a sequência a ser seguida. Nesse caso, você pode prover atributos no layout do arquivo usando tags como nextFocusDown, nextFocusLeft, nextFocusRight e nextFocusUp. Exemplo abaixo:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>
Com o código acima, veja que o foco vai do botão top para o botão bottom e vice-versa.

segunda-feira, 7 de março de 2011

0 comentários

Eclipse Marketplace e Color Themes

Quando eu passei a usar o Eclipse (e isso não tem muito tempo), eu estranhei a forma como o código era apresentado para mim em termos de colorização. Tendo vindo de outras ferramentas (como o Visual Studio 2010) em que eu instalei alguns plugins que melhoraram a colorização, fiquei me perguntando como fazer uma mudança nas cores do código no meu Eclipse para mimetizar a colorização que já estava acostumado.

Sei que parece besteira, mas com o tempo você se habitua a certos padrões de cores e, quando muda, você meio que fica perdido. Para mim, por exemplo, cor verde no código é sinal de comentário. Ok, estou parecendo mesmo velho, mas quem é que nunca passou por tal mudança e ficou meio perdido?

O padrão de cores do Eclipse é como o mostrado abaixo:


Então, fui pesquisar sobre como modificar essa visualização. A primeira coisa que fiz foi ir até as preferências do Eclipse (Window > Preferences). Lá, fui até Java > Editor > Syntax Coloring. 


A solução para meus problemas havia acabado. Nessa tela eu tenho acesso a todos os aspectos de colorização de sintaxe. Com isso, posso modificar a forma como meus códigos são mostrados para que sejam de meu agrado.

No entanto, abrindo a guia Java, vi a quantidade de itens que poderia configurar e percebi que seria uma tarefa tediosa. Então, resolvi pesquisar um pouco mais e descobri um plugin de colorização que só pode ser instalado no Eclipse através do Eclipse Marketplace, que é um local onde existe uma série de plugins para melhorar a vida de nós, desenvolvedores.

No entanto, como estamos usando o Eclipse Classic, a opção do Marketplace não está disponível por padrão. Então, vamos ver como instalar o Marketplace e também o plugin em questão.
  1. Abra o Eclipse e vá na opção Help > Install New Software.
  2. Quando a caixa abrir, escolha Helios como caminho de pesquisa e digite Marketplace no campo de pesquisa, como mostrado na imagem ao lado.
  3. Clique em Next e o instalador vai calcular as dependências e baixar o pacote da internet.
  4. Quando chegar a uma tela a janela pede para revisar a licença, marque a opção I accept the terms of the licence agreement e clique em Finish.
  5. Se tudo correr bem, o Eclipse pedirá para ser reinicializado.
Uma vez que o Eclipse tenha sido reiniciado, você vai perceber que já existe a opção de Marketplace em Help, como a imagem abaixo mostra.

Uma tela como a seguinte deverá aparecer.


Nessa tela, vamos fazer a pesquisa pelo Plugin Eclipse Color Theme, que no momento da criação desse post estava em sua versão 0.9.1. Ao achá-lo, como mostra a imagem abaixo, clique no botão Install que vem ao lado direito dele.


Uma tela com a confirmação dos itens a serem instalados aparecerá (caso você tenha selecionado mais de um item, serão mostrados nessa tela). Clique em Next. Na tela seguinte, será mostrado a licença do plugin. Caso concorde com ele, clique na opção I accept the terms of the licence agreement e depois em Finish.

Por fim, será mostrada uma janela que diz que o conteúdo que está tentando baixar e instalar contém conteúdo não assinado digitalmente e que não é possível estabelecer a validade ou autenticidade do software. Aceite, mesmo assim, para que a instalação possa prosseguir clicando em Ok.

O Eclipse, mais uma vez, pedirá para ser reinicializado. Proceda com a reinicialização.

Ao reabrir o software, vá em Window > Preferences e escolha a opção General > Appearance > Color Theme. Uma tela como a de baixo se abrirá:


Veja que o plugin já vem com uma série de temas que você poderá escolher e aplicar, bastando para isso clicar no nome do tema e depois no botão Apply. No entanto, pode acontecer de você não gostar de nenhum dos temas apresentados. Para isso, você tem uma série de temas de colorização, disponíveis em http://www.eclipsecolorthemes.org/.

Nesse site você poderá escolher um tema que melhor se encaixe em suas preferências e poderá baixá-lo. Para usá-lo, basta clicar no botão Import a theme e apontar para o arquivo que você baixou e depois clicar no botão Apply para aplicá-lo ao seu Eclipse.

Muito fácil, não?

Veja só como ficou o código após a aplicação do tema Mr:


Não é uma mudança enorme mas entendo que ficou bem mais legível. 

Interface de Usuários - Criando Diálogos Parte 2

Adicionando botões

Para criar um AlertDialog com botões lado a lado como o mostrado na imagem ao lado, use o método set...Button():
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
       .setCancelable(false)
       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                MyActivity.this.finish();
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
           }
       });
AlertDialog alert = builder.create();
Primeiro, adicione uma mensagem para o diálogo com setMessage(CharSequence). Então continue o encadeamento de métodos e configure o diálogo para ser not cancelable (não cancelável, para que o usuário não possa fechar o diálogo pressionando o botão de voltar) com o método setCancelable(boolean). Para cada botão, use um dos métodos dentro de set...Button(), como setPositiveButton(), que aceita o nome para o botão e um DialogInterface.OnClickListener que define a ação a ser tomada quando o usuário seleciona o botão.

Nota: Você só pode adicionar um botão de cada tipo de um AlertDialog. Ou seja, não é possível ter mais que um botão do tipo positivo. Isso limita o número de botões possíveis a três: positivo, neutro ou negativo. Esses nomes são tecnicamente irrelevantes para a função dos botões, mas você deve manter um controle do que cada um deles faz.

Adicionando uma lista

Para criar um AlertDialog() com uma lista de itens selecionáveis como o mostrado na imagem seguinte, use o método setItems():

final CharSequence[] items = {"Red", "Green", "Blue"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("Pick a color");builder.setItems(items, new DialogInterface.OnClickListener() {    public void onClick(DialogInterface dialog, int item) {        Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();    }});AlertDialog alert = builder.create();
Primeiro, adicione um título ao diálogo com setTitle(CharSequence). Então, adicione os itens selecionáveis com setItems(), que aceita um array de itens a serem mostrados e um DialogInterface.OnClickListener que define a nação a ser tomada quando o usuário seleciona um item.

Adicionando checkboxes e radio buttons

Para criar uma lista de itens de multipla escolha (checkboxes) ou itens de escolha única (radio buttons) dentro de um diálogo, use o método setMultiChoiceItems() e setSingleChoiceItems(), respectivamente. Se você criar uma dessas listas selecionáveis no método callback onCreateDialog() , o Android gerencia o estado para você. Enquanto a atividade estiver ativa, o diálogo se lembrará das opções que foram selecionadas anteriormente, mas quando o usuário sair da atividade, a seleção será perdida.

Nota: Para salvar uma seleção quando um usuário sair da atividade ou pausá-la, você deve salvar e restaurar as configurações através do ciclo de vida da atividade. Para permanentemente salvar a seleção, mesmo que o processo da atividade corrente tenha sido encerrado por completo, você precisará fazê-lo em algum tipo de banco de dados, usando técnicas de Data Storage.

Para criar um AlertDialog com uma lista de itens de escolha única, use o código abaixo para isso:

final CharSequence[] items = {"Red", "Green", "Blue"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Pick a color");
builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int item) {
        Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
    }
});
AlertDialog alert = builder.create();
Criando um ProgressDialog

Um ProgressDialog é uma extensão de AlertDialog que pode mostrar uma animação de progresso na forma de um círculo giratório, quando uma tarefa tem o progresso onde não se pode definir o término dele, ou uma barra de progresso, para uma tarefa com progresso definido. O diálogo pode também prover botões, como um botão de cancelar download, pode exemplo.

Abrir um diálogo de progresso é tão simples quanto chamar ProgressDialog.show(). Por exemplo, o diálogo de progresso mostrado na imagem ao lado pode ser facilmente alcançada sem ter de se gerenciar o diálogo através de onCreateDialog(int), como mostrado abaixo:

ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "",
                        "Loading. Please wait...", true);

O primeiro parâmetro é o contexto da aplicação, o segundo é o título para o diálogo (que foi deixado em branco), o terceiro a mensagem em si e o último parâmetro é se o progresso é inteterminado ou não.

O valor padrão para o diálogo de progresso é o da imagem acima, com o círculo giratório. Se você quer criar uma barra de progresso que mostre o progresso à medida que vai sendo realizada a tarefa, mais código é necessário, como mostrado na próxima seção.

Mostrando um progress bar.

Para mostrar uma progressão com uma barra de progressão animada:


  1. Inicialize o ProgressDialog com um construtor de classe, ProgressDialog(Context).
  2. Configure o estilo da progressão como "STYLE_HORIZONTAL" com setProgressStyle(int) e configure outros aspectos, como a mensagem.
  3. Quando estiver pronto para mostrar o diálogo, chame show() e retorne o ProgressDialog para o onCreateDialog(int).
  4. Você pode incrementar o progresso a ser mostrado na barra chamando ou setProgress(int) com o valor do percentual completado até então ou incrementeProgressBy(int) com um valor para o total de percentual a ser avançado na barra.
Um exemplo seria:
ProgressDialog progressDialog;
progressDialog = new ProgressDialog(mContext);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
Criando um diálogo customizado

Se você quer um diálogo com design customizado, você pode criar seu próprio layout para a janela de diálogo com layout e elementos widget internos a este. Após você ter definido o layout, passe o objeto View root ou o ID do recurso de layout para setContentView(View).

Por exemplo, para se criar o diálogo ao lado:

1) Crie um layout XML e salve-o como custom_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/layout_root"
              android:orientation="horizontal"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:padding="10dp"
              >
    <ImageView android:id="@+id/image"
               android:layout_width="wrap_content"
               android:layout_height="fill_parent"
               android:layout_marginRight="10dp"
               />
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:textColor="#FFF"
              />
</LinearLayout>


2) Configure o layout acima como a view de conteúdo para o diálogo e defina o conteúdo para o ImageView e o elemento TextView.

Context mContext = getApplicationContext();
Dialog dialog = new Dialog(mContext);
 
dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Custom Dialog");
 
TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
3) É isso.






Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
Related Posts Plugin for WordPress, Blogger...