SlideShare une entreprise Scribd logo
1  sur  64
Começando a Criar Interfaces
              Gráficas com Android

   • Introdução

       O estudo para criar este artigo foi feito em várias fontes, mas uma
chamou a atenção por teu uma seqüência de exemplos muito bem
explicados e de fácil entendimento. O texto se chama “Understanding User
Interface in Android”.
      Neste artigo vamos aprender como criar interfaces gráficas (UI) mais
básicas com Android, utilizando o Eclipse como IDE de desenvolvimento.
Pretendo criar outros artigos falando sobre componentes mais complexos
ou se aprofundando nos apresentados aqui.
       Para quem está chegando de mundos um pouco mais obscuros em
relação à UI, como o Java ME, a diferença é gritante e impressiona. Com
Android temos gerenciadores de layout sofisticados, componentes
estilizados com efeitos atrativos graficamente, além de uma facilidade no
desenvolvimento.


        Obs: O Java ME ganhou muito poder UI quando ganhou o
 framework LWUIT, permitindo uso de componentes e
 gerenciadores de layouts. Mas quem programou com Java ME
 pré-LWUIT sabe das dificuldades de criar uma tela amigável
 com Canvas. Existem algumas plataformas, como a da RIM
 (responsável pelos aparelhos BlackBerry) que redefiniu o Java
 ME para suas necessidades. Nestes aparelhos, também é possível
 criar telas atraentes para o usuário.
       O Android oferece dois modos de criar interfaces gráficas, uma é
definindo um arquivo XML que será carregado no startup da aplicação e a
renderização da tela é construída em tempo de execução. O outro modo é
através da codificação pura. Na maioria dos casos o desenvolvedor usará as
duas maneiras, porém, recomenda-se a preferência pelo uso do XML.
       Como vimos nos outros publicados por mim no Java Móvel, um
aplicativo Android terá uma Activity, que é responsável pela interface
gráfico da aplicação. Na verdade, ela pode ser imaginada como uma tela do
seu software.
Obs: A Activity utiliza uma pilha, chamada de activity stack, o
 índice que estiver no topo da pilha será a tela exibida para o usuário
 da aplicação. Para quem programa para BlackBerry OS verá grandes
 similaridades com a pilha de Screens desta plataforma.


     Como dissemos anteriormente, existem dois modos de criação de UI
no Android, aqui vamos nos deter principalmente no XML. Então, veja o
exemplo abaixo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/nome"
        />
</LinearLayout>




      O XML acima representa a interface gráfica, contendo um campo de
texto em um layout linear, orientado verticalmente. A aplicação deve
possuir no mínimo uma classe que herde de Activity e sobrecarregue o
método onCreate:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }


      Perceba que definidos a interface através de um arquivo XML,
usando o método setContentView. O R representa a classe com as
constantes que identificam os recursos da nossa aplicação.
      Ao longo deste artigo vamos ver em detalhes o pouco que fizemos
até aqui, vamos a luta.


   • View e ViewGroup
Quando pensamos em interface gráfica de um aplicativo Android
devemos ter em mente oque significa View e ViewGroup. Ambos
representam qualquer componente visual que você visualizar na tela do
aparelho.
       Como estas classes são de suma importância para o entendimento do
texto no geral, vou parafrasear o site oficial de desenvolvedores Android:
       A classe View representa o bloco de construção básico para
componentes de interface gráfica. Uma View ocupa uma área retangular na
tela e é responsável por desenhar e controlar os eventos. View é a classe
básica para widgets, que são usados para criar componenets de UI
interativos (botões, caixas de texto, etc.). A subclasse ViewGroup é a classe
base para layouts, que são containers invisíveis que contém Views (ou
outros ViewGroups) e definem as propriedades desse layout. Veja a Figura
1 para um melhor entendimento.




                          Figura 1: Views e Views Group.


      Para fazer com que o leitor entenda definitivamente à importância
dessas duas classes, veja a Figura 2:
      Na interface existe um vasto conjunto de widgets, desde botões até
caixas de seleções. Todos esses componentes estão dentro de um
gerenciador de layout, mais precisamente em um LinearLayout.
Figura 2: Exemplo real de Views e Views Group.




  • Gerenciadores de Layout

       Vamos começar a brincadeira com UI no Android com os
gerenciadores de layout. Como o próprio nome indica, estas classes
orientam o posicionamento dos widgets na tela. Dependendo do layout
utilizado, até a altura e largura do componente é alterada.
      Para quem trabalhou com o swing do Java lembra do BorderLayout,
FlowLayout, dentre outros. Até mesmo no Java ME é possível utilizar
gerenciador parecidos com os mencionados anteriormente, através do
LWUIT.
      Inicialmente vamos criar uma aplicação Android que alteraremos
conforme o gerenciador de layout a ser estudado.


        o Criando o projeto
     Recapitulando dos nossos artigos anteriores. Siga o caminho file-
>new->Android Project. Configure as seguintes opções e clique em Ok:
•   Project Name: LayoutsAndroid.
•   Contents: Create new project in workspace.
•   Target Name: Android 2.1.
•   Application Name: Layouts Android
•   Package Name: com.estudo.android.
•   Create Activity: LayoutsAndroid




                  Figura 3: Configurações do projeto inicial.
O Eclipse já cria o projeto e toda a estrutura de pastas e códigos
necessária. Execute este projeto e verá o seguinte:




                       Figura 3: Projeto inicial emulado.


      Dê uma olhada também no arquivo main.xml, que pode ser
encontrado no caminho res->layout.

Listagem 1:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello" />
</LinearLayout>



      O nosso exemplo já usa um gerenciador de layout, o LinearLayout,
que, por acaso, será nosso primeiro objeto de estudo.
o LinearLayout
      Este gerenciador organiza seus componentes filhos em uma única
coluna ou única linha, dependendo da orientação que o mesmo tiver.
       Para ficar mais claro, vamos editar o arquivo main.xml citado
anteriormente:

Listagem 2:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
<EditText android:id="@+id/EditText01"
      android:layout_width="180px"
      android:layout_height="wrap_content" />
<EditText android:id="@+id/EditText02"
      android:layout_width="180px"
      android:layout_height="wrap_content" />
<Button android:id="@+id/Button01"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Enviar" />
</LinearLayout>


      Se executarmos a aplicação agora, veja como fica:




                    Figura 4: Projeto alinhados verticalmente.
Vamos fazer algumas alterações no XML para compreender oque ele
faz. Na declaração do layout, que sempre deve ser o nó raiz do documento,
temos o LinearLayout. Definimos para este componente três propriedades:
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"


      A orientation defina se os componentes se desenrolarão no sentido
horizontal ou vertical. Se a tela terá apenas uma linha ou uma coluna, como
falado anteriormente. Mudemos essa propriedade para:
android:orientation="horizontal"


      O resultado podemos ver abaixo:




      Também definimos as propriedades de largura (width) e altura
(height). Ambos usam fill_parent, que diz o seguinte: use todo o espaço
disponível na tela. Vamos mudar novamente o main.xml, mais
especificamente as propriedades do LinearLayout.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="100px"
      android:layout_height="100px">



      O resultado é:




       Perceba que o restante dos componentes foi cortado, por exceder os
limites do seu container, o LinearLayout. Na prática, porém, vai ser raro as
vezes em que este gerenciador de layout não vai ocupar todo o espaço
disponível na tela.
      Existem alguns atributos específicos para componentes que fazem
todo sentido quando aplicados no LinearLayout. Vamos trabalhar com duas
propriedades: android:layout_weight e android:layout_gravity.
      Reescreva o main.xml:

LISTAGEM 3:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
<EditText android:id="@+id/EditText01"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_weight="0.3" />
<EditText android:id="@+id/EditText02"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_weight="0.7" />
<Button android:id="@+id/Button01"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Enviar"
      android:layout_gravity="right" />
</LinearLayout>



      Depois de executar veremos o seguinte:
Figura 7: Utilizando gravity e weight.


      A propriedade gravity funciona como uma função de alinhamento
em relação ao container, como usamos right no botão, veja que ele se
encontra na extremidade direita da tela.
      O weight repassa para os componentes o espaço não utilizado na tela.
Há, não se preocupem com os componentes, eles serão tratados daqui a
pouco. Volte para a figura 4 e perceba que o espaço “vazio” desapareceu,
sendo atribuído para as duas caixas de textos que definiram a propriedade
weight. Perceba também, que a segunda caixa de texto recebeu 70% do
espaço não utilizado, por isso ficou maior que a primeira caixa.
      Bem, encerramos por aqui a discussão sobre a LinearLayout. Há, não
se preocupe com os widgets (componentes). Logo veremos detalhadamente
cada um.


         o   AbsoluteLayout
      Este gerenciador define exatamente a posição (coordenada x/y) onde
cada componente deve ficar. Este layout é menos flexível e também exige
um maior trabalho para manutenção. Por exemplo, quando o aparelho
muda a orientação, quem deve redefinir a posição dos componentes é o
programador, via código.
Mas chega de conversa, redefina o main.xml para isso:
LISTAGEM 4:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" >
<EditText android:id="@+id/EditText01"
      android:layout_width="190px"
      android:layout_height="wrap_content"
      android:layout_x="12px"
      android:layout_y="12px" />
<EditText android:id="@+id/EditText02"
      android:layout_width="190px"
      android:layout_height="wrap_content"
      android:layout_x="12px"
      android:layout_y="60px" />
<Button android:id="@+id/Button01"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Enviar"
      android:layout_x="12px"
      android:layout_y="161px" />
</AbsoluteLayout>



     Quando executamos a nossa aplicação fica com a seguinte cara:




                      Figura 8: Utilizando AbsoluteLayout.


      Simples né? Mas como o leitor já deve ter percebido, na é um
gerenciador de layout muito aconselhado.
o TableLayout

      Este gerenciador pode ser o mais auto-descritivo de todos. Para
surpresa geral, ele organiza seus componentes filhos em linhas e colunas.
       As linhas da tabela são representadas pela classe TableRow. As
colunas são criadas conforme a inserção de componentes em uma mesma
linha. Não é permitido bordas em linhas, colunas e células.
      Reescreva o main.xml:

LISTAGEM 5:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" >
      <TableRow>
            <TextView
                  android:text="Nome"
                  android:layout_width="100px" />
            <EditText android:id="@+id/EditText01"
                  android:layout_width="200px" />
      </TableRow>
      <TableRow>
            <TextView android:text="Endereço"/>
            <EditText android:id="@+id/EditText02" />
      </TableRow>
      <TableRow>
            <TextView />
            <Button android:id="@+id/Button01"
                  android:text="Enviar" />
      </TableRow>
</TableLayout>



      Para gerar uma interface como a Figura 9:




                        Figura 8: Utilizando TableLayout.
Vários pontos devem ser detalhados aqui. Primeiramente, veja que
definimos a largura dos componentes somente para a primeira linha. Isso
porque a coluna define sua largura como igual a largura do maior
componente horizontal. Assim, se redefinirmos a última caixa de texto e o
botão para:

<TableRow>
            <TextView android:text="Endereço"/>
            <EditText android:id="@+id/EditText02"
                  android:layout_width="100px"/>
      </TableRow>
      <TableRow>
            <TextView />
            <Button android:id="@+id/Button01"
                  android:text="Enviar"
                  android:layout_width="50px" />
</TableRow>



      O resultado da interface vai ser o mesmo. Tanto o campo de texto de
endereço como o botão tem largura menor que a primeira caixa de texto.
      Na última linha colocamos um campo de texto vazio:

      <TextView />


      Isso deve ser feito para que não ocorra o seguinte efeito:




                 Figura 8: Utilizando TableLayout com espaço a mais.




         o RelativeLayout

      O RelativeLayout trabalha da seguinte forma. Cada componente filho
deve indicar sua posição em relação a outro componente.
Vamos começar nossos estudos com este main.xml.
LISTAGEM 6:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/RLayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <TextView
        android:id="@+id/lblComments"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Idéias"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        />
    <EditText
        android:id="@+id/txtComments"
        android:layout_width="fill_parent"
        android:layout_height="170px"
        android:textSize="18sp"
        android:layout_alignLeft="@+id/lblComments"
        android:layout_below="@+id/lblComments"
        android:layout_centerHorizontal="true"
        />
    <Button
        android:id="@+id/btnSave"
        android:layout_width="125px"
        android:layout_height="wrap_content"
        android:text="Salvar"
        android:layout_below="@+id/txtComments"
        android:layout_alignRight="@+id/txtComments"
        />
    <Button
        android:id="@+id/btnCancel"
        android:layout_width="124px"
        android:layout_height="wrap_content"
        android:text="Lixeira"
        android:layout_below="@+id/txtComments"
        android:layout_alignLeft="@+id/txtComments"
        />
</RelativeLayout>


      O primeiro componente, um texto estático, está orientado em relação
ao sei pai, ou seja, ao próprio layout. Então, definimos que ele estará a
esquerda e ao topo da tela.

      android:layout_alignParentTop="true"
      android:layout_alignParentLeft="true"


      Antes de prosseguir, veja como fica esta interface em trabalho.
Figura 9: Utilizando RelativeLayout.


      A caixa de texto tem sua localização definida com:

      android:layout_alignLeft="@+id/lblComments"
      android:layout_below="@+id/lblComments"


       O layout_alignLeft diz que o componente estará alinhado a esquerda
do componente com o id lblCmments, que neste caso, é o texto estático
“Idéias”. Também, usamos o layout_below para dizer que este componente
estará logo abaixo do mesmo componente de texto lblComments.
      O botão de lixeira define sua localização com;

      android:layout_below="@+id/txtComments"
      android:layout_alignLeft="@+id/txtComments"


      Exatamente da forma como definimos nossa caixa de texto, exceto
pela mudança do componente referenciado. Agora indicamos o
txtComments como ponto de referência.
      Finalmente, temos o botão salvar:

      android:layout_below="@+id/txtComments"
      android:layout_alignRight="@+id/txtComments"


      A única mudança é de alignLeft para alignRight.
O desenvolver tem acesso as seguinte propriedades para definir o
posicionamento dos componentes no RelativeLayout:
     * layout_above
     * layout_alignBaseline
     * layout_alignBottom
     * layout_alignLeft
     * layout_alignParentBottom
     * layout_alignParentLleft
     * layout_alignParentRight
     * layout_alignParentTop
     * layout_alignRight
     * layout_alignTop
     * layout_Below
     * layout_centerHorizontal
     * layout_centerInParent
     * layout_centerVertical
     * layout_leftOf
     * layout_rightOf
     * layout_true


         o   FrameLayout

      O FrameLayout reserva um espaço na tela que deve ser utilizado por
uma View. Se mais de uma View for colocada nesta área, haverá
sobreposição de componentes, com o último que foi inserido aparecendo
por primeiro.
     Vamos a codificação. Altere main.xml:

LISTAGEM 7:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout android:id="@+id/AbsoluteLayout01"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      xmlns:android="http://schemas.android.com/apk/res/android">
      <FrameLayout
            android:layout_x="88dip"
            android:id="@+id/FrameLayout01"
android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_y="104dip">
            <TimePicker android:id="@+id/TimePicker01"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content">
            </TimePicker>
      </FrameLayout>
</AbsoluteLayout>



       Neste XML, apenas o TmePicker pode parecer estranho, mas ele é
somente um widget para escolher uma hora do dia. Veja visualmente como
fica a execução da aplicação com este XML:




                      Figura 10: Utilizando FrameLayout.


      Estamos usando o FrameLayout dentro de um AbsoluteLayout, logo,
devemos especificar sua posição em coordenadas x, y. O FrameLayout
possui apenas uma widget, o TimePicker.
     Até aqui parece que não veremos nada de diferente nesse layout. Mas
vamos tentar adicionar mais um componente no XML:

<FrameLayout
            android:layout_x="88dip"
            android:id="@+id/FrameLayout01"
android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_y="104dip">
            <TimePicker android:id="@+id/TimePicker01"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content">
            </TimePicker>
            <Button android:text="Botão"
                  android:id="@+id/Button01"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"/>
</FrameLayout>



     Agora iniciamos a aplicação e veremos isto:




     Perceba que o botão sobrepôs o TimePicker. Isso acontece porque o
FrameLayout mostra apenas uma View.


         o ScrollView

       Agora fiquei em dúvida entre qual dos layout é o mais auto-
descritivo: TableLayout ou ScrollView. Este último, mostra apenas uma
ViewGroup que pode exceder os limites da tela física do aparelho.
Geralmente o ViewGroup utilizado é um LinearLayout.
      Falta pouco, vamos editar pela última vez o main.xml neste tópico de
layouts.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    android:id="@+id/widget54"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <LinearLayout
        android:layout_width="310px"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
        <Button android:text="Brasil"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="França"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Argentina"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Uruguai"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="México"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Paraguai"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Chile"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Colômbia"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Alemanha"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Estados Unidos"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Inglaterra"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
        <Button android:text="Escócia"
            android:layout_width="110px"
            android:layout_height="wrap_content" />
    </LinearLayout>
