segunda-feira, 10 de julho de 2017

Aplicações Android com Xamarin – Parte 3 de N – Classes de modelo e primeira tela

Em 05/07/2017

Continuando a série sobre desenvolvimento de aplicações Android com Xamarin, hoje nós vamos criar as classes de modelo da nossa aplicação e uma versão rudimentar da nossa primeira tela. Se você está acompanhando a série desde o começo, você provavelmente se lembra que nós construiremos um aplicativo bem simples de controle de gastos. Esse aplicativo terá somente duas telas, e hoje nós vamos construir um esboço da tela que listará os gastos cadastrados.

Acesse os artigos anteriores

Antes de continuar com a leitura deste artigo, acesse os artigos anteriores dessa série utilizando os links abaixo:

Xamarin Forms ou Xamarin Native?

Caso você não saiba, ao desenvolvermos aplicativos móveis com Xamarin, nós temos duas opções de desenvolvimento: Xamarin Forms e Xamarin Native.
Com o Xamarin Native, nós temos basicamente uma “tradução” das ferramentas de desenvolvimento nativas para C#. Ou seja, ao invés de programarmos em Java para desenvolvermos uma aplicação Android, nós programamos em C# e o Xamarin faz a conversão para Java por trás dos panos. Porém, o “jeitão” de programar é basicamente o mesmo se estivéssemos desenvolvendo a aplicação com Java. Isso quer dizer que, caso nós precisemos desenvolver também uma aplicação iOS, o código seria bem diferente, e o compartilhamento de código relacionado à UI entre os projetos Android e iOS seria bem mais complicado (afinal, o jeito de construir UIs no Android é completamente diferente do iOS).
Já com o Xamarin Forms, nós temos basicamente uma “layer” em cima do Android, iOS e UWP. Dessa forma, nós desenvolvemos somente um código de UI (utilizando XAML) e o Xamarin Forms fará a conversão apropriada para cada uma das plataformas desejadas. Se você acessar a página do Xamarin Forms, você encontrará esta imagem que representa muito bem a ideia dessa ferramenta:
Como você já deve imaginar, as duas opções contam com vantagens e desvantagens, e esse é um tópico bem extenso. Eu não pretendo me estender muito sobre esse assunto, mesmo porque eu não tenho experiência com nenhuma das duas modalidades de desenvolvimento para conseguir opinar sobre as diferenças. Quando eu tiver desenvolvido aplicações suficientes com Xamarin Forms e Xamarin Native, eu escrevo um outro artigo contando as minhas opiniões. Enquanto isso, você pode dar uma olhada nestes links:

E na nossa série? Qual abordagem vamos utilizar? Como nós vamos primeiramente construir somente um aplicativo Android, eu resolvi utilizar o Xamarin Native. Dessa forma, nós não teremos a curva de aprendizado do XAML necessária para o Xamarin Forms (apesar de eu ter experiência com desenvolvimento XAML no WPF e UWP, sei que muita gente que acompanha o site ainda não tem essa experiência). Dependendo do resultado dessa série, talvez mais para frente eu comece outra sobre Xamarin Forms mostrando a migração desse mesmo aplicativo para as três plataformas.

Criando o projeto

Agora que já está decidido que vamos utilizar Xamarin Native nessa primeira série, vamos começar criando a nossa solução. Já prevendo a criação de outras aplicações em outras plataformas no futuro, decidi criar uma solução em branco, para então adicionarmos os projetos individualmente. O nome dessa solução será “ControleDeGastos“:
Com a solução em branco criada, vamos adicionar um novo projeto do tipo “Blank App (Android)“, dando o nome de “ControleDeGastos.Android“:

Classes de modelo

Uma vez criado o projeto, vamos adicionar as nossas classes de modelo. Se analisarmos as imagens do protótipo da aplicação (apresentadas na primeira parte dessa série), conseguiremos detectar somente duas possíveis classes: Estabelecimento e Gasto.
A classe “Estabelecimento” terá somente uma propriedade “Id” e uma propriedade “Nome“. Já a classe “Gasto” terá as propriedades “Id“, “Data“, “Estabelecimento” e “Valor“. Para organizarmos melhor o nosso código, vamos criar essas classes dentro de uma nova pasta chamada “Models“:
1
2
3
4
5
public class Estabelecimento
{
    public int Id { get; set; }
    public string Nome { get; set; }
}
1
2
3
4
5
6
7
public class Gasto
{
    public int Id { get; set; }
    public DateTime Data { get; set; }
    public Estabelecimento Estabelecimento { get; set; }
    public decimal Valor { get; set; }
}
Nota: por enquanto nós só estamos trabalhando com um projeto Android, então eu criei as classes de modelo diretamente no projeto. Caso o seu objetivo seja trabalhar com múltiplas plataformas, uma melhor prática seria criar as classes de modelo em um projeto separado (Portable Class Library ou Shared Project, por exemplo).