</ScrollView>
Este layout não tem mistério, o leitor já deve até estar visualizando
mentalmente como ficará a execução do aplicação desta vez. Veja na
Figura abaixo:




      Veja a barra no lado direito. Fácil esse scroll view hein.
• Views

      Depois que aprendemos sobre os gerenciadores de layout,
representados pelos ViewsGroups, está na hora de aprender sobre s os
componentes, representados pelas classes que herdam de View.
       Para melhor compreensão, vamos dividir este tópico em cinco áreas:
   •   Views básicas: para criar componentes básicos, como caixa de textos
       e botões;
   •   Pickers Views: componentes especiais que permitem o usuário
       selecionar de uma certa fonte;
   •   Views de listas: componentes que mostram uma lista de
       informações;
   • Views para imagens: componentes especializados para tratamento
     com imagens. Vocês irão se surpreender com estes componentes;
   • Menus;
   • Extras.


      Antes de iniciarmos este instigante tópico de estudo, vamos criar um
novo projeto no Eclipse, chamado ViewsAndroid. Como o leitor já sabe os
passos, só vou deixar a imagem com as configurações:
Agora vamos partir para a ação.


         o   BasicViews - Início

      As views básicas não precisam de muita explicação, o leitor já deve
ter usado elas intensamente em qualquer software. E, se o leitor for
programador, então já deve ter criado milhares destes componentes:
• TextView
   •     EditText
   •     Button
   •     ImageButton
   •     CheckBox
   •     ToggleButton
   •     RadioButton
   •     RadioGroup


     Vamos editar nosso main.xml do projeto recém criado. Reescreva-o
com as seguintes informações:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

       <TextView android:id="@+id/txtView"
           android:text="Cadastro"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" />
       <Button android:id="@+id/btnAbrir"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Abrir"
           />
       <ImageButton android:id="@+id/btnImg1"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:src="@drawable/icon"
           />
       <EditText android:id="@+id/txtName"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           />
       <CheckBox android:id="@+id/chkAutosave"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:text="Autosave"
           />
       <CheckBox android:id="@+id/star"
           style="?android:attr/starStyle"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           />

       <RadioGroup android:id="@+id/rdbSexo"
android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
        <RadioButton android:id="@+id/rdbM"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Masculino"
            />
        <RadioButton android:id="@+id/F"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Feminino"
            />
    </RadioGroup>

    <ToggleButton android:id="@+id/toggle1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>



     Rode este projeto e verás o seguinte resultado:




                         Figura 14: Exemplo de Views.


      O primeiro componente é um TextView, dispensando maiores
apresentações. O segundo componente é um Button, também é muito auto-
explicativo. O terceiro componente é um ImageButton, mesclando uma
imagem ao botão tradicional. Aqui podemos perceber um ponto
interessante na forma de programar do Android. Sempre devemos definir a
fonte da imagem, no nosso exemplo utilizamos:

      android:src="@drawable/icon"



       O leito deve estar lembrado que na classe Activity usamos a seguinte
linha de código:

      setContentView(R.layout.main);



       Ou seja, ambos referem-se aos recursos localizados na pasta res. A
diferença é que no primeiro caso acessamos estes recursos através do
XML, sendo assim devemos definir um ‘@’, a localização do recurso
(drawable, layout ou values) e o nome. No último caso acessamos o
recurso através do código Java. Sendo assim, você indica a classe R e, o
caminho referente ao recurso desejado.
     Seguindo com o exemplo da Figura 14. O quarto componente é um
campo de texto, representado pela classe EditView. O quinto componente é
um simples CheckBox. O sexto componente também é um CheckBox, mas
com uma especificidade. Redefinimos seu estilo, veja:

      style="?android:attr/starStyle"


     O sétimo e oitavo componente são instâncias de RadioButton, dentro
de um ButtonGroup. Finalmente, o último componente é um ToggleButton,
um botão estilizado com dois estados: on e off.
      Também podemos mudar os textos do ToggleButton. Adicione mais
duas propriedades ao último componente citado:

      android:textOn="Sim"
      android:textOff="Não"


      Agora o componente apresenta textos definidos pelo programador, e
não aqueles padrões, veja:
Outro componente que possui atributos importantes para serem
citados aqui, é o EditText. Em alguns casos, o programador adiciona um
campo de texto onde o usuário informa sua senha, sendo assim, o texto
deve ser substituído por asteriscos. Para atingir este objetivo, existe uma
propriedade que pode ser adicionada ao EditText:

<EditText android:id="@+id/txtName"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:password = "true"
        />



      Veja oque acontece:




         o BasicViews – Tratamento de Eventos

      Até agora só mostramos alguns componente na tela, mas não
inserimos nenhum tratamento de eventos. E como podemos fazer isso?
      No início deste artigo falamos rapidamente que a interface gráfica de
um aplicativo pode ser construída de duas maneiras: diretamente com o
XML ou codificando cada componente. Por exemplo, já usamos o
TextView no XML, porém, existe uma classe TextView que pode ser
instanciada e tratada diretamente via código.
Mesmo quando optamos por criar a interface via XML, que é mais
indicada inclusive pelo site de desenvolvedores do Android, vamos usar a
codificação pura em Java para tratar dos eventos.
     Vamos alterar a classe ViewsAndroid, localizada na pasta
com.estudo.android, em src:

Listagem 11:
1: package com.estudo.android;
2:
3: import android.app.Activity;
4: import android.os.Bundle;
5: import android.view.View;
6: import android.widget.CheckBox;
7: import android.widget.Toast;
8;
9: public class ViewsAndroid extends Activity {
10:    /** Called when the activity is first created. */
11:    @Override
12:    public void onCreate(Bundle savedInstanceState) {
13:        super.onCreate(savedInstanceState);
14:        setContentView(R.layout.main);
15:
16:        CheckBox checkBox=(CheckBox)
findViewById(R.id.chkAutosave);
17:        checkBox.setOnClickListener(new View.OnClickListener()
18:        {
19:            public void onClick(View v) {
20:               Toast.makeText(getBaseContext(),
                              "Salvar "+
(((CheckBox)v).isChecked()?"Aut.":"Man."),
                        Toast.LENGTH_SHORT).show();
21:            }
22:        });
23:
24:    }
25:}



       Não sei se vocês perceberam que em todos widgets (componentes)
criados até aqui, sempre definimos uma propriedade android:id. Essa
identificação é usada para recuperar este componente no código Java
através do método findViewById(), linha 16 da listagem de código 16 .
       Com posse da instância de CheckBox podemos configurar um
listener para o evento de clique, usando o método setOnClickListener e
passando por parâmetro uma instância de OnClickListener.
        Na Listagem de código isso é feito na linha 17. Perceba que
instanciamos a classe passada para o método da mesma linha. Quando
definimos o método OnClickLisener devemos redefinir o comportamento
do método onClick. Este, por sua vez, programa oque acontecerá quando o
comportamento receber o evento de clique.
Veja nas Figuras abaixo oque programos para o momento em que o
botão for selecionado como checado e não-checado. Inicialmente o
CheckBox está desativado, então, quando ele for selecionado mostramos
“Salvar Aut.”, caso inverso mostramos “Salvar Man.”.




      Figura 15: CheckBox ativado.         Figura 16: CheckBox desativado.




       Esse texto que aparece na tela é um Toast. Veja a linha de código 20
da Listagem 11. Usamos o método estático makeToast() que recebe os
seguintes parâmetros: um contexto, a mensagem e um inteiro que define a
duração. No temo usamos a constante LENGHT_SHORT.
     Para os componentes Button e ToogleButton também podemos usar o
OnClickListener.  Para    o     RadioButton     vamos    utilizar  o
OnCheckedChangeListener.
     Vamos fazer algumas alterações no exemplo anterior, assim, o
ChangeLisener será compreendida perfeitamente.
      A idéia é associar uma imagem com o campo de escolha do sexo.
Sendo assim, a primeira mudança é no main.xml, adicionando mais uma
propriedade ao botão de escolha do sexo masculino.

<RadioButton android:id="@+id/rdbM"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Masculino"
            android:checked="true"
/>



      Com isso, a opção de “Masculino” vai vir marcada como padrão.
       O primeiro passo é criar um widget ImageView na nossa tela.
Inicialmente ela mostrará uma imagem do sexo masculino:
</RadioGroup>
<ImageView android:id="@+id/imgSexo"
            android:src = "@drawable/menino"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
/>


      Ao rodar este aplicativo veremos o seguinte:




                   Figura 17: RadioButton masculino selecionado.


     As imagens que aparecerão são da internet, você por qualquer
imagem na sua pasta res/drawable e chama-las de menino e menina.
      Se o usuário escolher “Feminino” ainda não acontece nada. Eu disse
ainda, porque vamos mudar isso agora. Veja a Listagem de código 12:

Listagem 12:
1:public void onCreate(Bundle savedInstanceState) {
2:         ...
3:   RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rdbSexo);
4:   radioGroup.setOnCheckedChangeListener(new
OnCheckedChangeListener()
5:     {
6:         public void onCheckedChanged(RadioGroup group, int
checkedId) {
7:           RadioButton rdb = (RadioButton) findViewById(checkedId);
8:           ImageView img = (ImageView) findViewById(R.id.imgSexo);
9:           if (rdb.getText().equals("Feminino")){
10:                img.setImageResource(R.drawable.menina);
11:          } else {
12:                img.setImageResource(R.drawable.menino);
13:          }
14:      }
15: });
16:}


       Na linha 4 adicionamos o OnCheckedChangeListener ao
componente RadioGroup. Assim, quando um dos RadioButton´s for
selecionado o método onCheckedChanged(), na linha 6, será notificado. Os
parâmetros que este método recebe são: o RadioGroup que recebeu a
iteração e o identificador único do RadioButton que foi marcado como
checado.
       Na linha 7 recuperamos o objeto RadioButton através do id recebido
como parâmetro. Na linha 8 recuperamos o objeto ImageView da forma já
conhecida, ou seja, referenciando o componente através das constantes da
classe R.
      Na linha 9 testamos se o texto do RadioButton selecionado é igual a
“Feminino”. Caso afirmativo, devemos configurar a fonte do ImageView
para a imagem da menininha. E é isso que fizemos na linha 11. Caso o teste
booleano resulte em false, a imagem mostrada deve ser do menino (como já
foi mostrado na Figura 17).
      Agora podemos executar o aplicativo novamente e marcar a caixa de
seleção “Feminino”. Veremos algo semelhante ao mostrado na Figura 18:




                   Figura 18: RadioButton masculino selecionado.


         o BasicViews – Barra de Progresso

       A barra de progresso é um componente muito comum em qualquer
interface de usuário. Seus exemplos de uso podem ser: acompanhar quantos
bytes foram transmitidos quando envia seu relatório para seu chefe,
acompanhar um processamento um pouco mais pesado e não pensar que a
aplicação deu erro e está travada, dentre outros.
      Vamos criar uma nova tela para vermos o comportamento desse
widget. Crie um novo arquivo .xml em res/layout, chamado
barradeprogresso.xml. Veja como na Figura 19:
Figura 19: Criando o barradeprogresso.xml.


     Edite o barradeprogresso.xml com o código da Listagem 13:

Listagem 13:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ProgressBar android:id="@+id/progressbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button android:id="@+id/btnEnviar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Enviar" />
</LinearLayout>
Mude também a classe ViewsAndroid (Listagem 14).

Listagem 14:
package com.estudo.android;

import android.app.Activity;
import android.os.Bundle;

public class ViewsAndroid extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.barradeprogresso);
    }
}



      Depois de executar o aplicativo temos:




       Essa é a forma mais básica da barra de progresso do Android, dê uma
olhada nas propriedades e verá que não acrescentamos nada de novo ao que
já vínhamos utilizando. O modo que estamos usando este componente é
padrozinado, seu ciclo é indeterminado. Útil para operações que não temos
idéia de quando serão finalizadas.
      No código acima a barra de progresso (que mais parece um círculo
de progresso) vai ficar na tela infinitamente. Vamos adicionar o código da
Listagem 15 no onCreate:

Listagem 15:
1:progressBar = (ProgressBar) findViewById(R.id.progressbar);
2:
3:new Thread(new Runnable() {
4:    public void run() {
5:          while (progressStatus < 10) {
6:                progressStatus++;// = doSomeWork();
7:                try {
9:                      Thread.sleep(500);
10:               } catch (InterruptedException e) {
11:                     e.printStackTrace();
12:               }
13:         }
14:
15:         progressBar.setVisibility(8);
16:   }
17:}).start();



       A Listagem 15 recupera o objeto PorgressBar logo na primeira
linha. Posteriormente, adicionamos uma rotina com código Java puro, que
apenas roda uma Thread enquanto a variável progressStatus for menor que
10. Depois disse ele muda a visibilidade do ProgressBar, para 8.
     Execute o aplicativo, espere alguns segundos e...




     Como assim? Que erro é esse?
     Substitua a linha 15 pelo conjunto de linhas de código abaixo:

handler.post(new Runnable() {
      public void run() {
            progressBar.setVisibility(8);
      }
});
O erro aconteceu porque dentro de uma Thread, não é possível lançar
outra linha de execução. O Handler permite que isso acontece trabalhando
diretamente com o sistema operacional. Depois da correção você pode
reiniciar a aplicação e esperar alguns segundos que o ProgressBar
desaparecerá da tela.




      Mas ainda ficou uma questão em aberto. Reveja a linha de código:

      progressBar.setVisibility(8);



      Afinal, oque significa o parâmetro 8. O ProgressBar pode ter três
estados possível, identificados por números inteiros:


   • 0 – visível
   • 4 – invisível
   • 8 – finalizado


      Por exemplo, se mudarmos a linha do setVisibly para:

      progressBar.setVisibility(4);



      Depois do mesmo intervalo de tempo veríamos:
Mas ainda não acabamos a discussão sobre o ProgressBar. Outra
propriedade interessante é a possibilidade de mudar o estilo do widget. O
primeiro passo é redefinir o widget em nosso xml:

<ProgressBar android:id="@+id/progressbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="50" />



      Fizemos duas coisas. O atributo style define o estilo do componente.
O android:max define o valor máximo da barra de progresso (que agora
sim terá um formato de barra de progresso).
        Na classe ViewsAndroid redefina o bloco de código dentro do while
para:

while (progressStatus < 50) {
      progressStatus++;

        handler.post(new Runnable() {
              public void run() {
                    progressBar.setProgress(progressStatus);
              }
        });

        try {
              Thread.sleep(100);
        } catch (InterruptedException e) {
              e.printStackTrace();
        }
}

       Perceba que implementamos o método setProgress dentro do laço,
ou seja, a cada iteração a barra de progresso aumenta sua área completada.
Depois chegar aos 50 (seu valor máximo) ela ainda deverá sumir, portanto,
o restando do código permanece igual.
        Execute novamente o aplicativo e recebera:
o BasicViews – AutoCompleteTextView

       O AutoCompleteTextView é filho de TextView, sendo assim, ele traz
um campo para inserção de texto. Seu diferencial é a possibilidade de
definir um conjunto de Strings que funcionam como auto complemento do
texto que está sendo digitado pelo usuário.
     Reescreva o barradeprogresso.xml com o código da Listagem 16:

Listagem 16:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <AutoCompleteTextView android:id="@+id/txtEstadios"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />
</LinearLayout>


       Até este momento apenas criamos o campo de texto. Se olharmos o
aplicativo nesse momento a interface conterá apenas uma caixa de exto
normal, sem complemento de código nenhum.
      Agora vamos editar também o ViewsAndroid com o texto da
Listagem 17:

Listagem 17:
package com.estudo.android;

import   android.app.Activity;
import   android.os.Bundle;
import   android.widget.ArrayAdapter;
import   android.widget.AutoCompleteTextView;

public class ViewsAndroid extends Activity {
1:
2:    String[] estadios = { "Soccer City", "Ellis Park",
                  "Moses Mabhida", "Peter Mokaba", "Mbombela Stadium",
                  "Loftus Versfeld", "Royal Bafokeng", "Free State",
                  "Green Point", "Nelson Mandela Bay" };

     /** Called when the activity is first created. */
     @Override
3:   public void onCreate(Bundle savedInstanceState) {
4:         super.onCreate(savedInstanceState);
5:         setContentView(R.layout.barradeprogresso);
6:
7:          ArrayAdapter<String> adapter = new
ArrayAdapter<String>(this, android.R.layout.
simple_dropdown_item_1line, estadios);

8:          AutoCompleteTextView textView = (AutoCompleteTextView)
findViewById(R.id.txtEstadios);
9:          textView.setThreshold(3);
10:         textView.setAdapter(adapter);
11:   }
12:}



      Vamos examinar o código a partir da linha 8. Neste ponto criamos a
instãncia de AutoCompleteTextView. Na linha 9 usamos o método
setThreshold para definir que depois da terceira letra o complemento já
pode trabalhar e, finalmente, na linha 10 adicionamos o ArrayAdapter ao
componente, este, definirá os textos que podem ser usados no
complemento.
      O ArrayAdapter, por sua vez, é criado na linha 7. O construtor usado