Alterando o título da janela

Com as classes de modelo criadas, vamos ao nosso primeiro desafio de hoje: como alterar o título da janela no Xamarin Android? Quando criamos um novo projeto em branco, o Visual Studio cria automaticamente para a gente uma janela principal vazia. As janelas nos projetos Android são divididas entre layout (interface) e code-behind (implementação da lógica de negócio). Os layouts são definidos nos arquivos “axml” dentro da pasta Resources/layout:
Se abrirmos o arquivo “Main.axml“, veremos que a janela está com o título “ControleDeGastos.Android“, que é o nome que definimos para o nosso projeto:
Procurando pelos lugares no projeto em que a string “ControleDeGastos.Android” estava sendo utilizada, encontrei algumas opções promissoras. A minha primeira tentativa foi mudar o nome da aplicação no manifesto (propriedades do projeto). Quem sabe a janela estava pegando essa informação desse local?
Fechei o designer da janela e abri novamente, porém, ela continuou com o título “ControleDeGastos.Android“. Minha segunda tentativa foi alterar a string “ApplicationName“, que estava presente no arquivo “Strings.xml“:
Também não tive sucesso. Por fim, tentei alterar o conteúdo da propriedade “Label” no atributo da classe “MainActivity“:
Mais uma vez, fechei o designer, abri novamente e nada: o título ainda estava com a string original. Tentei executar a aplicação no emulador e, sabe qual foi o resultado? O título tinha mudado!
Aparentemente só o título no designer é que estava errado! E agora? Qual das alterações fez com que o título fosse realmente alterado em tempo de execução? Depois de fazer alguns testes, eu descobri que foi a alteração da propriedade “Label” (a última alteração que eu fiz). Como você pode ver, o designer não é atualizado quando alteramos essa propriedade:
Esse é um “bugzito” que temos com o designer do Xamarin. Não se esqueça disso antes de passar meia hora tentando descobrir o motivo de o designer não estar atualizando com as últimas informações.

Adicionando um ListView

Para exibirmos a lista de gastos na nossa janela, nós vamos utilizar, a princípio, um controle do tipo ListView. Novos controles podem ser adicionados na tela arrastando-os para o lugar desejado ou editando o arquivo “axml“. Note que na parte inferior da janela, nós podemos alternar entre o modo designer e o modo código fonte:
Vamos adicionar o ListView dentro da janela arrastando-o da caixa de ferramentas:
Feito isso, vamos alterar o nome do ListView para “listViewGastos“. Fazemos isso alterando a propriedade “id” para “@+id/listViewGastos“:
Pode parecer meio esquisito, mas esse é o jeito que definimos os nomes nos controles em projetos Xamarin Android. Tudo o que estiver depois da “barra” representa o nome que utilizaremos para acessar o controle no code-behind. Ah, e não se preocupe quando o nome no título da janela de propriedades não mudar. Esse é mais um “bugzito” do designer do Xamarin. Uma vez fechado e aberto o projeto novamente, o título na janela propriedades deve mudar também.
Enfim, uma vez realizadas essas alterações, se alternarmos para o modo código da janela, obteremos o seguinte resultado:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <ListView
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/listViewGastos" />
</LinearLayout>
Note que o código de layout das janelas nada mais é que um XML especial do Android, que lembra um pouco o XAML do WPF e UWP.

Populando o ListView com uma lista de strings

Com o ListView adicionado na janela, vamos criar uma lista de gastos fictícios em memória para listarmos no controle. O code-behind da janela principal está localizado dentro do arquivo “MainActivity.cs“. Dentro do método “OnCreate” nós teremos a inicialização da nossa janela, e é aí que nós criaremos a lista fictícia de gastos.
Primeiramente, vamos criar um novo método chamado “CarregarGastos“. Mais para a frente nessa série sobre Xamarin, nós veremos como armazenar dados no dispositivo, aí nós ajustaremos esse método para carregar os gastos que foram salvos anteriormente. Porém, por enquanto, esse método criará e retornará uma lista com dois gastos fictícios:
1
2
3
4
5
6
7
8
9
10
11
private List<Models.Gasto> CarregarGastos()
{
    var gastos = new List<Models.Gasto>();
 
    var restaurante = new Models.Estabelecimento() { Id = 1, Nome = "Restaurante" };
    var padaria = new Models.Estabelecimento() { Id = 2, Nome = "Padaria" };
    gastos.Add(new Models.Gasto() { Id = 1, Data = DateTime.Now, Estabelecimento = restaurante, Valor = 15 });
    gastos.Add(new Models.Gasto() { Id = 2, Data = DateTime.Now.AddDays(1), Estabelecimento = padaria, Valor = 3 });
 
    return gastos;
}
Feito isso, nós ajustaremos o código do método “OnCreate” da seguinte maneira (calma que eu já vou explicar o que eu estou fazendo aqui):
1
2
3
4
5
6
7
8
9
10
11
12
protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
 
    var gastos = CarregarGastos();
    var gastosFormatados = gastos.Select(g => string.Format("{0:d} - {1}: {2:n2}", g.Data, g.Estabelecimento.Nome, g.Valor)).ToArray();
 
    SetContentView(Resource.Layout.Main);
 
    var listViewGastos = FindViewById<ListView>(Resource.Id.listViewGastos);
    listViewGastos.Adapter = new ArrayAdapter<string>(this, global::Android.Resource.Layout.SimpleListItem1, gastosFormatados);
}
As duas primeiras linhas depois da chamada de “base.OnCreate” são bem tranquilas. Primeiro, nós chamamos o método que cria a lista de gastos e armazenamos em uma lista chamada “gastos“. Em seguida, nós convertemos esses gastos em uma lista de strings formatadas, juntando a data, nome do estabelecimento e valor dentro de uma única string para cada registro. Nós fazemos isso porque a exibição “padrão” do ListView só aceita strings (no próximo artigo da série nós veremos como exibir outras informações que não sejam strings).
Depois de criamos a lista formatada de gastos, nós temos um passo muito importante, que é o carregamento do layout na Activity. A linha com a chamada de “SetContentView” (que vem inicialmente comentada pelo Visual Studio) faz com que o layout definido em “Main.axml” seja carregado em tempo de execução. Para quem está acostumado a desenvolver com Windows Forms ou WPF, essa chamada é mais ou menos a mesma coisa que o “InitializeComponent” dos formulários.
Em seguida, nós criamos uma variável para acessarmos o “listViewGastos“. Como você pode perceber, nós conseguimos acessar os controles da janela chamando o método “FindByViewId“, passando o “id” que definimos para o controle no arquivo de layout (no nosso caso, “listViewGastos“).
Com o ListView referenciado, nós carregamos o seu conteúdo através da propriedade “Adapter“. Por enquanto, nós estamos configurando um “ArrayAdapter” para essa propriedade. Essa é uma classe padrão do próprio Xamarin Android que possibilita o carregamento de strings em controles do tipo ListView. No próximo artigo da série nós veremos como customizar o ListView e carregar os dados de outra maneira.
O construtor do ArrayAdapter recebe três parâmetros: o contexto (que é a própria Activity), o recurso onde está armazenado o layout para cada item do ListView (que nós estamos trabalhando a princípio com um recurso padrão do Xamarin Android – o “SimpleListItem1“) e um array de strings contendo os elementos que devem ser carregados no ListView.
Execute o projeto e veja o resultado:

Acesse o código no GitHub

Normalmente eu disponibilizo os códigos dos artigos e vídeos somente para as pessoas que se inscrevem na minha newsletter. Porém, como nessa série nós evoluiremos o projeto em cada artigo, achei mais interessante publicar o código no GitHub, onde todos poderão acompanhar a evolução do projeto quando novos artigos forem sendo publicados. Caso você se interesse, acesse o repositório desse projeto no meu GitHub.

Concluindo

No artigo de hoje nós discutimos brevemente sobre as diferenças entre Xamarin Native e Xamarin Forms, bem como uma explicação dos motivos por ter escolhido o Xamarin Native para escrever essa série de artigos. Em seguida, nós criamos o projeto em branco, adicionamos as nossas duas classes de modelo e alteramos o título da janela principal. Por fim, nós adicionamos um ListView na nossa janela e conferimos como podemos carregar uma lista de gastos fictícios nesse ListView.
Daqui há algumas semanas, no próximo artigo dessa série, nós veremos como criar um layout customizado para o nosso ListView, de forma que carreguemos os dados dos nossos gastos sem que precisemos converter tudo para strings.
E aí, o que você está achando da série até agora? Está conseguindo acompanhar? Ficou com alguma dúvida específica? É só falar nos comentários, OK?
Por fim, convido você a inscrever-se na minha newsletter. Ao fazer isso, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário logo abaixo.
Até a próxima!
André Lima

Nenhum comentário:

Postar um comentário