recebe um contexto, que pode ser this. Recebe também um segundo
parâmetro inteiro, que define seu comportamento. O último parâmetro
recebe um vetor de Objects com as Strings para complemento.
      Agora podemos executar a aplicação novamente.




     Perceba que depois que digito a terceira letra, o ‘e’,ele me traz as
opções cadastradas no ArrayAdapter.


         o   PickerViews

     Estetipo de widget permite que o usuário selecione uma data ou hora
de um componente estilizado e atraente visualmente.
      Vamos criar uma nova interface que pede o nome do usuário, a data
e hora do nascimento e calcula quantos dias faltam para tira a carteira de
habilitação, ou, quantos dias faltam para a aposentadoria (pensando em 65
anos). Se o usuário tiver mais que 65 anos, mostramos quantas copas o
usuário já assistiu.
      Crie um novo arquivo XML chamado datahora.xml:

Listagem 18:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <EditText android:id="@+id/txtNome"
      android:layout_width="200px"
      android:layout_height="wrap_content" />
    <TimePicker android:id="@+id/pckHora"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <DatePicker android:id="@+id/pckData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button android:id="@+id/btnCalcular"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Calcular" />
</LinearLayout>



      No XML da Listagem 18 os únicos dois componentes que se
destacam por serem novos são o DatePicker e o TimePicker. As
propriedades de ambos já são bem conhecidas do leitor.
      Também altere a classe ViewsAndroid usando o código da Listagem
19:

Listagem 19:
package com.estudo.android;

import java.util.Calendar;
import java.util.Date;

import   android.app.Activity;
import   android.os.Bundle;
import   android.view.View;
import   android.widget.Button;
import   android.widget.DatePicker;
import   android.widget.EditText;
import   android.widget.TimePicker;
import   android.widget.Toast;

public class ViewsAndroid extends Activity {

      private static final String CATEGORIA = "data e hora";
/** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.datahora);
     }
}



     Ao executarmos este aplicativo veremos:




               Figura 26: Aplicativo usando DatePicker e TimePicker.


       Nossa aplicação ainda não fará nada se clicarmos no botão
“Calcular”. Para conseguir isso vamos adicionar o trecho de código da
Listagem 20 depois da linha do setContentView no método onCreate.

1:Button botao = (Button) findViewById(R.id.btnCalcular);
2;botao.setOnClickListener(new View.OnClickListener(){
3:    public void onClick(View v){
4:          TimePicker hora = (TimePicker) findViewById(R.id.pckHora);
5:          DatePicker data = (DatePicker) findViewById(R.id.pckData);
6:          EditText edtNome = (EditText) findViewById(R.id.txtNome);
7;
8:          Calendar calNasc = Calendar.getInstance();
9:          calNasc.set(Calendar.YEAR, data.getYear());
10:         calNasc.set(Calendar.MONTH, data.getMonth());
11:         calNasc.set(Calendar.DAY_OF_MONTH, data.getDayOfMonth());
12:         calNasc.set(Calendar.HOUR_OF_DAY, hora.getCurrentHour());
13:         calNasc.set(Calendar.MINUTE, hora.getCurrentMinute());
14:
15:         Calendar calHoje = Calendar.getInstance();
16:         calHoje.setTime(new Date());
17:
18:         int tempo = calHoje.compareTo(calNasc);
19:
20:         if (tempo > 0){
21:               calculaData(calNasc, calHoje,
edtNome.getText().toString());
22:         }
23:   }
24:});



       Nas duas primeiras linhas configuramos o listener para o
componente Button. Na linha 3 criamos o método que vai responder por
todas iterações.
     Nas linhas 4, 5 e 6 recuperamos os objetos para o TimePicker,
DatePicker e EditText.
      Na linha 8 criamos a instância de Calendar que armazena a data de
nascimento do usuário. Na seqüência de linhas de 9 até 11, configuro os
valores de ano, mês e data do calendário, utilizando os métodos da classe
DatePicker para recuperar os valores configurados pelo usuário.
      As linhas 12 e 13 configuram a hora do dia e o minuto do nascimento
do usuário, utilizando métodos da classe TimePicker. Perceba que não
tratamos o tempo, apenas incluímos estas linhas de código como
aprendizado, porém, pode ficar como um tema de casa para o leitor.
      Na linha 15 criamos uma nova instância de Calendar. Na linha 16
configuramos a data atual como valor para o objeto criado na linha anterior.
      Na linha 18 utilizamos o método compareTo da classe Calendar para
pegar um número inteiro com a diferença entre as duas datas comparadas.
Se o valor for maior que zero (teste realizado na linha 20), significa que o
usuário informou uma data do passado, caso contrário, a lógica do
programa não precisa ser concluída porque ninguém nasce no futuro, ainda.
      O leitor deve ter percebido que paramos no método calculaData,
onde passamos três parâmetros: data de nascimento do usuário, data atual e
nome do usuário.
      Veja na Listagem 21 o código do método calculaData:

Listagem 21:
public void calculaData(Calendar nascimento, Calendar agora, String
nome){
      int ano = agora.get(Calendar.YEAR);
      int mes = agora.get(Calendar.MONTH);
      int dia = agora.get(Calendar.DAY_OF_MONTH);

      int anoNasc = nascimento.get(Calendar.YEAR);
      int mesNasc = nascimento.get(Calendar.MONTH);
int diaNasc = nascimento.get(Calendar.DAY_OF_MONTH);

     int idade = ano - anoNasc;

     if(mes < mesNasc) {
           idade--;
     } else if (mes == mesNasc) {
           if(dia < diaNasc) {
                 idade--;
           }
     }

      String mensagem = "";
      if (idade < 18)
            mensagem = nome+ ", faltam "+(18 - idade)+" anos para tirar
a carteira!";
      else if (idade >= 18 && idade < 65)
            mensagem = "Calma "+nome+", faltam "+(65 - idade)+" anos
para você se aposentar";
      else
            mensagem = nome+ ", o senhor já assistiu "+(idade/4)+"
copas";

     Toast.makeText(getBaseContext(),
           mensagem, Toast.LENGTH_SHORT).show();
}


       O código da Listagem 21 não tem segredo, é apenas código Java.
Primeiramente calculamos a idade, conforme esse resultado configuramos a
mensagem do aviso. Finalmente, utilizamos o Toast (já discutido nesse
texto), para apresentar a mensagem ao usuário.
     Veja o resultado de um dos casos:
Figura 27: Caso de uso do aplicativo usando DatePicker e TimePicker.




       Não utilizamos muito o TimePicker, mas o aplicativo já mostrou uma
idéia do uso deste componente. Assim como os outros widgets do Android,
este é bem fácil de usa.
      O programador também pode usar os pickers um uma janela de
diálogo. Vamos fazer algumas alterações, primeiro, no datahora.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <TextView android:id="@+id/txtAlarme"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Alarme não configurado"/>
    <Button android:id="@+id/btnConfigurar"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Configurar" />
</LinearLayout>



      Realmente acho que não preciso explicar o XML. A nossa aplicação
vai mostrar uma caixa de texto e um botão. O objetivo é que ao interagir
com o botão, o usuário receba uma caixa de diálogo com um seletor de
hora para configurar seu despertador.
      Vamos alterar o conteúdo da classe ViewsAndroid. Veja a Listagem
23:

Listagem 23:
1:    private static final int TIME_DIALOG_ID = 0;
2:    private TextView lblAlarme;
3:
4:    /** Called when the activity is first created. */
5:    @Override
6:    public void onCreate(Bundle savedInstanceState) {
7:          super.onCreate(savedInstanceState);
8:          setContentView(R.layout.datahora);
9:          lblAlarme = (TextView) findViewById(R.id.txtAlarme);
10:         Button btn = (Button) findViewById(R.id.btnConfigurar);
11:         btn.setOnClickListener(new View.OnClickListener(){
12:               public void onClick(View v){
13:                     showDialog(TIME_DIALOG_ID);
14:               }
15:         });
16:
17:    }

18:    @Override
19:    protected Dialog onCreateDialog(int id)
20:    {
21:        switch (id) {
22:            case TIME_DIALOG_ID:
23:               TimePickerDialog td = new TimePickerDialog(
24:                     this, mTimeSetListener, 12, 00, false);
25:
26:               return td;
27:        }
28:        return null;
29:    }
30:
31:    private TimePickerDialog.OnTimeSetListener mTimeSetListener =
32:    new TimePickerDialog.OnTimeSetListener()
33:    {
34:        public void onTimeSet(TimePicker view, int hourOfDay, int
minuteOfHour)
35:        {
36:         lblAlarme.setText("Alarme configurado para " + hourOfDay +
":" + minuteOfHour);
37:        }
38:    };



       Na linha 9 recuperamos o objeto TextView, porque vamos editar seu
texto posteriormente. Na linha 10 recuperamos o objeto Button. Na linha 11
adicionamos um OnClickListener para o botão recém criado. Quando o
usuário clicar neste componente vamos abrir uma caixa de diálogo.
       Para q    ue o diálogo mostrado não seja o padrão do Android,
devemos sobrescrever o método onCreateDialog. Também por isso,
passamos o TIME_DILAOG_ID como parâmetro, para termos certeza de
interceptar somente nosso diálogo. Com isso, mensagens vindas
diretamente do Android continuarão a serem mostradas.
      Dentro do onCreatDialog verificamos se estamos recebendo a
mensagem do nosso próprio código. Caso afirmativo, instanciamos um
novo objeto TimePickerDialog (linha 23). Seu construtor recebe um
Context, um OnTimeSetListener, uma hora e um minuto inicial e, por fim,
um valor booleano dentificando se o componente trabalhará com 24 horas
ou, com horas AM e PM.
       Perceba que o OnTimeSetListener foi criado no mesmo código, na
linha 31, devemos obrigatoriamente implementar o método onTimeSet
(linha 34). Este último método é chamado sempre que a hora é configurada
no TimePickerDialog. Quando isso acontecer apenas mudamos o texto do
TextView.
      Veja em três passos a aplicação em funcionamento:
Figura 28: Tela inicial da   Figura 29: Diálogo aberto após   Figura 30: Depois de clicar em
         aplicação.                   clicar no botão.            “Set” mudamos o texto do
                                                                          TetView.




           o ListViews

     O ListView é um componente para mostrar uma grande lista de dados
com scroll.
      Este componente não precisa de muita explicação, porém, tem
algumas diferenças significativas com os exemplos que vimos até aqui.
Para explorar ao máximo este widget vamos criar uma lista com todos os
países da copa do mundo de 2010. Ao clicarmos em um dos nomes
mostramos a posição da seleção no ranking da FIFA.
      Primeiramente vamos criar um novo XML, listview.xml. Veja seu
conteúdo na Listagem 24:

Listagem 24:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ListView android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>


       Ainda não vimos nenhuma novidade, mas veja como ficará nossa
classe ViewsAndroid na Listagem 25:
Listagem 25:
1:public class ViewsAndroid extends ListActivity {
2:
3:     String[] paises = {
4:             "Africa do Sul",
5:             ...
6:             "Uruguai" };
7:
8:     int posicoes[] = new int[]{
9:           90, ..., 18 };
10:
11: public void onCreate(Bundle savedInstanceState)
12: {
13:         super.onCreate(savedInstanceState);
14:         setContentView(R.layout.listview);
15:
16:         setListAdapter(new ArrayAdapter<String>(this,
17:             android.R.layout.simple_list_item_1, paises));
18:     }
19:
20: public void onListItemClick(ListView parent, View v,
     int position, long id) {
21:     Toast.makeText(this, paises[position]+" está na
"+posicoes[position]+"° posição", Toast.LENGTH_SHORT).show();
22: }
23:}



       A primeira grande diferença já encontramos na linha 1, perceba que
não estendemos mais a classe de Activity, mas sim de ListActivity. O
interessante deste componente, é que ele já utiliza internamente uma
ListView.
       Na linha 3 criamos um vetor de String com todos os nomes dos
países participantes da copa do mundo. Como não iríamos colocar os 32
países aí, usamos as reticências. Na linha 8 é a vez de criar o vetor de
inteiros com as posições das seleções no ranking da FIFA.
       O ListActivity precisa que a classe configure seu ListAdapter, que
pode ser entendido como um adaptador que faz a ponte entre o vetor de
itens com a lista propriamente dita. Na Listagem estamos fazendo isso na
linha 16. Um de seus construtores (usados na nossa codificação) recebe um
Context, um inteiro que define o layout da lista e um vetor com os itens da
lista.
       Finalmente, implementamos o método onListItemChecked para tratar
das interações do usuário com a lista. Com o parâmetro position definimos
o país e sua colocação e apresentamos em um Toast.
      Veja na Figura abaixo o comportamento do aplicativo em execução:
Figura 31: Lista de países com interação no item Brasil.


      Nossa lista está configurado para escolha única, padrão do
componente. Mas poderíamos alterar isso, trabalhando com a sua
propriedade android:choiceMode, que permite o uso de três constantes:
none, singleChoice e multipleChoice.


         o SpinnerViews

     Este componente também objetiva mostrar uma grande quantidade
de dados em uma lista. Porém, ele mostra uma lista no estilo popup,
lembrando o ChoiceGroup estilo POPUP NO Java ME.
      Vamos trabalhar no mesmo exemplo criado acima mas mudando o
componente. Para começar, crie um arquivo chamado spinner.xml e edite-o
conforme a Listagem 26:

Listagem 26:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <Spinner
android:id="@+id/spinner1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>



      A classe ViewsAndroid também sofrerá algumas mudanças. A
primeira é na declaração da classe, que fica assim:

      public class ViewsAndroid extends Activity {



      No onCreate também teremos alterações. Veja a Listagem 27:

Listagem 27:
1: super.onCreate(savedInstanceState);
2: setContentView(R.layout.spinner);
3:
4: s1 = (Spinner) findViewById(R.id.spinner1);
5: ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
    android.R.layout.simple_spinner_item, paises);
6:
7: s1.setAdapter(adapter);
8: s1.setOnItemSelectedListener(new OnItemSelectedListener() {
9:    public void onItemSelected(AdapterView<?> arg0,
10:         View arg1, int arg2, long arg3) {
11:        int index = s1.getSelectedItemPosition();
12:        Toast.makeText(getBaseContext(), paises[index]+" ocupa a
"+posicoes[index]+"° no ranking da FIFA", Toast.LENGTH_SHORT).show();
13: }
14:
15: public void onNothingSelected(AdapterView<?> arg0) {}
16:});


       Na linha 4 recuperamos o objeto Spinner. Este componente também
trabalha com um adaptador, criado na linha 5, e configurado para o Spinner
na linha 7. Na linha 8 adicionamos o OnItemSelectedListener, e
implementamos seus dois métodos obrigatórios. No onItemSelected
recuperamos a posição do item selecionado no Spinner (linha 11) e depois
mostramos a mesma mensagem mostrada no exemplo anterior.
      Veja como ficou este aplicativo:




                  Figura 32: Tela inicial do aplicativo com Spinner.
Figura 33: Spinner mostrando seus itens.




          Figura 34: Tela depois de selecionarmos a Argentina no Spinner.




      Também podemos mudar a forma como a lista é mostrada ao
usuário. Altere a linha 5 da lista 27 para:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_spinner_dropdown_item, paises);



      Veja o resultado:




                     Figura 35: Spinner com layout modificado.


         o Gallery e ImageView

      A partir desse momento vamos ver componente que nos ajudam a
apresentar imagens ao usuário. Se o leitor deste texto estava começando se
apaixonar pelo Android, vai pedir a mão dele em casamento ao final deste
tópico.
     Como este tópico difere dos demais, vamos criar um novo aplicativo,
chamado ImagesInAndroid:
Figura 36: Criação do projeto ImagesInAndroid.


      Crie um arquivo XML chamado passo1.xml. Veja seu conteúdo na
Listagem 28:

Listagem 28:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <Gallery
        android:id="@+id/gallery1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
Também precisamos alterar a classe ImagesInAndroid. Como as
mudanças são várias, vamos por partes.
      Primeiramente veja o básico que já aprendemos sobre Android:

package com.estudos.android;


import …

public class ImagesInAndroid extends Activity
{

      @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.passo1);
      }
}

       Nenhuma novidade. O passo seguinte é separar algumas imagens e
joga-las dentro da patas res.drawable. Veja como fica a estrutura de
diretório na Figura 37:




                 Figura 37: Arquitetura atualizada com as imagens.


       Feito isso, cria-se um variável com um vetor de instâncias de
Integer. Veja abaixo como fica. Perceba que estamos referenciando a nossa
classe de recursos, R.
Integer[] imageIDs = {
            R.drawable.pic1,
            R.drawable.pic2,
            R.drawable.pic3,
            R.drawable.pic4,
            R.drawable.pic5,
            R.drawable.pic6
};


      Agora, vamos adicionar um evento de clique nas imagens do
Gallery. O código mostrado abaixo está dentro do método onCreate:

Gallery gallery = (Gallery) findViewById(R.id.gallery1);

gallery.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView parent, View v, int
position, long id) {
         Toast.makeText(getBaseContext(), "Selecionou" + (position +
1), Toast.LENGTH_SHORT).show();
      }
});

      Nesse código também não encontramos nada de novo em relação ao
que já vimos até aqui. Agora execute este arquivo e:




                          Figura 38: Usando Gallery.


      Cadê as imagens? As imagens não apareceram porque o Gallery
também precisa de um adaptador, semelhante ao que ocorre com o
ListView e o Spinner, vistos a pouco.
      Esse adaptador precisa ser criado, diferentemente do Spinner por
exemplo, que já tem uma implementação da BaseAdapter para ela
(SpinnerAdapter), ou do ListView, que possui o ListAdapter. Sendo assim,
vamos criar uma classe interna chamada ImageAdapter, veja na Listagem
32 seu código:

Listagem 33:
1:public class ImagesInAndroid extends Activity
2:{
3:    …
4:
5: public class ImageAdapter extends BaseAdapter {
6:        private Context context;
7:        private int itemBackground;
8:
9:        public ImageAdapter(Context c) {
10:            context = c;
11:        }
12:
13:        public int getCount() {
14:            return imageIDs.length;
15:        }
16:
17:        public Object getItem(int position) {
18:            return position;
19:        }
20:
21:        public long getItemId(int position) {
22:            return position;
23:        }
24:
25:        public View getView(int position, View convertView,
ViewGroup parent) { }
26:   }
27:}

       Veja que a classe ImageAdapter está dentro de ImagesInAndroid. Ela
herda diretamente de BaseAdapter, e, como a linguagem Java ensina,
existem alguns métodos que devem ser implementados ao herdar esta
classe, sendo eles:
   •   getCount (linha 13): retorna o número de componentes. No nosso
       caso retornamos o número de elementos no vetor imageIDs, que
       contém as imgens que serão mostradas no Gallery.
   •   getItem e getItemId (linhas 17 e 21 respectivamente): retornam o
       objeto e o identificador do elemento em uma determinada posição.
   •   getView (linha 25): retorna um objeto que herda de View que será
       mostrado em uma determinada posição do Gallery.


      Vimos que o getView retorna o objeto que será mostrado na galeria.
Aqui estamos trabalhando com ImageView, mas é importante sabe que o
método pode retornar qualquer classe que herda de View. Por exemplo,
poderíamos retornar instâncias de TextView. Veja como ficaria o método
getView:



public View getView(int position, View convertView, ViewGroup parent)
{
      TextView tv = new TextView(context);
      tv.setWidth(100);
tv.setText("Teste");
     return tv;
}


     E o resultado é:




                      Figura 39: Usando Gallery com TextView.


      Claro que este exemplo não tem nenhuma utilidade prática, mas
serve como prova de conceito.
      Voltando aquilo que realmente importa neste tópico, que é Gallery
com ImageView, devemos retornar uma instância desta última classe no
lugar do TextView no método getView.
     Vamos editar novamente o método:

public View getView(int position, View convertView, ViewGroup parent)
{
      ImageView imageView = new ImageView(context);
      imageView.setImageResource(imageIDs[position]);
      return imageView;
}



     E o resultado:




                      Figura 40: Usando Gallery com ImageView.
As imagens ainda estão com o seu tamanho natural, também é
possível perceber que elas tem um sombreamento mais claro nas
extremidades laterais, isso acontece porque é o estilo padrão do
componente.
      Vamos configurar algumas propriedades do ImageView para
melhorar o Gallery. Adicione mais estas duas linhas de código no corpo do
getView:

imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setLayoutParams(new Gallery.LayoutParams(150, 120));


      Estamos definindo o tamanho do componente na segunda linha e, na
primeira, configuramos o tipo de escala. Como resultado, a imagem vai
ocupar toda a área reservada pra ela (150 por 120 pixeis). Veja como fica
na Figura 41:




            Figura 41: Usando Gallery com ImageView e parâmetros de layout.


     Para finalizar com toque de ouro, vamos usar um estilo para
melhorar a apresentação das fotos.

public View getView(int position, View convertView, ViewGroup parent)
{
      ...
      ...

      ...

      imageView.setBackgroundResource( android.R.drawable.alert_light_
frame);
     return imageView;
}



      E o resultado disso:
Figura 42: Usando Gallery com ImageView e estilo.


      Mas acho que nossa aplicação ainda não está legal, no momento
quando clicamos em uma foto apenas mostramos na tela qual imagem foi
clicada:




                Figura 43: Resultado inicial de interação com imagens.


      Mas acho que podemos fazer melhor que isso. Vamos mostrar a
imagem selecionada na parte central da tela, em um componente
ImageView. Para conseguir nosso objetivo edite o passo1.xml e adicione o
seguinte trecho de código logo depois do Gallery.

<ImageView
        android:id="@+id/image1"
android:layout_width="320px"
          android:layout_height="250px" />


        Também altere o tratamento da interação do usuário com o Gallery,
veja:

gallery.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView parent,
            View v, int position, long id) {
         ImageView imageView = (ImageView) findViewById(R.id.image1);
         imageView.setImageResource(imageIDs[position]);
      }
});



        O resultado está na Figura 44:




             Figura 44: Interação com imagens configurando imagens no centro.


       Lembram-se que antes usamos o tipo de escala para definir o
comportamento da galeria de imagens na parte superior da tela, também
podemos usar agora na visualização da imagem. Adicione o seguinte
atributo ao ImageView no passo1.xml:




        android:scaleType="fitXY" />
Agora a imagem vai preencher toda a região reservada ao
ImageView. Veja na Figura 45:




          Figura 45: ImageView escalado para preencher região central da tela.


         o ImageSwitcher

     A troca de imagens que implementamos no exemplo anterior com
ImageView e Gallery também pode ser conseguida com este componente ,
e com uma vantagem, o ImageSwitcher permite configurar alguns efeitos
3D na troca das imagens.
      Este exemplo será construído encima do anterior. Sendo assim, edite
o arquivo passo1.xml conforme a Listagem 39:

Listagem 39:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ff000000" >
    <ImageSwitcher
        android:id="@+id/switcher1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true" />
    <Gallery
        android:id="@+id/gallery1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
</RelativeLayout>


      Também é preciso alterar a classe ImagesInAndroid. Siga a Listagem
40:
Listagem 40:
1:public class ImagesInAndroid extends Activity implements
               ViewFactory {
2:   private ImageSwitcher imageSwitcher;
3:
4:   Integer[] imageIDs = {};
5:
6:   @Override
7;   public void onCreate(Bundle savedInstanceState)
8:   {
9:      super.onCreate(savedInstanceState);
10:     setContentView(R.layout.passo1);
11:
12:         imageSwitcher = (ImageSwitcher) findViewById(R.id.switcher1);
13:         imageSwitcher.setFactory(this);
14:
15:        imageSwitcher.setInAnimation( AnimationUtils.loadAnimation(
this, android.R.anim.fade_in));
16:         imageSwitcher.setOutAnimation( AnimationUtils.loadAnimation(
this, android.R.anim.fade_out));
27:
18:         Gallery gallery = (Gallery) findViewById(R.id.gallery1);
19:         ...
20:         gallery.setOnItemClickListener(new OnItemClickListener() {
21:           public void onItemClick(AdapterView parent,
22:               View v, int position, long id) {
23:                  imageSwitcher.setImageResource(imageIDs[position]);
24:               }
25:           });
26:      }
27:
28:      public class ImageAdapter extends BaseAdapter
29:      {}
30:
31:      @Override
32:      public View makeView() {
33:        ImageView imageView = new ImageView(this);
34:         imageView.setBackgroundColor(0xFF000000);
35:         imageView.setScaleType(ImageView.ScaleType.FIT_XY);
36:         imageView.setLayoutParams(new
37:        ImageSwitcher.LayoutParams(
                         LayoutParams.FILL_PARENT,
                         LayoutParams.FILL_PARENT));
38:         return imageView;
39:    }
40:}
Vamos falar somente das alterações feitas na classe anterior. Perceba
que na linha 12 recuperamos o componente ImageSwitcher. Na linha 13
usamos o método setFactory para definir a fábrica usada para criar as duas
imagens que serão usadas para o componente fazer o flip.
       Este método recebe como parâmetro uma classe que implemente a
interface ViewFactory, implementada na mesma classe ImagesInAndroid,
veja a linha 1.
    Nas linhas 15 e3 16 configuramos os eventos que a imagem terá no
momento de entrada e de saída da tela do usuário.
      Também mudamos a tarefa a realizar quando o usuário clicar em
uma das imagens do Gallery. Neste momento indicamos ao ImageSwitcher
qual imagem ele deve apresentar na tela, ele próprio trata da renderização
dos efeitos configurados anteriormente.
      Por fim, vá até a linha 32 e veja que implementamos o método
makeView, obrigatório quando implementamos a ViewFactory. Estemétodo
criará a nova View que será adicionada no switcher. Aqui também
poderíamos passar qualquer componente que herde de View, como fizemos
com o TextView no exemplo do tópico anterior (Gallery e ImageView).
      Ao executar a aplicamos veremos:




                        Figura 46: Uso do ImageSwitcher.
Aparentemente não percebemos nenhuma diferença, a não ser pelo
fato da imagem ocupar a tela inteira. Porém, interaja com o Gallery para
ver os efeitos do ImageSwitcher.


         o GridView

      Para finalizar este artigo/tutorial/ vãos mostrar o GridView, que,
como o próprio nome indica permite que mostramos imagens em uma
grade de fotos.
     O passo1.xml fica da seguinte maneira:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="auto_fit"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:columnWidth="90dp"
    android:stretchMode="columnWidth"
    android:gravity="center"
/>



      No próprio XML configuramos algumas propriedades que são
próprias de qualquer grade, não só Android, como por exemplo:
android:layout_width,    android:layout_height, android:numColumns,
android:verticalSpacing,                    android:horizontalSpacing,
android:columnWidth.


       O ImagesInAndroid sofre mudanças, mas o leitor irá tirar de letra
este código a esta altura do campeonato. Veja a Listagem de código 42:

Listagem 42:
public class ImagesInAndroid extends Activity {
    //---the images to display---
    Integer[] imageIDs = {
             R.drawable.pic1,
             R.drawable.pic2,
             R.drawable.pic3,
             R.drawable.pic4,
             R.drawable.pic5,
             R.drawable.pic6
    };
@Override
    public void onCreate(Bundle savedInstanceState)
    {
      super.onCreate(savedInstanceState);
        setContentView(R.layout.passo1);

        GridView gridView = (GridView) findViewById(R.id.gridview);
        gridView.setAdapter(new ImageAdapter(this));

        gridView.setOnItemClickListener(new OnItemClickListener()
        {
            public void onItemClick(AdapterView parent,
            View v, int position, long id)
            {
                Toast.makeText(getBaseContext(),
                        "pic" + (position + 1) + " selected",
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

    public class ImageAdapter extends BaseAdapter
    {
        private Context context;
        private int itemBackground;

        public ImageAdapter(Context c)
        {
            context = c;
        }

        public int getCount() {
            return imageIDs.length;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup
parent) {
            ImageView imageView;
            if (convertView == null) {
                imageView = new ImageView(context);
                imageView.setLayoutParams(new
GridView.LayoutParams(85, 85));
                 imageView.setScaleType( ImageView.ScaleType.CENTER_CRO
                        P);
            } else {
                imageView = (ImageView) convertView;
            }
            imageView.setImageResource(imageIDs[position]);
            return imageView;

        }
    }
}
Execute a aplicação:




       Obs: as fotos são uma homenagem a uma pessoa mais que especial
 na minha vida, minha noiva e futura esposa. Sheila, te amo. Ah, ela
 liberou o direito de imagem, está tudo certo.



         o CONCLUSÃO

      Primeiramente gostaria de agradecer mais uma vez ao autor do texto
“Understanding User Interface in Android”, que foi de onde parti meu
estudo em interfaces de usuário com Android. Além de outras fontes que
pesquisei.
      No texto foi possível perceber claramente a facilidade que existe na
criação das UIs de nossos aplicativos com a mistura entre XML e
codificação Java. Os componentes do Android são fáceis de usar e muito
bonitos, deixando um programador Java ME como eu de queixo caído,
principalmente nas View que tratam de imagens.
      Se o tempo permitir pretendo continuar com a série de artigos aqui
no Java Móvel, comentários e sugestões são sempre bem vindos.
o SOBRE MIM


       Meu nome é Ricardo da Silva Ogliari, sou graduado em Ciência da
Computação pela Universidade de Passo Fundo. Atualmente também estou
cursando uma pós-graduação em web, estratégias de inovação e tecnologia,
no Senac SP. Trabalho com mobile a 6 anos, escrevo artigos para algumas
revistas nacionais especializadas. Sou criador e mantenedor do
http://www.mobilidadetudo.com e sou um dos membros do
www.javamovel.com. Palestrei em eventos nacionais e internacionais,
como o FISL e o JustJava, além de ter dezenas de artigos meus espalhados
pelo mundão da internet.

Contenu connexe

Tendances

Apostila passo a passo como programar em android edição03
Apostila passo a passo como programar em android edição03Apostila passo a passo como programar em android edição03
Apostila passo a passo como programar em android edição03Horacio Diamante Mondlane
 
Introdução à programação para Android
Introdução à programação para AndroidIntrodução à programação para Android
Introdução à programação para AndroidJorge Cardoso
 
Programação Android - Básico
Programação Android - BásicoProgramação Android - Básico
Programação Android - BásicoHugoDalevedove
 
Computação Móvel 2012.2 - Android
Computação Móvel 2012.2 - AndroidComputação Móvel 2012.2 - Android
Computação Móvel 2012.2 - AndroidTiago Bencardino
 
Android About Page API Para Construir a Tela Sobre
Android About Page API Para Construir a Tela SobreAndroid About Page API Para Construir a Tela Sobre
Android About Page API Para Construir a Tela SobreVinícius Thiengo
 
Ebook AngularJS | Guia Introdutório
Ebook AngularJS | Guia Introdutório Ebook AngularJS | Guia Introdutório
Ebook AngularJS | Guia Introdutório Portal GSTI
 
Sobre Visual studio
Sobre Visual studioSobre Visual studio
Sobre Visual studioleolupe
 
Curso de Android Aula 4
Curso de Android Aula 4Curso de Android Aula 4
Curso de Android Aula 4Jose Berardo
 
Android: Avaliação do Pré-projeto Agenda Cultural
Android: Avaliação do Pré-projeto Agenda CulturalAndroid: Avaliação do Pré-projeto Agenda Cultural
Android: Avaliação do Pré-projeto Agenda CulturalVinícius Thiengo
 
Construindo aplicações com netbeans
Construindo aplicações com netbeansConstruindo aplicações com netbeans
Construindo aplicações com netbeansSliedesharessbarbosa
 
Introdução ao desenvolvimento de apps para Android - Dia 2/2
Introdução ao desenvolvimento de apps para Android - Dia 2/2Introdução ao desenvolvimento de apps para Android - Dia 2/2
Introdução ao desenvolvimento de apps para Android - Dia 2/2Matheus Calegaro
 
Da introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento AndroidDa introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento AndroidRicardo Longa
 
Trabalhando Análise Qualitativa em seu Aplicativo Android
Trabalhando Análise Qualitativa em seu Aplicativo AndroidTrabalhando Análise Qualitativa em seu Aplicativo Android
Trabalhando Análise Qualitativa em seu Aplicativo AndroidVinícius Thiengo
 

Tendances (20)

Apostila passo a passo como programar em android edição03
Apostila passo a passo como programar em android edição03Apostila passo a passo como programar em android edição03
Apostila passo a passo como programar em android edição03
 
Introdução à programação para Android
Introdução à programação para AndroidIntrodução à programação para Android
Introdução à programação para Android
 
Modelo de desenvolvimento de software em 3 camadas para Wordpress
Modelo de desenvolvimento de software em 3 camadas para WordpressModelo de desenvolvimento de software em 3 camadas para Wordpress
Modelo de desenvolvimento de software em 3 camadas para Wordpress
 
Programação Android - Básico
Programação Android - BásicoProgramação Android - Básico
Programação Android - Básico
 
Computação Móvel 2012.2 - Android
Computação Móvel 2012.2 - AndroidComputação Móvel 2012.2 - Android
Computação Móvel 2012.2 - Android
 
Android About Page API Para Construir a Tela Sobre
Android About Page API Para Construir a Tela SobreAndroid About Page API Para Construir a Tela Sobre
Android About Page API Para Construir a Tela Sobre
 
Android Aula 3
Android Aula 3Android Aula 3
Android Aula 3
 
Android Aula 5
Android Aula 5Android Aula 5
Android Aula 5
 
Ebook AngularJS | Guia Introdutório
Ebook AngularJS | Guia Introdutório Ebook AngularJS | Guia Introdutório
Ebook AngularJS | Guia Introdutório
 
Sobre Visual studio
Sobre Visual studioSobre Visual studio
Sobre Visual studio
 
Android Aula 4
Android Aula 4Android Aula 4
Android Aula 4
 
Curso de Android Aula 4
Curso de Android Aula 4Curso de Android Aula 4
Curso de Android Aula 4
 
Android: Avaliação do Pré-projeto Agenda Cultural
Android: Avaliação do Pré-projeto Agenda CulturalAndroid: Avaliação do Pré-projeto Agenda Cultural
Android: Avaliação do Pré-projeto Agenda Cultural
 
Apostila visual basic
Apostila visual basicApostila visual basic
Apostila visual basic
 
Construindo aplicações com netbeans
Construindo aplicações com netbeansConstruindo aplicações com netbeans
Construindo aplicações com netbeans
 
Android Aula 2
Android Aula 2Android Aula 2
Android Aula 2
 
Uml Para Web
Uml Para WebUml Para Web
Uml Para Web
 
Introdução ao desenvolvimento de apps para Android - Dia 2/2
Introdução ao desenvolvimento de apps para Android - Dia 2/2Introdução ao desenvolvimento de apps para Android - Dia 2/2
Introdução ao desenvolvimento de apps para Android - Dia 2/2
 
Da introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento AndroidDa introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento Android
 
Trabalhando Análise Qualitativa em seu Aplicativo Android
Trabalhando Análise Qualitativa em seu Aplicativo AndroidTrabalhando Análise Qualitativa em seu Aplicativo Android
Trabalhando Análise Qualitativa em seu Aplicativo Android
 

Similaire à Como criar interfaces gráficas com android

Android Core Aula 6 - Desenvolvimento de aplicações Android
Android Core Aula 6 -  Desenvolvimento de aplicações AndroidAndroid Core Aula 6 -  Desenvolvimento de aplicações Android
Android Core Aula 6 - Desenvolvimento de aplicações AndroidFelipe Silveira
 
Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3Erisvaldo Junior
 
Layouts e multiplas activities
Layouts e multiplas activitiesLayouts e multiplas activities
Layouts e multiplas activitiesCalebeMiquissene
 
435142330-Guia-Completo-React-Js.pdf
435142330-Guia-Completo-React-Js.pdf435142330-Guia-Completo-React-Js.pdf
435142330-Guia-Completo-React-Js.pdfJulia469065
 
Spring & Struts
Spring & StrutsSpring & Struts
Spring & Strutseduan
 
Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojofabioginzel
 
Minicurso de Android
Minicurso de AndroidMinicurso de Android
Minicurso de AndroidEdgar Eler
 
Programando Android - Aula 3
Programando Android - Aula 3Programando Android - Aula 3
Programando Android - Aula 3Kalil Maciel
 
RelativeLayout em 3 Lições
RelativeLayout em 3 LiçõesRelativeLayout em 3 Lições
RelativeLayout em 3 LiçõesRenascienza
 
Data Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI AndroidData Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI AndroidVinícius Thiengo
 
Material Design - Melhorando a experiência de seu App
Material Design - Melhorando a experiência de seu AppMaterial Design - Melhorando a experiência de seu App
Material Design - Melhorando a experiência de seu Appalissin
 
Da introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento AndroidDa introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento AndroidRodolfo Faquin Della Justina
 

Similaire à Como criar interfaces gráficas com android (20)

Apostila Android
Apostila AndroidApostila Android
Apostila Android
 
Android Core Aula 6 - Desenvolvimento de aplicações Android
Android Core Aula 6 -  Desenvolvimento de aplicações AndroidAndroid Core Aula 6 -  Desenvolvimento de aplicações Android
Android Core Aula 6 - Desenvolvimento de aplicações Android
 
Hello World Android
Hello World AndroidHello World Android
Hello World Android
 
Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3
 
Layouts e multiplas activities
Layouts e multiplas activitiesLayouts e multiplas activities
Layouts e multiplas activities
 
435142330-Guia-Completo-React-Js.pdf
435142330-Guia-Completo-React-Js.pdf435142330-Guia-Completo-React-Js.pdf
435142330-Guia-Completo-React-Js.pdf
 
React js
React js React js
React js
 
Spring & Struts
Spring & StrutsSpring & Struts
Spring & Struts
 
Asp net mvc
Asp net mvcAsp net mvc
Asp net mvc
 
Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojo
 
Minicurso de Android
Minicurso de AndroidMinicurso de Android
Minicurso de Android
 
Programando Android - Aula 3
Programando Android - Aula 3Programando Android - Aula 3
Programando Android - Aula 3
 
RelativeLayout em 3 Lições
RelativeLayout em 3 LiçõesRelativeLayout em 3 Lições
RelativeLayout em 3 Lições
 
Data Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI AndroidData Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI Android
 
Material Design - Melhorando a experiência de seu App
Material Design - Melhorando a experiência de seu AppMaterial Design - Melhorando a experiência de seu App
Material Design - Melhorando a experiência de seu App
 
Da introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento AndroidDa introdução à prática no desenvolvimento Android
Da introdução à prática no desenvolvimento Android
 
JavaServer Faces
JavaServer FacesJavaServer Faces
JavaServer Faces
 
Hello ReactJs
Hello ReactJsHello ReactJs
Hello ReactJs
 
Apostila JavaME
Apostila JavaMEApostila JavaME
Apostila JavaME
 
Android - Parte 7
Android - Parte 7Android - Parte 7
Android - Parte 7
 

Plus de Ricardo Ogliari

Clean Code/Architecture com Android e Flutter
Clean Code/Architecture com Android e FlutterClean Code/Architecture com Android e Flutter
Clean Code/Architecture com Android e FlutterRicardo Ogliari
 
Mobile, Flutter e Mercado
Mobile, Flutter e MercadoMobile, Flutter e Mercado
Mobile, Flutter e MercadoRicardo Ogliari
 
Aula 1 view model livedata e databinding.pptx
Aula 1   view model livedata e databinding.pptxAula 1   view model livedata e databinding.pptx
Aula 1 view model livedata e databinding.pptxRicardo Ogliari
 
Programando em ruby para arduino
Programando em ruby para arduinoProgramando em ruby para arduino
Programando em ruby para arduinoRicardo Ogliari
 
Intel edison Primeiro Projeto
Intel edison Primeiro ProjetoIntel edison Primeiro Projeto
Intel edison Primeiro ProjetoRicardo Ogliari
 
Internacionalizando um aplicativo BlackBerry API
Internacionalizando um aplicativo BlackBerry APIInternacionalizando um aplicativo BlackBerry API
Internacionalizando um aplicativo BlackBerry APIRicardo Ogliari
 
Criando itens de menu em aplicativos nativos com a BlackBerry API
Criando itens de menu em aplicativos nativos com a BlackBerry APICriando itens de menu em aplicativos nativos com a BlackBerry API
Criando itens de menu em aplicativos nativos com a BlackBerry APIRicardo Ogliari
 
Utilizando O Cell Id Para Popularizar Os Sistemas Lbs
Utilizando O Cell Id Para Popularizar Os Sistemas LbsUtilizando O Cell Id Para Popularizar Os Sistemas Lbs
Utilizando O Cell Id Para Popularizar Os Sistemas LbsRicardo Ogliari
 
Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.
Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.
Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.Ricardo Ogliari
 
A hora de criar LBS para pequenos dispositivos é agora!!
A hora de criar LBS para pequenos dispositivos é agora!!A hora de criar LBS para pequenos dispositivos é agora!!
A hora de criar LBS para pequenos dispositivos é agora!!Ricardo Ogliari
 

Plus de Ricardo Ogliari (15)

IoT além do Arduino
IoT além do ArduinoIoT além do Arduino
IoT além do Arduino
 
Clean Code/Architecture com Android e Flutter
Clean Code/Architecture com Android e FlutterClean Code/Architecture com Android e Flutter
Clean Code/Architecture com Android e Flutter
 
Mobile, Flutter e Mercado
Mobile, Flutter e MercadoMobile, Flutter e Mercado
Mobile, Flutter e Mercado
 
Aula 1 view model livedata e databinding.pptx
Aula 1   view model livedata e databinding.pptxAula 1   view model livedata e databinding.pptx
Aula 1 view model livedata e databinding.pptx
 
Programando em ruby para arduino
Programando em ruby para arduinoProgramando em ruby para arduino
Programando em ruby para arduino
 
Intel edison Primeiro Projeto
Intel edison Primeiro ProjetoIntel edison Primeiro Projeto
Intel edison Primeiro Projeto
 
Internacionalizando um aplicativo BlackBerry API
Internacionalizando um aplicativo BlackBerry APIInternacionalizando um aplicativo BlackBerry API
Internacionalizando um aplicativo BlackBerry API
 
Bada
BadaBada
Bada
 
Internacionalizacao
InternacionalizacaoInternacionalizacao
Internacionalizacao
 
Palm e web os
Palm e web osPalm e web os
Palm e web os
 
Trechos interessantes
Trechos interessantesTrechos interessantes
Trechos interessantes
 
Criando itens de menu em aplicativos nativos com a BlackBerry API
Criando itens de menu em aplicativos nativos com a BlackBerry APICriando itens de menu em aplicativos nativos com a BlackBerry API
Criando itens de menu em aplicativos nativos com a BlackBerry API
 
Utilizando O Cell Id Para Popularizar Os Sistemas Lbs
Utilizando O Cell Id Para Popularizar Os Sistemas LbsUtilizando O Cell Id Para Popularizar Os Sistemas Lbs
Utilizando O Cell Id Para Popularizar Os Sistemas Lbs
 
Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.
Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.
Instalando e Configurando o JIL SDK. Crie seu primeiro widget com a ferramenta.
 
A hora de criar LBS para pequenos dispositivos é agora!!
A hora de criar LBS para pequenos dispositivos é agora!!A hora de criar LBS para pequenos dispositivos é agora!!
A hora de criar LBS para pequenos dispositivos é agora!!
 

Como criar interfaces gráficas com android

  • 1. Começando a Criar Interfaces Gráficas com Android • Introdução O estudo para criar este artigo foi feito em várias fontes, mas uma chamou a atenção por teu uma seqüência de exemplos muito bem explicados e de fácil entendimento. O texto se chama “Understanding User Interface in Android”. Neste artigo vamos aprender como criar interfaces gráficas (UI) mais básicas com Android, utilizando o Eclipse como IDE de desenvolvimento. Pretendo criar outros artigos falando sobre componentes mais complexos ou se aprofundando nos apresentados aqui. Para quem está chegando de mundos um pouco mais obscuros em relação à UI, como o Java ME, a diferença é gritante e impressiona. Com Android temos gerenciadores de layout sofisticados, componentes estilizados com efeitos atrativos graficamente, além de uma facilidade no desenvolvimento. Obs: O Java ME ganhou muito poder UI quando ganhou o framework LWUIT, permitindo uso de componentes e gerenciadores de layouts. Mas quem programou com Java ME pré-LWUIT sabe das dificuldades de criar uma tela amigável com Canvas. Existem algumas plataformas, como a da RIM (responsável pelos aparelhos BlackBerry) que redefiniu o Java ME para suas necessidades. Nestes aparelhos, também é possível criar telas atraentes para o usuário. O Android oferece dois modos de criar interfaces gráficas, uma é definindo um arquivo XML que será carregado no startup da aplicação e a renderização da tela é construída em tempo de execução. O outro modo é através da codificação pura. Na maioria dos casos o desenvolvedor usará as duas maneiras, porém, recomenda-se a preferência pelo uso do XML. Como vimos nos outros publicados por mim no Java Móvel, um aplicativo Android terá uma Activity, que é responsável pela interface gráfico da aplicação. Na verdade, ela pode ser imaginada como uma tela do seu software.
  • 2. Obs: A Activity utiliza uma pilha, chamada de activity stack, o índice que estiver no topo da pilha será a tela exibida para o usuário da aplicação. Para quem programa para BlackBerry OS verá grandes similaridades com a pilha de Screens desta plataforma. Como dissemos anteriormente, existem dois modos de criação de UI no Android, aqui vamos nos deter principalmente no XML. Então, veja o exemplo abaixo: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/nome" /> </LinearLayout> O XML acima representa a interface gráfica, contendo um campo de texto em um layout linear, orientado verticalmente. A aplicação deve possuir no mínimo uma classe que herde de Activity e sobrecarregue o método onCreate: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } Perceba que definidos a interface através de um arquivo XML, usando o método setContentView. O R representa a classe com as constantes que identificam os recursos da nossa aplicação. Ao longo deste artigo vamos ver em detalhes o pouco que fizemos até aqui, vamos a luta. • View e ViewGroup
  • 3. Quando pensamos em interface gráfica de um aplicativo Android devemos ter em mente oque significa View e ViewGroup. Ambos representam qualquer componente visual que você visualizar na tela do aparelho. Como estas classes são de suma importância para o entendimento do texto no geral, vou parafrasear o site oficial de desenvolvedores Android: A classe View representa o bloco de construção básico para componentes de interface gráfica. Uma View ocupa uma área retangular na tela e é responsável por desenhar e controlar os eventos. View é a classe básica para widgets, que são usados para criar componenets de UI interativos (botões, caixas de texto, etc.). A subclasse ViewGroup é a classe base para layouts, que são containers invisíveis que contém Views (ou outros ViewGroups) e definem as propriedades desse layout. Veja a Figura 1 para um melhor entendimento. Figura 1: Views e Views Group. Para fazer com que o leitor entenda definitivamente à importância dessas duas classes, veja a Figura 2: Na interface existe um vasto conjunto de widgets, desde botões até caixas de seleções. Todos esses componentes estão dentro de um gerenciador de layout, mais precisamente em um LinearLayout.
  • 4. Figura 2: Exemplo real de Views e Views Group. • Gerenciadores de Layout Vamos começar a brincadeira com UI no Android com os gerenciadores de layout. Como o próprio nome indica, estas classes orientam o posicionamento dos widgets na tela. Dependendo do layout utilizado, até a altura e largura do componente é alterada. Para quem trabalhou com o swing do Java lembra do BorderLayout, FlowLayout, dentre outros. Até mesmo no Java ME é possível utilizar gerenciador parecidos com os mencionados anteriormente, através do LWUIT. Inicialmente vamos criar uma aplicação Android que alteraremos conforme o gerenciador de layout a ser estudado. o Criando o projeto Recapitulando dos nossos artigos anteriores. Siga o caminho file- >new->Android Project. Configure as seguintes opções e clique em Ok:
  • 5. Project Name: LayoutsAndroid. • Contents: Create new project in workspace. • Target Name: Android 2.1. • Application Name: Layouts Android • Package Name: com.estudo.android. • Create Activity: LayoutsAndroid Figura 3: Configurações do projeto inicial.
  • 6. O Eclipse já cria o projeto e toda a estrutura de pastas e códigos necessária. Execute este projeto e verá o seguinte: Figura 3: Projeto inicial emulado. Dê uma olhada também no arquivo main.xml, que pode ser encontrado no caminho res->layout. Listagem 1: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> O nosso exemplo já usa um gerenciador de layout, o LinearLayout, que, por acaso, será nosso primeiro objeto de estudo.
  • 7. o LinearLayout Este gerenciador organiza seus componentes filhos em uma única coluna ou única linha, dependendo da orientação que o mesmo tiver. Para ficar mais claro, vamos editar o arquivo main.xml citado anteriormente: Listagem 2: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <EditText android:id="@+id/EditText01" android:layout_width="180px" android:layout_height="wrap_content" /> <EditText android:id="@+id/EditText02" android:layout_width="180px" android:layout_height="wrap_content" /> <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enviar" /> </LinearLayout> Se executarmos a aplicação agora, veja como fica: Figura 4: Projeto alinhados verticalmente.
  • 8. Vamos fazer algumas alterações no XML para compreender oque ele faz. Na declaração do layout, que sempre deve ser o nó raiz do documento, temos o LinearLayout. Definimos para este componente três propriedades: android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" A orientation defina se os componentes se desenrolarão no sentido horizontal ou vertical. Se a tela terá apenas uma linha ou uma coluna, como falado anteriormente. Mudemos essa propriedade para: android:orientation="horizontal" O resultado podemos ver abaixo: Também definimos as propriedades de largura (width) e altura (height). Ambos usam fill_parent, que diz o seguinte: use todo o espaço disponível na tela. Vamos mudar novamente o main.xml, mais especificamente as propriedades do LinearLayout.
  • 9. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="100px" android:layout_height="100px"> O resultado é: Perceba que o restante dos componentes foi cortado, por exceder os limites do seu container, o LinearLayout. Na prática, porém, vai ser raro as vezes em que este gerenciador de layout não vai ocupar todo o espaço disponível na tela. Existem alguns atributos específicos para componentes que fazem todo sentido quando aplicados no LinearLayout. Vamos trabalhar com duas propriedades: android:layout_weight e android:layout_gravity. Reescreva o main.xml: LISTAGEM 3: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <EditText android:id="@+id/EditText01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0.3" /> <EditText android:id="@+id/EditText02" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0.7" /> <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enviar" android:layout_gravity="right" /> </LinearLayout> Depois de executar veremos o seguinte:
  • 10. Figura 7: Utilizando gravity e weight. A propriedade gravity funciona como uma função de alinhamento em relação ao container, como usamos right no botão, veja que ele se encontra na extremidade direita da tela. O weight repassa para os componentes o espaço não utilizado na tela. Há, não se preocupem com os componentes, eles serão tratados daqui a pouco. Volte para a figura 4 e perceba que o espaço “vazio” desapareceu, sendo atribuído para as duas caixas de textos que definiram a propriedade weight. Perceba também, que a segunda caixa de texto recebeu 70% do espaço não utilizado, por isso ficou maior que a primeira caixa. Bem, encerramos por aqui a discussão sobre a LinearLayout. Há, não se preocupe com os widgets (componentes). Logo veremos detalhadamente cada um. o AbsoluteLayout Este gerenciador define exatamente a posição (coordenada x/y) onde cada componente deve ficar. Este layout é menos flexível e também exige um maior trabalho para manutenção. Por exemplo, quando o aparelho muda a orientação, quem deve redefinir a posição dos componentes é o programador, via código.
  • 11. Mas chega de conversa, redefina o main.xml para isso: LISTAGEM 4: <?xml version="1.0" encoding="utf-8"?> <AbsoluteLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" > <EditText android:id="@+id/EditText01" android:layout_width="190px" android:layout_height="wrap_content" android:layout_x="12px" android:layout_y="12px" /> <EditText android:id="@+id/EditText02" android:layout_width="190px" android:layout_height="wrap_content" android:layout_x="12px" android:layout_y="60px" /> <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enviar" android:layout_x="12px" android:layout_y="161px" /> </AbsoluteLayout> Quando executamos a nossa aplicação fica com a seguinte cara: Figura 8: Utilizando AbsoluteLayout. Simples né? Mas como o leitor já deve ter percebido, na é um gerenciador de layout muito aconselhado.
  • 12. o TableLayout Este gerenciador pode ser o mais auto-descritivo de todos. Para surpresa geral, ele organiza seus componentes filhos em linhas e colunas. As linhas da tabela são representadas pela classe TableRow. As colunas são criadas conforme a inserção de componentes em uma mesma linha. Não é permitido bordas em linhas, colunas e células. Reescreva o main.xml: LISTAGEM 5: <?xml version="1.0" encoding="utf-8"?> <TableLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" > <TableRow> <TextView android:text="Nome" android:layout_width="100px" /> <EditText android:id="@+id/EditText01" android:layout_width="200px" /> </TableRow> <TableRow> <TextView android:text="Endereço"/> <EditText android:id="@+id/EditText02" /> </TableRow> <TableRow> <TextView /> <Button android:id="@+id/Button01" android:text="Enviar" /> </TableRow> </TableLayout> Para gerar uma interface como a Figura 9: Figura 8: Utilizando TableLayout.
  • 13. Vários pontos devem ser detalhados aqui. Primeiramente, veja que definimos a largura dos componentes somente para a primeira linha. Isso porque a coluna define sua largura como igual a largura do maior componente horizontal. Assim, se redefinirmos a última caixa de texto e o botão para: <TableRow> <TextView android:text="Endereço"/> <EditText android:id="@+id/EditText02" android:layout_width="100px"/> </TableRow> <TableRow> <TextView /> <Button android:id="@+id/Button01" android:text="Enviar" android:layout_width="50px" /> </TableRow> O resultado da interface vai ser o mesmo. Tanto o campo de texto de endereço como o botão tem largura menor que a primeira caixa de texto. Na última linha colocamos um campo de texto vazio: <TextView /> Isso deve ser feito para que não ocorra o seguinte efeito: Figura 8: Utilizando TableLayout com espaço a mais. o RelativeLayout O RelativeLayout trabalha da seguinte forma. Cada componente filho deve indicar sua posição em relação a outro componente.
  • 14. Vamos começar nossos estudos com este main.xml. LISTAGEM 6: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/RLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" > <TextView android:id="@+id/lblComments" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Idéias" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" /> <EditText android:id="@+id/txtComments" android:layout_width="fill_parent" android:layout_height="170px" android:textSize="18sp" android:layout_alignLeft="@+id/lblComments" android:layout_below="@+id/lblComments" android:layout_centerHorizontal="true" /> <Button android:id="@+id/btnSave" android:layout_width="125px" android:layout_height="wrap_content" android:text="Salvar" android:layout_below="@+id/txtComments" android:layout_alignRight="@+id/txtComments" /> <Button android:id="@+id/btnCancel" android:layout_width="124px" android:layout_height="wrap_content" android:text="Lixeira" android:layout_below="@+id/txtComments" android:layout_alignLeft="@+id/txtComments" /> </RelativeLayout> O primeiro componente, um texto estático, está orientado em relação ao sei pai, ou seja, ao próprio layout. Então, definimos que ele estará a esquerda e ao topo da tela. android:layout_alignParentTop="true" android:layout_alignParentLeft="true" Antes de prosseguir, veja como fica esta interface em trabalho.
  • 15. Figura 9: Utilizando RelativeLayout. A caixa de texto tem sua localização definida com: android:layout_alignLeft="@+id/lblComments" android:layout_below="@+id/lblComments" O layout_alignLeft diz que o componente estará alinhado a esquerda do componente com o id lblCmments, que neste caso, é o texto estático “Idéias”. Também, usamos o layout_below para dizer que este componente estará logo abaixo do mesmo componente de texto lblComments. O botão de lixeira define sua localização com; android:layout_below="@+id/txtComments" android:layout_alignLeft="@+id/txtComments" Exatamente da forma como definimos nossa caixa de texto, exceto pela mudança do componente referenciado. Agora indicamos o txtComments como ponto de referência. Finalmente, temos o botão salvar: android:layout_below="@+id/txtComments" android:layout_alignRight="@+id/txtComments" A única mudança é de alignLeft para alignRight.
  • 16. O desenvolver tem acesso as seguinte propriedades para definir o posicionamento dos componentes no RelativeLayout: * layout_above * layout_alignBaseline * layout_alignBottom * layout_alignLeft * layout_alignParentBottom * layout_alignParentLleft * layout_alignParentRight * layout_alignParentTop * layout_alignRight * layout_alignTop * layout_Below * layout_centerHorizontal * layout_centerInParent * layout_centerVertical * layout_leftOf * layout_rightOf * layout_true o FrameLayout O FrameLayout reserva um espaço na tela que deve ser utilizado por uma View. Se mais de uma View for colocada nesta área, haverá sobreposição de componentes, com o último que foi inserido aparecendo por primeiro. Vamos a codificação. Altere main.xml: LISTAGEM 7: <?xml version="1.0" encoding="utf-8"?> <AbsoluteLayout android:id="@+id/AbsoluteLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <FrameLayout android:layout_x="88dip" android:id="@+id/FrameLayout01"
  • 17. android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_y="104dip"> <TimePicker android:id="@+id/TimePicker01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TimePicker> </FrameLayout> </AbsoluteLayout> Neste XML, apenas o TmePicker pode parecer estranho, mas ele é somente um widget para escolher uma hora do dia. Veja visualmente como fica a execução da aplicação com este XML: Figura 10: Utilizando FrameLayout. Estamos usando o FrameLayout dentro de um AbsoluteLayout, logo, devemos especificar sua posição em coordenadas x, y. O FrameLayout possui apenas uma widget, o TimePicker. Até aqui parece que não veremos nada de diferente nesse layout. Mas vamos tentar adicionar mais um componente no XML: <FrameLayout android:layout_x="88dip" android:id="@+id/FrameLayout01"
  • 18. android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_y="104dip"> <TimePicker android:id="@+id/TimePicker01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TimePicker> <Button android:text="Botão" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </FrameLayout> Agora iniciamos a aplicação e veremos isto: Perceba que o botão sobrepôs o TimePicker. Isso acontece porque o FrameLayout mostra apenas uma View. o ScrollView Agora fiquei em dúvida entre qual dos layout é o mais auto- descritivo: TableLayout ou ScrollView. Este último, mostra apenas uma
  • 19. ViewGroup que pode exceder os limites da tela física do aparelho. Geralmente o ViewGroup utilizado é um LinearLayout. Falta pouco, vamos editar pela última vez o main.xml neste tópico de layouts. <?xml version="1.0" encoding="utf-8"?> <ScrollView android:id="@+id/widget54" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" > <LinearLayout android:layout_width="310px" android:layout_height="wrap_content" android:orientation="vertical" > <Button android:text="Brasil" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="França" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Argentina" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Uruguai" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="México" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Paraguai" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Chile" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Colômbia" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Alemanha" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Estados Unidos" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Inglaterra" android:layout_width="110px" android:layout_height="wrap_content" /> <Button android:text="Escócia" android:layout_width="110px" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView>
  • 20. Este layout não tem mistério, o leitor já deve até estar visualizando mentalmente como ficará a execução do aplicação desta vez. Veja na Figura abaixo: Veja a barra no lado direito. Fácil esse scroll view hein.
  • 21. • Views Depois que aprendemos sobre os gerenciadores de layout, representados pelos ViewsGroups, está na hora de aprender sobre s os componentes, representados pelas classes que herdam de View. Para melhor compreensão, vamos dividir este tópico em cinco áreas: • Views básicas: para criar componentes básicos, como caixa de textos e botões; • Pickers Views: componentes especiais que permitem o usuário selecionar de uma certa fonte; • Views de listas: componentes que mostram uma lista de informações; • Views para imagens: componentes especializados para tratamento com imagens. Vocês irão se surpreender com estes componentes; • Menus; • Extras. Antes de iniciarmos este instigante tópico de estudo, vamos criar um novo projeto no Eclipse, chamado ViewsAndroid. Como o leitor já sabe os passos, só vou deixar a imagem com as configurações:
  • 22. Agora vamos partir para a ação. o BasicViews - Início As views básicas não precisam de muita explicação, o leitor já deve ter usado elas intensamente em qualquer software. E, se o leitor for programador, então já deve ter criado milhares destes componentes:
  • 23. • TextView • EditText • Button • ImageButton • CheckBox • ToggleButton • RadioButton • RadioGroup Vamos editar nosso main.xml do projeto recém criado. Reescreva-o com as seguintes informações: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/txtView" android:text="Cadastro" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/btnAbrir" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Abrir" /> <ImageButton android:id="@+id/btnImg1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/icon" /> <EditText android:id="@+id/txtName" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <CheckBox android:id="@+id/chkAutosave" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Autosave" /> <CheckBox android:id="@+id/star" style="?android:attr/starStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <RadioGroup android:id="@+id/rdbSexo"
  • 24. android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <RadioButton android:id="@+id/rdbM" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Masculino" /> <RadioButton android:id="@+id/F" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Feminino" /> </RadioGroup> <ToggleButton android:id="@+id/toggle1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> Rode este projeto e verás o seguinte resultado: Figura 14: Exemplo de Views. O primeiro componente é um TextView, dispensando maiores apresentações. O segundo componente é um Button, também é muito auto-
  • 25. explicativo. O terceiro componente é um ImageButton, mesclando uma imagem ao botão tradicional. Aqui podemos perceber um ponto interessante na forma de programar do Android. Sempre devemos definir a fonte da imagem, no nosso exemplo utilizamos: android:src="@drawable/icon" O leito deve estar lembrado que na classe Activity usamos a seguinte linha de código: setContentView(R.layout.main); Ou seja, ambos referem-se aos recursos localizados na pasta res. A diferença é que no primeiro caso acessamos estes recursos através do XML, sendo assim devemos definir um ‘@’, a localização do recurso (drawable, layout ou values) e o nome. No último caso acessamos o recurso através do código Java. Sendo assim, você indica a classe R e, o caminho referente ao recurso desejado. Seguindo com o exemplo da Figura 14. O quarto componente é um campo de texto, representado pela classe EditView. O quinto componente é um simples CheckBox. O sexto componente também é um CheckBox, mas com uma especificidade. Redefinimos seu estilo, veja: style="?android:attr/starStyle" O sétimo e oitavo componente são instâncias de RadioButton, dentro de um ButtonGroup. Finalmente, o último componente é um ToggleButton, um botão estilizado com dois estados: on e off. Também podemos mudar os textos do ToggleButton. Adicione mais duas propriedades ao último componente citado: android:textOn="Sim" android:textOff="Não" Agora o componente apresenta textos definidos pelo programador, e não aqueles padrões, veja:
  • 26. Outro componente que possui atributos importantes para serem citados aqui, é o EditText. Em alguns casos, o programador adiciona um campo de texto onde o usuário informa sua senha, sendo assim, o texto deve ser substituído por asteriscos. Para atingir este objetivo, existe uma propriedade que pode ser adicionada ao EditText: <EditText android:id="@+id/txtName" android:layout_width="fill_parent" android:layout_height="wrap_content" android:password = "true" /> Veja oque acontece: o BasicViews – Tratamento de Eventos Até agora só mostramos alguns componente na tela, mas não inserimos nenhum tratamento de eventos. E como podemos fazer isso? No início deste artigo falamos rapidamente que a interface gráfica de um aplicativo pode ser construída de duas maneiras: diretamente com o XML ou codificando cada componente. Por exemplo, já usamos o TextView no XML, porém, existe uma classe TextView que pode ser instanciada e tratada diretamente via código.
  • 27. Mesmo quando optamos por criar a interface via XML, que é mais indicada inclusive pelo site de desenvolvedores do Android, vamos usar a codificação pura em Java para tratar dos eventos. Vamos alterar a classe ViewsAndroid, localizada na pasta com.estudo.android, em src: Listagem 11: 1: package com.estudo.android; 2: 3: import android.app.Activity; 4: import android.os.Bundle; 5: import android.view.View; 6: import android.widget.CheckBox; 7: import android.widget.Toast; 8; 9: public class ViewsAndroid extends Activity { 10: /** Called when the activity is first created. */ 11: @Override 12: public void onCreate(Bundle savedInstanceState) { 13: super.onCreate(savedInstanceState); 14: setContentView(R.layout.main); 15: 16: CheckBox checkBox=(CheckBox) findViewById(R.id.chkAutosave); 17: checkBox.setOnClickListener(new View.OnClickListener() 18: { 19: public void onClick(View v) { 20: Toast.makeText(getBaseContext(), "Salvar "+ (((CheckBox)v).isChecked()?"Aut.":"Man."), Toast.LENGTH_SHORT).show(); 21: } 22: }); 23: 24: } 25:} Não sei se vocês perceberam que em todos widgets (componentes) criados até aqui, sempre definimos uma propriedade android:id. Essa identificação é usada para recuperar este componente no código Java através do método findViewById(), linha 16 da listagem de código 16 . Com posse da instância de CheckBox podemos configurar um listener para o evento de clique, usando o método setOnClickListener e passando por parâmetro uma instância de OnClickListener. Na Listagem de código isso é feito na linha 17. Perceba que instanciamos a classe passada para o método da mesma linha. Quando definimos o método OnClickLisener devemos redefinir o comportamento do método onClick. Este, por sua vez, programa oque acontecerá quando o comportamento receber o evento de clique.
  • 28. Veja nas Figuras abaixo oque programos para o momento em que o botão for selecionado como checado e não-checado. Inicialmente o CheckBox está desativado, então, quando ele for selecionado mostramos “Salvar Aut.”, caso inverso mostramos “Salvar Man.”. Figura 15: CheckBox ativado. Figura 16: CheckBox desativado. Esse texto que aparece na tela é um Toast. Veja a linha de código 20 da Listagem 11. Usamos o método estático makeToast() que recebe os seguintes parâmetros: um contexto, a mensagem e um inteiro que define a duração. No temo usamos a constante LENGHT_SHORT. Para os componentes Button e ToogleButton também podemos usar o OnClickListener. Para o RadioButton vamos utilizar o OnCheckedChangeListener. Vamos fazer algumas alterações no exemplo anterior, assim, o ChangeLisener será compreendida perfeitamente. A idéia é associar uma imagem com o campo de escolha do sexo. Sendo assim, a primeira mudança é no main.xml, adicionando mais uma propriedade ao botão de escolha do sexo masculino. <RadioButton android:id="@+id/rdbM" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Masculino" android:checked="true" /> Com isso, a opção de “Masculino” vai vir marcada como padrão. O primeiro passo é criar um widget ImageView na nossa tela. Inicialmente ela mostrará uma imagem do sexo masculino:
  • 29. </RadioGroup> <ImageView android:id="@+id/imgSexo" android:src = "@drawable/menino" android:layout_width="wrap_content" android:layout_height="wrap_content" /> Ao rodar este aplicativo veremos o seguinte: Figura 17: RadioButton masculino selecionado. As imagens que aparecerão são da internet, você por qualquer imagem na sua pasta res/drawable e chama-las de menino e menina. Se o usuário escolher “Feminino” ainda não acontece nada. Eu disse ainda, porque vamos mudar isso agora. Veja a Listagem de código 12: Listagem 12: 1:public void onCreate(Bundle savedInstanceState) { 2: ... 3: RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rdbSexo); 4: radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() 5: { 6: public void onCheckedChanged(RadioGroup group, int checkedId) { 7: RadioButton rdb = (RadioButton) findViewById(checkedId); 8: ImageView img = (ImageView) findViewById(R.id.imgSexo); 9: if (rdb.getText().equals("Feminino")){ 10: img.setImageResource(R.drawable.menina); 11: } else { 12: img.setImageResource(R.drawable.menino); 13: } 14: } 15: }); 16:} Na linha 4 adicionamos o OnCheckedChangeListener ao componente RadioGroup. Assim, quando um dos RadioButton´s for selecionado o método onCheckedChanged(), na linha 6, será notificado. Os parâmetros que este método recebe são: o RadioGroup que recebeu a
  • 30. iteração e o identificador único do RadioButton que foi marcado como checado. Na linha 7 recuperamos o objeto RadioButton através do id recebido como parâmetro. Na linha 8 recuperamos o objeto ImageView da forma já conhecida, ou seja, referenciando o componente através das constantes da classe R. Na linha 9 testamos se o texto do RadioButton selecionado é igual a “Feminino”. Caso afirmativo, devemos configurar a fonte do ImageView para a imagem da menininha. E é isso que fizemos na linha 11. Caso o teste booleano resulte em false, a imagem mostrada deve ser do menino (como já foi mostrado na Figura 17). Agora podemos executar o aplicativo novamente e marcar a caixa de seleção “Feminino”. Veremos algo semelhante ao mostrado na Figura 18: Figura 18: RadioButton masculino selecionado. o BasicViews – Barra de Progresso A barra de progresso é um componente muito comum em qualquer interface de usuário. Seus exemplos de uso podem ser: acompanhar quantos bytes foram transmitidos quando envia seu relatório para seu chefe, acompanhar um processamento um pouco mais pesado e não pensar que a aplicação deu erro e está travada, dentre outros. Vamos criar uma nova tela para vermos o comportamento desse widget. Crie um novo arquivo .xml em res/layout, chamado barradeprogresso.xml. Veja como na Figura 19:
  • 31. Figura 19: Criando o barradeprogresso.xml. Edite o barradeprogresso.xml com o código da Listagem 13: Listagem 13: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ProgressBar android:id="@+id/progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/btnEnviar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Enviar" /> </LinearLayout>
  • 32. Mude também a classe ViewsAndroid (Listagem 14). Listagem 14: package com.estudo.android; import android.app.Activity; import android.os.Bundle; public class ViewsAndroid extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.barradeprogresso); } } Depois de executar o aplicativo temos: Essa é a forma mais básica da barra de progresso do Android, dê uma olhada nas propriedades e verá que não acrescentamos nada de novo ao que já vínhamos utilizando. O modo que estamos usando este componente é padrozinado, seu ciclo é indeterminado. Útil para operações que não temos idéia de quando serão finalizadas. No código acima a barra de progresso (que mais parece um círculo de progresso) vai ficar na tela infinitamente. Vamos adicionar o código da Listagem 15 no onCreate: Listagem 15: 1:progressBar = (ProgressBar) findViewById(R.id.progressbar); 2: 3:new Thread(new Runnable() { 4: public void run() { 5: while (progressStatus < 10) { 6: progressStatus++;// = doSomeWork(); 7: try {
  • 33. 9: Thread.sleep(500); 10: } catch (InterruptedException e) { 11: e.printStackTrace(); 12: } 13: } 14: 15: progressBar.setVisibility(8); 16: } 17:}).start(); A Listagem 15 recupera o objeto PorgressBar logo na primeira linha. Posteriormente, adicionamos uma rotina com código Java puro, que apenas roda uma Thread enquanto a variável progressStatus for menor que 10. Depois disse ele muda a visibilidade do ProgressBar, para 8. Execute o aplicativo, espere alguns segundos e... Como assim? Que erro é esse? Substitua a linha 15 pelo conjunto de linhas de código abaixo: handler.post(new Runnable() { public void run() { progressBar.setVisibility(8); } });
  • 34. O erro aconteceu porque dentro de uma Thread, não é possível lançar outra linha de execução. O Handler permite que isso acontece trabalhando diretamente com o sistema operacional. Depois da correção você pode reiniciar a aplicação e esperar alguns segundos que o ProgressBar desaparecerá da tela. Mas ainda ficou uma questão em aberto. Reveja a linha de código: progressBar.setVisibility(8); Afinal, oque significa o parâmetro 8. O ProgressBar pode ter três estados possível, identificados por números inteiros: • 0 – visível • 4 – invisível • 8 – finalizado Por exemplo, se mudarmos a linha do setVisibly para: progressBar.setVisibility(4); Depois do mesmo intervalo de tempo veríamos:
  • 35. Mas ainda não acabamos a discussão sobre o ProgressBar. Outra propriedade interessante é a possibilidade de mudar o estilo do widget. O primeiro passo é redefinir o widget em nosso xml: <ProgressBar android:id="@+id/progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal" android:max="50" /> Fizemos duas coisas. O atributo style define o estilo do componente. O android:max define o valor máximo da barra de progresso (que agora sim terá um formato de barra de progresso). Na classe ViewsAndroid redefina o bloco de código dentro do while para: while (progressStatus < 50) { progressStatus++; handler.post(new Runnable() { public void run() { progressBar.setProgress(progressStatus); } }); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } Perceba que implementamos o método setProgress dentro do laço, ou seja, a cada iteração a barra de progresso aumenta sua área completada. Depois chegar aos 50 (seu valor máximo) ela ainda deverá sumir, portanto, o restando do código permanece igual. Execute novamente o aplicativo e recebera:
  • 36. o BasicViews – AutoCompleteTextView O AutoCompleteTextView é filho de TextView, sendo assim, ele traz um campo para inserção de texto. Seu diferencial é a possibilidade de definir um conjunto de Strings que funcionam como auto complemento do texto que está sendo digitado pelo usuário. Reescreva o barradeprogresso.xml com o código da Listagem 16: Listagem 16: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <AutoCompleteTextView android:id="@+id/txtEstadios" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> Até este momento apenas criamos o campo de texto. Se olharmos o aplicativo nesse momento a interface conterá apenas uma caixa de exto normal, sem complemento de código nenhum. Agora vamos editar também o ViewsAndroid com o texto da Listagem 17: Listagem 17: package com.estudo.android; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; public class ViewsAndroid extends Activity { 1: 2: String[] estadios = { "Soccer City", "Ellis Park", "Moses Mabhida", "Peter Mokaba", "Mbombela Stadium", "Loftus Versfeld", "Royal Bafokeng", "Free State", "Green Point", "Nelson Mandela Bay" }; /** Called when the activity is first created. */ @Override 3: public void onCreate(Bundle savedInstanceState) { 4: super.onCreate(savedInstanceState); 5: setContentView(R.layout.barradeprogresso); 6:
  • 37. 7: ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout. simple_dropdown_item_1line, estadios); 8: AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.txtEstadios); 9: textView.setThreshold(3); 10: textView.setAdapter(adapter); 11: } 12:} Vamos examinar o código a partir da linha 8. Neste ponto criamos a instãncia de AutoCompleteTextView. Na linha 9 usamos o método setThreshold para definir que depois da terceira letra o complemento já pode trabalhar e, finalmente, na linha 10 adicionamos o ArrayAdapter ao componente, este, definirá os textos que podem ser usados no complemento. O ArrayAdapter, por sua vez, é criado na linha 7. O construtor usado recebe um contexto, que pode ser this. Recebe também um segundo parâmetro inteiro, que define seu comportamento. O último parâmetro recebe um vetor de Objects com as Strings para complemento. Agora podemos executar a aplicação novamente. Perceba que depois que digito a terceira letra, o ‘e’,ele me traz as opções cadastradas no ArrayAdapter. o PickerViews Estetipo de widget permite que o usuário selecione uma data ou hora de um componente estilizado e atraente visualmente. Vamos criar uma nova interface que pede o nome do usuário, a data e hora do nascimento e calcula quantos dias faltam para tira a carteira de
  • 38. habilitação, ou, quantos dias faltam para a aposentadoria (pensando em 65 anos). Se o usuário tiver mais que 65 anos, mostramos quantas copas o usuário já assistiu. Crie um novo arquivo XML chamado datahora.xml: Listagem 18: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <EditText android:id="@+id/txtNome" android:layout_width="200px" android:layout_height="wrap_content" /> <TimePicker android:id="@+id/pckHora" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <DatePicker android:id="@+id/pckData" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/btnCalcular" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Calcular" /> </LinearLayout> No XML da Listagem 18 os únicos dois componentes que se destacam por serem novos são o DatePicker e o TimePicker. As propriedades de ambos já são bem conhecidas do leitor. Também altere a classe ViewsAndroid usando o código da Listagem 19: Listagem 19: package com.estudo.android; import java.util.Calendar; import java.util.Date; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.DatePicker; import android.widget.EditText; import android.widget.TimePicker; import android.widget.Toast; public class ViewsAndroid extends Activity { private static final String CATEGORIA = "data e hora";
  • 39. /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.datahora); } } Ao executarmos este aplicativo veremos: Figura 26: Aplicativo usando DatePicker e TimePicker. Nossa aplicação ainda não fará nada se clicarmos no botão “Calcular”. Para conseguir isso vamos adicionar o trecho de código da Listagem 20 depois da linha do setContentView no método onCreate. 1:Button botao = (Button) findViewById(R.id.btnCalcular); 2;botao.setOnClickListener(new View.OnClickListener(){ 3: public void onClick(View v){ 4: TimePicker hora = (TimePicker) findViewById(R.id.pckHora); 5: DatePicker data = (DatePicker) findViewById(R.id.pckData); 6: EditText edtNome = (EditText) findViewById(R.id.txtNome); 7; 8: Calendar calNasc = Calendar.getInstance(); 9: calNasc.set(Calendar.YEAR, data.getYear()); 10: calNasc.set(Calendar.MONTH, data.getMonth()); 11: calNasc.set(Calendar.DAY_OF_MONTH, data.getDayOfMonth()); 12: calNasc.set(Calendar.HOUR_OF_DAY, hora.getCurrentHour()); 13: calNasc.set(Calendar.MINUTE, hora.getCurrentMinute()); 14: 15: Calendar calHoje = Calendar.getInstance(); 16: calHoje.setTime(new Date());
  • 40. 17: 18: int tempo = calHoje.compareTo(calNasc); 19: 20: if (tempo > 0){ 21: calculaData(calNasc, calHoje, edtNome.getText().toString()); 22: } 23: } 24:}); Nas duas primeiras linhas configuramos o listener para o componente Button. Na linha 3 criamos o método que vai responder por todas iterações. Nas linhas 4, 5 e 6 recuperamos os objetos para o TimePicker, DatePicker e EditText. Na linha 8 criamos a instância de Calendar que armazena a data de nascimento do usuário. Na seqüência de linhas de 9 até 11, configuro os valores de ano, mês e data do calendário, utilizando os métodos da classe DatePicker para recuperar os valores configurados pelo usuário. As linhas 12 e 13 configuram a hora do dia e o minuto do nascimento do usuário, utilizando métodos da classe TimePicker. Perceba que não tratamos o tempo, apenas incluímos estas linhas de código como aprendizado, porém, pode ficar como um tema de casa para o leitor. Na linha 15 criamos uma nova instância de Calendar. Na linha 16 configuramos a data atual como valor para o objeto criado na linha anterior. Na linha 18 utilizamos o método compareTo da classe Calendar para pegar um número inteiro com a diferença entre as duas datas comparadas. Se o valor for maior que zero (teste realizado na linha 20), significa que o usuário informou uma data do passado, caso contrário, a lógica do programa não precisa ser concluída porque ninguém nasce no futuro, ainda. O leitor deve ter percebido que paramos no método calculaData, onde passamos três parâmetros: data de nascimento do usuário, data atual e nome do usuário. Veja na Listagem 21 o código do método calculaData: Listagem 21: public void calculaData(Calendar nascimento, Calendar agora, String nome){ int ano = agora.get(Calendar.YEAR); int mes = agora.get(Calendar.MONTH); int dia = agora.get(Calendar.DAY_OF_MONTH); int anoNasc = nascimento.get(Calendar.YEAR); int mesNasc = nascimento.get(Calendar.MONTH);
  • 41. int diaNasc = nascimento.get(Calendar.DAY_OF_MONTH); int idade = ano - anoNasc; if(mes < mesNasc) { idade--; } else if (mes == mesNasc) { if(dia < diaNasc) { idade--; } } String mensagem = ""; if (idade < 18) mensagem = nome+ ", faltam "+(18 - idade)+" anos para tirar a carteira!"; else if (idade >= 18 && idade < 65) mensagem = "Calma "+nome+", faltam "+(65 - idade)+" anos para você se aposentar"; else mensagem = nome+ ", o senhor já assistiu "+(idade/4)+" copas"; Toast.makeText(getBaseContext(), mensagem, Toast.LENGTH_SHORT).show(); } O código da Listagem 21 não tem segredo, é apenas código Java. Primeiramente calculamos a idade, conforme esse resultado configuramos a mensagem do aviso. Finalmente, utilizamos o Toast (já discutido nesse texto), para apresentar a mensagem ao usuário. Veja o resultado de um dos casos:
  • 42. Figura 27: Caso de uso do aplicativo usando DatePicker e TimePicker. Não utilizamos muito o TimePicker, mas o aplicativo já mostrou uma idéia do uso deste componente. Assim como os outros widgets do Android, este é bem fácil de usa. O programador também pode usar os pickers um uma janela de diálogo. Vamos fazer algumas alterações, primeiro, no datahora.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/txtAlarme" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Alarme não configurado"/> <Button android:id="@+id/btnConfigurar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Configurar" /> </LinearLayout> Realmente acho que não preciso explicar o XML. A nossa aplicação vai mostrar uma caixa de texto e um botão. O objetivo é que ao interagir com o botão, o usuário receba uma caixa de diálogo com um seletor de hora para configurar seu despertador. Vamos alterar o conteúdo da classe ViewsAndroid. Veja a Listagem 23: Listagem 23: 1: private static final int TIME_DIALOG_ID = 0; 2: private TextView lblAlarme; 3: 4: /** Called when the activity is first created. */ 5: @Override 6: public void onCreate(Bundle savedInstanceState) { 7: super.onCreate(savedInstanceState); 8: setContentView(R.layout.datahora); 9: lblAlarme = (TextView) findViewById(R.id.txtAlarme); 10: Button btn = (Button) findViewById(R.id.btnConfigurar); 11: btn.setOnClickListener(new View.OnClickListener(){ 12: public void onClick(View v){ 13: showDialog(TIME_DIALOG_ID); 14: }
  • 43. 15: }); 16: 17: } 18: @Override 19: protected Dialog onCreateDialog(int id) 20: { 21: switch (id) { 22: case TIME_DIALOG_ID: 23: TimePickerDialog td = new TimePickerDialog( 24: this, mTimeSetListener, 12, 00, false); 25: 26: return td; 27: } 28: return null; 29: } 30: 31: private TimePickerDialog.OnTimeSetListener mTimeSetListener = 32: new TimePickerDialog.OnTimeSetListener() 33: { 34: public void onTimeSet(TimePicker view, int hourOfDay, int minuteOfHour) 35: { 36: lblAlarme.setText("Alarme configurado para " + hourOfDay + ":" + minuteOfHour); 37: } 38: }; Na linha 9 recuperamos o objeto TextView, porque vamos editar seu texto posteriormente. Na linha 10 recuperamos o objeto Button. Na linha 11 adicionamos um OnClickListener para o botão recém criado. Quando o usuário clicar neste componente vamos abrir uma caixa de diálogo. Para q ue o diálogo mostrado não seja o padrão do Android, devemos sobrescrever o método onCreateDialog. Também por isso, passamos o TIME_DILAOG_ID como parâmetro, para termos certeza de interceptar somente nosso diálogo. Com isso, mensagens vindas diretamente do Android continuarão a serem mostradas. Dentro do onCreatDialog verificamos se estamos recebendo a mensagem do nosso próprio código. Caso afirmativo, instanciamos um novo objeto TimePickerDialog (linha 23). Seu construtor recebe um Context, um OnTimeSetListener, uma hora e um minuto inicial e, por fim, um valor booleano dentificando se o componente trabalhará com 24 horas ou, com horas AM e PM. Perceba que o OnTimeSetListener foi criado no mesmo código, na linha 31, devemos obrigatoriamente implementar o método onTimeSet (linha 34). Este último método é chamado sempre que a hora é configurada no TimePickerDialog. Quando isso acontecer apenas mudamos o texto do TextView. Veja em três passos a aplicação em funcionamento:
  • 44. Figura 28: Tela inicial da Figura 29: Diálogo aberto após Figura 30: Depois de clicar em aplicação. clicar no botão. “Set” mudamos o texto do TetView. o ListViews O ListView é um componente para mostrar uma grande lista de dados com scroll. Este componente não precisa de muita explicação, porém, tem algumas diferenças significativas com os exemplos que vimos até aqui. Para explorar ao máximo este widget vamos criar uma lista com todos os países da copa do mundo de 2010. Ao clicarmos em um dos nomes mostramos a posição da seleção no ranking da FIFA. Primeiramente vamos criar um novo XML, listview.xml. Veja seu conteúdo na Listagem 24: Listagem 24: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> Ainda não vimos nenhuma novidade, mas veja como ficará nossa classe ViewsAndroid na Listagem 25:
  • 45. Listagem 25: 1:public class ViewsAndroid extends ListActivity { 2: 3: String[] paises = { 4: "Africa do Sul", 5: ... 6: "Uruguai" }; 7: 8: int posicoes[] = new int[]{ 9: 90, ..., 18 }; 10: 11: public void onCreate(Bundle savedInstanceState) 12: { 13: super.onCreate(savedInstanceState); 14: setContentView(R.layout.listview); 15: 16: setListAdapter(new ArrayAdapter<String>(this, 17: android.R.layout.simple_list_item_1, paises)); 18: } 19: 20: public void onListItemClick(ListView parent, View v, int position, long id) { 21: Toast.makeText(this, paises[position]+" está na "+posicoes[position]+"° posição", Toast.LENGTH_SHORT).show(); 22: } 23:} A primeira grande diferença já encontramos na linha 1, perceba que não estendemos mais a classe de Activity, mas sim de ListActivity. O interessante deste componente, é que ele já utiliza internamente uma ListView. Na linha 3 criamos um vetor de String com todos os nomes dos países participantes da copa do mundo. Como não iríamos colocar os 32 países aí, usamos as reticências. Na linha 8 é a vez de criar o vetor de inteiros com as posições das seleções no ranking da FIFA. O ListActivity precisa que a classe configure seu ListAdapter, que pode ser entendido como um adaptador que faz a ponte entre o vetor de itens com a lista propriamente dita. Na Listagem estamos fazendo isso na linha 16. Um de seus construtores (usados na nossa codificação) recebe um Context, um inteiro que define o layout da lista e um vetor com os itens da lista. Finalmente, implementamos o método onListItemChecked para tratar das interações do usuário com a lista. Com o parâmetro position definimos o país e sua colocação e apresentamos em um Toast. Veja na Figura abaixo o comportamento do aplicativo em execução:
  • 46. Figura 31: Lista de países com interação no item Brasil. Nossa lista está configurado para escolha única, padrão do componente. Mas poderíamos alterar isso, trabalhando com a sua propriedade android:choiceMode, que permite o uso de três constantes: none, singleChoice e multipleChoice. o SpinnerViews Este componente também objetiva mostrar uma grande quantidade de dados em uma lista. Porém, ele mostra uma lista no estilo popup, lembrando o ChoiceGroup estilo POPUP NO Java ME. Vamos trabalhar no mesmo exemplo criado acima mas mudando o componente. Para começar, crie um arquivo chamado spinner.xml e edite-o conforme a Listagem 26: Listagem 26: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Spinner
  • 47. android:id="@+id/spinner1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> A classe ViewsAndroid também sofrerá algumas mudanças. A primeira é na declaração da classe, que fica assim: public class ViewsAndroid extends Activity { No onCreate também teremos alterações. Veja a Listagem 27: Listagem 27: 1: super.onCreate(savedInstanceState); 2: setContentView(R.layout.spinner); 3: 4: s1 = (Spinner) findViewById(R.id.spinner1); 5: ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, paises); 6: 7: s1.setAdapter(adapter); 8: s1.setOnItemSelectedListener(new OnItemSelectedListener() { 9: public void onItemSelected(AdapterView<?> arg0, 10: View arg1, int arg2, long arg3) { 11: int index = s1.getSelectedItemPosition(); 12: Toast.makeText(getBaseContext(), paises[index]+" ocupa a "+posicoes[index]+"° no ranking da FIFA", Toast.LENGTH_SHORT).show(); 13: } 14: 15: public void onNothingSelected(AdapterView<?> arg0) {} 16:}); Na linha 4 recuperamos o objeto Spinner. Este componente também trabalha com um adaptador, criado na linha 5, e configurado para o Spinner na linha 7. Na linha 8 adicionamos o OnItemSelectedListener, e implementamos seus dois métodos obrigatórios. No onItemSelected recuperamos a posição do item selecionado no Spinner (linha 11) e depois mostramos a mesma mensagem mostrada no exemplo anterior. Veja como ficou este aplicativo: Figura 32: Tela inicial do aplicativo com Spinner.
  • 48. Figura 33: Spinner mostrando seus itens. Figura 34: Tela depois de selecionarmos a Argentina no Spinner. Também podemos mudar a forma como a lista é mostrada ao usuário. Altere a linha 5 da lista 27 para:
  • 49. ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, paises); Veja o resultado: Figura 35: Spinner com layout modificado. o Gallery e ImageView A partir desse momento vamos ver componente que nos ajudam a apresentar imagens ao usuário. Se o leitor deste texto estava começando se apaixonar pelo Android, vai pedir a mão dele em casamento ao final deste tópico. Como este tópico difere dos demais, vamos criar um novo aplicativo, chamado ImagesInAndroid:
  • 50. Figura 36: Criação do projeto ImagesInAndroid. Crie um arquivo XML chamado passo1.xml. Veja seu conteúdo na Listagem 28: Listagem 28: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Gallery android:id="@+id/gallery1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
  • 51. Também precisamos alterar a classe ImagesInAndroid. Como as mudanças são várias, vamos por partes. Primeiramente veja o básico que já aprendemos sobre Android: package com.estudos.android; import … public class ImagesInAndroid extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.passo1); } } Nenhuma novidade. O passo seguinte é separar algumas imagens e joga-las dentro da patas res.drawable. Veja como fica a estrutura de diretório na Figura 37: Figura 37: Arquitetura atualizada com as imagens. Feito isso, cria-se um variável com um vetor de instâncias de Integer. Veja abaixo como fica. Perceba que estamos referenciando a nossa classe de recursos, R.
  • 52. Integer[] imageIDs = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6 }; Agora, vamos adicionar um evento de clique nas imagens do Gallery. O código mostrado abaixo está dentro do método onCreate: Gallery gallery = (Gallery) findViewById(R.id.gallery1); gallery.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { Toast.makeText(getBaseContext(), "Selecionou" + (position + 1), Toast.LENGTH_SHORT).show(); } }); Nesse código também não encontramos nada de novo em relação ao que já vimos até aqui. Agora execute este arquivo e: Figura 38: Usando Gallery. Cadê as imagens? As imagens não apareceram porque o Gallery também precisa de um adaptador, semelhante ao que ocorre com o ListView e o Spinner, vistos a pouco. Esse adaptador precisa ser criado, diferentemente do Spinner por exemplo, que já tem uma implementação da BaseAdapter para ela (SpinnerAdapter), ou do ListView, que possui o ListAdapter. Sendo assim, vamos criar uma classe interna chamada ImageAdapter, veja na Listagem 32 seu código: Listagem 33: 1:public class ImagesInAndroid extends Activity 2:{ 3: …
  • 53. 4: 5: public class ImageAdapter extends BaseAdapter { 6: private Context context; 7: private int itemBackground; 8: 9: public ImageAdapter(Context c) { 10: context = c; 11: } 12: 13: public int getCount() { 14: return imageIDs.length; 15: } 16: 17: public Object getItem(int position) { 18: return position; 19: } 20: 21: public long getItemId(int position) { 22: return position; 23: } 24: 25: public View getView(int position, View convertView, ViewGroup parent) { } 26: } 27:} Veja que a classe ImageAdapter está dentro de ImagesInAndroid. Ela herda diretamente de BaseAdapter, e, como a linguagem Java ensina, existem alguns métodos que devem ser implementados ao herdar esta classe, sendo eles: • getCount (linha 13): retorna o número de componentes. No nosso caso retornamos o número de elementos no vetor imageIDs, que contém as imgens que serão mostradas no Gallery. • getItem e getItemId (linhas 17 e 21 respectivamente): retornam o objeto e o identificador do elemento em uma determinada posição. • getView (linha 25): retorna um objeto que herda de View que será mostrado em uma determinada posição do Gallery. Vimos que o getView retorna o objeto que será mostrado na galeria. Aqui estamos trabalhando com ImageView, mas é importante sabe que o método pode retornar qualquer classe que herda de View. Por exemplo, poderíamos retornar instâncias de TextView. Veja como ficaria o método getView: public View getView(int position, View convertView, ViewGroup parent) { TextView tv = new TextView(context); tv.setWidth(100);
  • 54. tv.setText("Teste"); return tv; } E o resultado é: Figura 39: Usando Gallery com TextView. Claro que este exemplo não tem nenhuma utilidade prática, mas serve como prova de conceito. Voltando aquilo que realmente importa neste tópico, que é Gallery com ImageView, devemos retornar uma instância desta última classe no lugar do TextView no método getView. Vamos editar novamente o método: public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView = new ImageView(context); imageView.setImageResource(imageIDs[position]); return imageView; } E o resultado: Figura 40: Usando Gallery com ImageView.
  • 55. As imagens ainda estão com o seu tamanho natural, também é possível perceber que elas tem um sombreamento mais claro nas extremidades laterais, isso acontece porque é o estilo padrão do componente. Vamos configurar algumas propriedades do ImageView para melhorar o Gallery. Adicione mais estas duas linhas de código no corpo do getView: imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setLayoutParams(new Gallery.LayoutParams(150, 120)); Estamos definindo o tamanho do componente na segunda linha e, na primeira, configuramos o tipo de escala. Como resultado, a imagem vai ocupar toda a área reservada pra ela (150 por 120 pixeis). Veja como fica na Figura 41: Figura 41: Usando Gallery com ImageView e parâmetros de layout. Para finalizar com toque de ouro, vamos usar um estilo para melhorar a apresentação das fotos. public View getView(int position, View convertView, ViewGroup parent) { ... ... ... imageView.setBackgroundResource( android.R.drawable.alert_light_ frame); return imageView; } E o resultado disso:
  • 56. Figura 42: Usando Gallery com ImageView e estilo. Mas acho que nossa aplicação ainda não está legal, no momento quando clicamos em uma foto apenas mostramos na tela qual imagem foi clicada: Figura 43: Resultado inicial de interação com imagens. Mas acho que podemos fazer melhor que isso. Vamos mostrar a imagem selecionada na parte central da tela, em um componente ImageView. Para conseguir nosso objetivo edite o passo1.xml e adicione o seguinte trecho de código logo depois do Gallery. <ImageView android:id="@+id/image1"
  • 57. android:layout_width="320px" android:layout_height="250px" /> Também altere o tratamento da interação do usuário com o Gallery, veja: gallery.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { ImageView imageView = (ImageView) findViewById(R.id.image1); imageView.setImageResource(imageIDs[position]); } }); O resultado está na Figura 44: Figura 44: Interação com imagens configurando imagens no centro. Lembram-se que antes usamos o tipo de escala para definir o comportamento da galeria de imagens na parte superior da tela, também podemos usar agora na visualização da imagem. Adicione o seguinte atributo ao ImageView no passo1.xml: android:scaleType="fitXY" />
  • 58. Agora a imagem vai preencher toda a região reservada ao ImageView. Veja na Figura 45: Figura 45: ImageView escalado para preencher região central da tela. o ImageSwitcher A troca de imagens que implementamos no exemplo anterior com ImageView e Gallery também pode ser conseguida com este componente , e com uma vantagem, o ImageSwitcher permite configurar alguns efeitos 3D na troca das imagens. Este exemplo será construído encima do anterior. Sendo assim, edite o arquivo passo1.xml conforme a Listagem 39: Listagem 39: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ff000000" > <ImageSwitcher android:id="@+id/switcher1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentLeft="true"
  • 59. android:layout_alignParentRight="true" android:layout_alignParentBottom="true" /> <Gallery android:id="@+id/gallery1" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </RelativeLayout> Também é preciso alterar a classe ImagesInAndroid. Siga a Listagem 40: Listagem 40: 1:public class ImagesInAndroid extends Activity implements ViewFactory { 2: private ImageSwitcher imageSwitcher; 3: 4: Integer[] imageIDs = {}; 5: 6: @Override 7; public void onCreate(Bundle savedInstanceState) 8: { 9: super.onCreate(savedInstanceState); 10: setContentView(R.layout.passo1); 11: 12: imageSwitcher = (ImageSwitcher) findViewById(R.id.switcher1); 13: imageSwitcher.setFactory(this); 14: 15: imageSwitcher.setInAnimation( AnimationUtils.loadAnimation( this, android.R.anim.fade_in)); 16: imageSwitcher.setOutAnimation( AnimationUtils.loadAnimation( this, android.R.anim.fade_out)); 27: 18: Gallery gallery = (Gallery) findViewById(R.id.gallery1); 19: ... 20: gallery.setOnItemClickListener(new OnItemClickListener() { 21: public void onItemClick(AdapterView parent, 22: View v, int position, long id) { 23: imageSwitcher.setImageResource(imageIDs[position]); 24: } 25: }); 26: } 27: 28: public class ImageAdapter extends BaseAdapter 29: {} 30: 31: @Override 32: public View makeView() { 33: ImageView imageView = new ImageView(this); 34: imageView.setBackgroundColor(0xFF000000); 35: imageView.setScaleType(ImageView.ScaleType.FIT_XY); 36: imageView.setLayoutParams(new 37: ImageSwitcher.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 38: return imageView; 39: } 40:}
  • 60. Vamos falar somente das alterações feitas na classe anterior. Perceba que na linha 12 recuperamos o componente ImageSwitcher. Na linha 13 usamos o método setFactory para definir a fábrica usada para criar as duas imagens que serão usadas para o componente fazer o flip. Este método recebe como parâmetro uma classe que implemente a interface ViewFactory, implementada na mesma classe ImagesInAndroid, veja a linha 1. Nas linhas 15 e3 16 configuramos os eventos que a imagem terá no momento de entrada e de saída da tela do usuário. Também mudamos a tarefa a realizar quando o usuário clicar em uma das imagens do Gallery. Neste momento indicamos ao ImageSwitcher qual imagem ele deve apresentar na tela, ele próprio trata da renderização dos efeitos configurados anteriormente. Por fim, vá até a linha 32 e veja que implementamos o método makeView, obrigatório quando implementamos a ViewFactory. Estemétodo criará a nova View que será adicionada no switcher. Aqui também poderíamos passar qualquer componente que herde de View, como fizemos com o TextView no exemplo do tópico anterior (Gallery e ImageView). Ao executar a aplicamos veremos: Figura 46: Uso do ImageSwitcher.
  • 61. Aparentemente não percebemos nenhuma diferença, a não ser pelo fato da imagem ocupar a tela inteira. Porém, interaja com o Gallery para ver os efeitos do ImageSwitcher. o GridView Para finalizar este artigo/tutorial/ vãos mostrar o GridView, que, como o próprio nome indica permite que mostramos imagens em uma grade de fotos. O passo1.xml fica da seguinte maneira: <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:columnWidth="90dp" android:stretchMode="columnWidth" android:gravity="center" /> No próprio XML configuramos algumas propriedades que são próprias de qualquer grade, não só Android, como por exemplo: android:layout_width, android:layout_height, android:numColumns, android:verticalSpacing, android:horizontalSpacing, android:columnWidth. O ImagesInAndroid sofre mudanças, mas o leitor irá tirar de letra este código a esta altura do campeonato. Veja a Listagem de código 42: Listagem 42: public class ImagesInAndroid extends Activity { //---the images to display--- Integer[] imageIDs = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6 };
  • 62. @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.passo1); GridView gridView = (GridView) findViewById(R.id.gridview); gridView.setAdapter(new ImageAdapter(this)); gridView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { Toast.makeText(getBaseContext(), "pic" + (position + 1) + " selected", Toast.LENGTH_SHORT).show(); } }); } public class ImageAdapter extends BaseAdapter { private Context context; private int itemBackground; public ImageAdapter(Context c) { context = c; } public int getCount() { return imageIDs.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(context); imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); imageView.setScaleType( ImageView.ScaleType.CENTER_CRO P); } else { imageView = (ImageView) convertView; } imageView.setImageResource(imageIDs[position]); return imageView; } } }
  • 63. Execute a aplicação: Obs: as fotos são uma homenagem a uma pessoa mais que especial na minha vida, minha noiva e futura esposa. Sheila, te amo. Ah, ela liberou o direito de imagem, está tudo certo. o CONCLUSÃO Primeiramente gostaria de agradecer mais uma vez ao autor do texto “Understanding User Interface in Android”, que foi de onde parti meu estudo em interfaces de usuário com Android. Além de outras fontes que pesquisei. No texto foi possível perceber claramente a facilidade que existe na criação das UIs de nossos aplicativos com a mistura entre XML e codificação Java. Os componentes do Android são fáceis de usar e muito bonitos, deixando um programador Java ME como eu de queixo caído, principalmente nas View que tratam de imagens. Se o tempo permitir pretendo continuar com a série de artigos aqui no Java Móvel, comentários e sugestões são sempre bem vindos.
  • 64. o SOBRE MIM Meu nome é Ricardo da Silva Ogliari, sou graduado em Ciência da Computação pela Universidade de Passo Fundo. Atualmente também estou cursando uma pós-graduação em web, estratégias de inovação e tecnologia, no Senac SP. Trabalho com mobile a 6 anos, escrevo artigos para algumas revistas nacionais especializadas. Sou criador e mantenedor do http://www.mobilidadetudo.com e sou um dos membros do www.javamovel.com. Palestrei em eventos nacionais e internacionais, como o FISL e o JustJava, além de ter dezenas de artigos meus espalhados pelo mundão da internet.