6 - Criação do primeiro projeto

Esse capítulo é dedicado a descrever os passos para a criação do primeiro projeto em Android utilizando Kotlin, além de começar a explorar alguns conceitos básicos, como:

  • Estrutura do projeto Android;
  • Criação e conceitos iniciais da interface gráfica;
  • Definição do comportamento da interface gráfica através do código em Kotlin;
  • View binding.

A ideia desse capítulo é fazer com que o leitor tenha uma introdução desses conceitos para prosseguir com assuntos mais avançados. Por isso, guarde esse projeto, pois ele ainda será bastante utilizado em capítulos adiante.

O aplicativo a ser criado aqui será uma simples tela onde o usuário poderá digitar informações de um produto e, quando desejar, poderá “salvar” (que na verdade não vai salvar em nenhum lugar), exibindo suas informações em caixas de texto na mesma tela:

Tela do aplicativo
Tela do aplicativo

A ideia é fazer um aplicativo de lista de compras, que só pode ter um produto na lista. Obviamente, isso não tem nenhuma utilidade prática, mas tem muitos detalhes que serão utilizados para ensinar os primeiros conceitos.

6.1 - Criando o primeiro projeto

Para criar o primeiro projeto, abra o Android Studio e selecione a opção + Start a new Android Studio project:

Iniciando um novo projeto no Android Studio
Iniciando um novo projeto no Android Studio

Como a ideia desse projeto é apenas dar os passos iniciais, sua estrutura será a mais simples possível, por isso selecione a opção Empty Activity na tela seguinte, dentro da seção Phone and Tablet:

Selecionando a estrutura do projeto
Selecionando a estrutura do projeto

Repare que nessa tela existem outras opções para criação de projetos mais complexos, o que facilita o trabalho inicial na construção de aplicativos com opções de navegação mais sofisticados. Porém, esse não é o caso agora, então a opção Empty Activity é suficiente. Em seguida, clique em Next para passar para a próxima tela:

Configuração do projeto
Configuração do projeto

Nessa última tela existem configurações importantes a serem feitas:

  • Nome do projeto: Esse é o nome que vai aparecer para o usuário quando ele instalar o aplicativo em seu dispositivo;
  • Nome do pacote: O nome do pacote deve ser único para ser publicado na loja do Google, por isso é interessante colocar seu site em notação reversa, seguido do nome do projeto. Porém, para facilitar a condução dos exercícios nesse livro, mantenha o mesmo nome que foi configurado na figura anterior;
  • Local a ser salvo: Escolha um local para salvar o projeto na sua máquina de desenvolvimento;
  • Linguagem: Escolha a linguagem Kotlin;
  • Nível mínimo da API: Essa é uma configuração importante, que define a versão mínima do Android em que o aplicativo irá rodar. Para esse exemplo, escolha a mesma opção da figura anterior.

O nível mínimo da API pode ser alterado posteriormente dentro do projeto, porém é importante saber escolher esse nível, pois, ela definirá a versão mínima do sistema operacional que o aplicativo poderá ser executado. O Android Studio oferece uma estatística da porcentagem de dispositivos atuais capazes de rodar o aplicativo em cada nível de API. Para saber mais sobre qual API corresponde a cada versão do Android, consulte esse link.

Finalize a configuração e peça ao Android Studio para criar o projeto. Após algum tempo, ele estará aberto e pronto para ser trabalhado!

6.2 - Estrutura do projeto

Depois que o projeto é criado, é possível observar sua estrutura no Android Studio, na aba lateral esquerda, chamada Project:

Estrutura do projeto
Estrutura do projeto

Essa é a estrutura básica de um projeto Android. A seguir, algumas informações sobre essa estrutura.

a) Arquivo AndroidManifest.xml: esse arquivo define permissões que o aplicativo necessita para ser executado além de instruções ao sistema Android. Nesse primeiro projeto não será necessário alterá-lo, mas no próximo projeto sim, pois, será necessário solicitar permissão de acesso à Internet;

b) Classe MainActivity: essa é a classe em Kotlin onde será criado o comportamento do aplicativo;

c) Pasta de recursos: imagens, strings, layouts e valores são considerados recursos em projeto Android, e ficam nessa pasta;

d) Scripts do Gradle: aqui estão definidos os arquivos para que o projeto seja compilado utilizando Gradle. A seção seguinte traz mais detalhes sobre esse tópico.

A pasta res está dividida pelo tipo do recurso e a o arquivo activity_main.xml é o que define a interface gráfica do usuário. Ele é um arquivo no formato XML onde os componentes são criados, configurados e ajustados no layout da tela. A seção 6.4 adiante traz mais detalhes sobre esse arquivo.

6.3 - Arquivo build.gradle

O projeto Android utiliza o Gradle como gerenciador de dependências, que são as bibliotecas que podem ser adicionadas para desempenhar diversas funções.

Na pasta Gradle scripts existem dois arquivos build.gradle: um para todo o projeto e outro para o módulo app. Isso faz com que o projeto esteja preparado para múltiplos módulos, que não é alvo desse livro. Para saber mais sobre módulos, consulte esse link.

O arquivo build.gradle (Module: app) é o que define as configurações do módulo app, que nesse caso concentra todo o aplicativo a ser desenvolvido. Nele é possível distinguir 3 seções até o momento:

a) Plugins:

Nessa seção são definidos os plugins necessários para a compilação do projeto. A seguir estão os que foram criados pelo Android Studio:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

b) Configurações de compilação:

Essa seção foi parcialmente definida durante a criação do projeto, quando a versão mínima da API foi definida:

android {
    compileSdk 32
    defaultConfig {
        applicationId "com.example.androidproject01"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), '\
proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

Aqui vale a pena ressaltas as seguintes configurações:

  • applicationId: essa é a identificação única do aplicativo. Esse valor será utilizado caso ele seja publicado na loja do Google;
  • compileSdk: esse valor especifica o nível da API em que o projeto será compilado;
  • minSdk: define o nível mínimo da API que o aplicativo poderá ser executado, que consequentemente define a versão mínima do Android;
  • targetSdk: esse é o valor que indica a versão da API que o aplicativo será testado.

Algumas configurações ainda serão feitas nessa seção para adicionar funcionalidades ao processo de compilação e desenvolvimento do projeto.

c) Dependências:

Nessa seção são colocadas as dependências de bibliotecas que o projeto necessita:

dependencies {
    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

As versão devem ser muito bem escolhidas para não haver incompatibilidade entre elas. Uma dependência que vale a pena ser ressaltada nessa configuração inicial é a biblioteca ConstraintLayout, que facilita muito o desenvolvimento de interfaces gráficas.

Quando novas bibliotecas forem necessárias ao projeto, sejam do próprio Google ou de terceiros, elas deverão ser adicionadas aqui para serem utilizadas pelo projeto.

Para informações mais detalhadas sobre o arquivo build.gradle, consulte a documentação oficial nesse link.

6.4 - Criando a primeira interface gráfica

Como dito anteriormente, as interfaces gráficas em projeto Android são definidas em arquivos XML. O projeto criado possui apenas uma tela, que está no arquivo res\layout\activity_main.xml.

Ao abrir esse arquivo é possível ter três visões, controladas por abas que estão localizadas na parte superior direita da tela:

  • Code: nessa visão é possível editar o arquivo XML e ter uma pré-visualização ao mesmo tempo;
  • Split: aqui é possível visualizar o código e o design da tela ao mesmo tempo;
  • Design: nessa aba é possível visualizar e editar a interface gráfica utilizando os recursos do Android Studio.

Ao selecionar a aba Design, é possível ter uma visualização como a da figura a seguir:

Design da tela
Design da tela

À esquerda estão a paleta de componentes gráficos, que podem ser arrastados para dentro da tela e sua árvore de componentes. No centro, está a visualização da tela, bem como um blue print, onde configurações de layout e espaçamento podem ser observados. Por fim, do lado direito são exibidos os atributos do componente selecionado, bem como as suas configurações de posicionamento na tela.

No Android, é possível criar telas constituídas de vários tipos de layouts, que permitem a organização dos componentes em forma de listas horizontais, listas verticais, grades com colunas e linhas e também com posicionamento relativo entre os componentes.

A tela criada pelo Android Studio possui um layout chamado ConstraintLayout, como pode ser observado dentro do arquivo XML, na aba Text da figura anterior:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.and\
roid.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Esse tipo de layout permite que os componentes fiquem organizados na tela de forma relativa a outros componentes.

Nesse caso, há apenas um componente do tipo TextView, que está posicionado no centro de seu pai, que é a tela inteira. Isso permite que ele sempre fique nessa posição, independente do tamanho da tela ou de sua orientação durante a execução da aplicação. Os atributos que definem esse comportamento são os que estão definidos com os nomes iniciando com app:layout_constraint.

No Android, todos os componentes gráficos são considerados algum tipo de View. Nesse caso, TextViewé uma View especializada em exibição de textos.

Ainda no componente TextView, existem 3 outras propriedades importantes:

  • layout_width: isso define a largura máxima que o componente irá utilizar da tela. A opção wrap_content diz que ele não deve ocupar mais do que o necessário para exibir o conteúdo;
  • layout_height: essa propriedade define a altura máxima que o componente deve ocupar na tela. A opção wrap_content diz que tal altura deve ser o suficiente para exibir o conteúdo;
  • text: esse é o valor que será exibido na tela para o usuário.

Ainda existem outras propriedades que um TextView pode assumir, mas que não fazem parte dessa primeira View.

Todas as propriedades dos componentes, bem como sua organização e criação, podem ser feitas tanto diretamente no arquivo XML, quanto na interface gráfica, na aba Design. O desenvolvedor tem a liberdade de escolher a forma que preferir.

Como o objetivo aqui é desenvolver uma tela, como a do início do capítulo, serão necessários os seguintes componentes:

  • 8 TextView;
  • 4 EditText;
  • 1 Button.

Esses componentes devem ser agrupados de tal forma a criar uma interface gráfica capaz de se adaptar a qualquer tamanho de tela e orientação. E é aí que o ConstraintLayout pode ser utilizado para facilitar esse trabalho.

Para começar, mude para a aba Design e apague o TextView que está na tela.

Utilizando a paleta de componentes do lado esquerdo, escolha o componente TextView e coloque próximo ao topo da tela. Repare que quando o componente é selecionado, aparecem 4 círculos, como na figura a seguir:

Selecionando o TextView
Selecionando o TextView

Esses círculos são utilizados para posicionar o componente em relação a outros componentes ou às bordas da tela, quando se constroi uma interface com base no ConstraintLayout.

Conecte os círculos superior, direito e esquerdo às bordas da tela:

Constraints do TextView
Constraints do TextView

Porém, quando as ligações são feitas com as bordas da tela, o Android assume valores padrões para os atributos dessas ligações, que não são as desejadas para esse componente. Para isso, mantendo o TextView selecionado, vá até a aba Attributes, no canto direito e configure a seção Layout com as seguintes características:

  • Espaçamento superior com o valor 16;
  • Espaçamentos laterais com valor 8;
  • Mude o tipo do espaço lateral para Match Constraints. Isso pode ser feito clicando-se no desenho marcado em azul na figura anterior, entre os dois combo boxes.

Essas configurações farão com que o componente fique afastado de 16 dp do topo, bem como 8 dp das margens laterais. Além disso, o componente irá se adaptar às variações de largura, de acordo com o tamanho da tela ou sua orientação.

Ainda com o TextView selecionado, altere o atributo text, localizado na seção Common Attributes na aba Attributes para o valor Name: . Esse é o valor que será exibido para o usuário na interface gráfica.

Como esse componente não será referenciado pelo código Kotlin, não é necessário definir um identificação única para ele, além da que o próprio Android Studio já definiu.

O próximo componente a ser posicionado na tela é uma caixa de texto que poderá ser editada pelo usuário. Esse componente chama-se EditText , mas aparece com o nome Plain Text na seção Text da paleta de componentes. Selecione-o e arraste-o para logo abaixo do TextView:

Caixa de texto
Caixa de texto

Conecte os círculos laterais às bordas da tela, da mesma forma como foi feito com o TextView. Em seguida, conecte o círculo de sua parte superior ao círculo da parte inferior do TextView:

Constraints do EditText
Constraints do EditText

Da mesma forma como foi feito com o TextView, o novo EditText terá sua largura adaptável ao tamanho da tela e sua orientação. Porém, ele sempre estará próximo ao TextView, fazendo que a interface gráfica se mantenha coerente independente dessas mudanças.

Existem apenas mais duas configurações a serem feitas nesse EditText:

  • Remova o valor do atributo text, que está o valor Name. Esse é o local onde o usuário irá digitar o nome do produto, por isso deve estar vazio desde o início;
  • Configure o atributo id, localizado no topo da aba Attributes, para o valor edtName. Esse será o valor no qual esse componente poderá ser referenciado de dentro do código Kotlin.

A ideia é ler o valor que o usuário digitou nesse campo, por isso ele deve possuir uma identificação única para ser localizado de dentro do código Kotlin.

Acrescente mais 3 conjuntos de TextView e EditText para representar os campos de descrição, código e preço do produto. Configure o atributo id dos componentes EditText seguintes com os seguintes valores:

  • Descrição do produto: edtDescription
  • Código do produto: edtCode
  • Preço do produto: edtPrice

O componente para edição do preço do produto merece uma atenção especial, afinal, seria interessante exibir um teclado diferente ao usuário, uma vez que ele irá digitar um valor decimal. Isso pode ser feito configurando o atributo inputType para o valor numberDecimal. Isso fará com que o usuário possa digitar apenas números decimais para o preço, ao invés de letras, o que faz todo o sentido.

Logo abaixo do último EditText, que é do preço, posicione um botão, como na figura a seguir:

Posicionando o botão
Posicionando o botão

Repare que o botão está está conectado à última caixa de texto e à borda da tela, como pode ser observado na seção Layout da seção Attributes. Veja também seu id foi definido para btnSave, pois será necessário referenciá-lo no código Kotlin.

Para deixar o botão com esse estilo, basta alterar o atributo style para o valor @style/Widget.AppCompat.Button.Colored. Esse é um dos estilos pré-definidos do Android.

Além disso, configure também seu texto para Save.

Agora posicione mais 4 TextView logo após o botão. Eles servirão para exibir os detalhes do produto, depois que o usuário pressionar o botão Save. Veja como deve ficar:

Detalhes do produto
Detalhes do produto

Coloque um valor fixo para o atributo text desses novos TextView. Isso dará um efeito didático para a demonstração do funcionamento do aplicativo, da forma como ele será construído.

Defina um id para cada desses novos 4 TextView:

  • Nome do produto: txtName
  • Descrição do produto: txtDescription
  • Código do produto: txtCode
  • Preço do produto: txtPrice

Definir uma identificação única para esses novos 4 TextView é essencial, pois eles terão seus valores modificados pelo código Kotlin, quando o usuário clicar no botão Save.

Ainda existem algumas configurações necessárias para essa tela, que são:

  • Colocar todos os componentes dentro de um outro componente capaz de fazer a tela rolar, caso ela seja exibida em um dispositivo pequeno ou quando simplesmente não houver espaço para mostrar todos os componentes;
  • Transformar as strings que aparecem na tela, em recursos capazes para facilitar a tradução.

O componente capaz de fazer a tela rolar chama-se ScrollView, e deve englobar todos os elemento da tela, inclusive o componente do tipo ConstraintLayout. Para fazer isso, estando com o arquivo activity_main.xml aberto, mude para a aba Code, localizada na parte superior direita da tela, para poder alterar o arquivo XML manualmente.

Agora vá até o início do arquivo e altere-o para ficar como o trecho a seguir:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:context=".MainActivity">

Da mesma forma, altere o fim do arquivo para finalizar as tags XML corretamente para esses dois componentes:

    </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

Lembre-se de ajustar a tabulação do arquivo o final das alterações.

Essa modificação faz com que todos os componentes da tela, incluindo o gerenciador de layouts ConstraintLayout fique dentro de ScrollView, tornando a tela capaz de rolar caso não haja espaço para mostrar todos os componentes.

A segunda alteração que deve ser feita no arquivo XML, é a extração das strings que estão fixas no código, tornando-as recursos que podem ser traduzidos para outros idiomas. Perceba que o Android Studio ressalta essas strings no arquivo activity_main.xml, como mostra a figura a seguir:

Strings com valores fixos
Strings com valores fixos

Da forma como está, não é possível traduzir o aplicativo para outros idiomas. Então, para extrair essa e as demais strings para a pasta de recursos, clique na lâmpada amarela localizada à esquerda e escolha a opção Extract string resource.

Na tela que aparecer, digite o nome do novo recurso, por exemplo str_name. Perceba que o arquivo com o nome onde recurso será salvo é strings.xml, localizado na pasta res\values do projeto:

Criando o recurso de string
Criando o recurso de string

Se o projeto já tiver mais que um idioma, ele aparecerá na lista na parte inferior dessa tela. Clique em OK e repita o processo para os demais atributos text desse arquivo, até que todas as strings que estão fixas nesse arquivo sejam extraídas.

Em seguida, vá até o arquivo res\values\strings.xml e perceba que as strings que foram extraídas agora estão lá:

<resources>
    <string name="app_name">AndroidProject01</string>
    <string name="str_name">Name:</string>
    <string name="str_description">Description:</string>
    <string name="str_code">Code:</string>
    <string name="str_price">Price:</string>
    <string name="str_save">Save</string>
    <string name="str_empty">empty</string>
</resources>

Esse então é o arquivo padrão para os recursos de string. Cada idioma que for acrescentado ao projeto, terá um arquivo igual a esse, traduzido para esse idioma.

Para verificar como a tela ficou, execute a aplicação no emulador ou em um dispositivo real. Gire o aparelho e verifique que é possível rolar a tela, para exibir os componentes que possivelmente não cabem na tela.

6.5 - Criando o comportamento da interface gráfica

Agora que a interface gráfica já foi construída, é hora de adicionar algum comportamento a ela. A ideia por enquanto é simples, para seguir com a didática proposta no capítulo:

  • O usuário irá digitar os detalhes do produto desejado nos 4 campos superiores da tela;
  • Quando finalizar, ele deverá clicar no botão Save;
  • Essa ação fará com que a aplicação leia os dados digitados pelo usuário e exiba-os adequadamente nas caixas de texto abaixo do botão Save.

Não se preocupe se esse aplicativo não tem uma função prática. O objetivo é mostrar como criar um código em Kotlin capaz de interagir com a tela e as ações do usuário.

Para começar, vá até o arquivo MainActivity. Ele deve estar semelhante ao trecho de código a seguir:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Essa classe representa uma Activity no Android, que é responsável por exibir e definir os comportamentos de uma tela da aplicação. Porém, ela não é uma classe qualquer, pois ela estende de AppCompatActivity, como pode ser visto em sua declaração. Isso faz com que ela tenha métodos especiais que serão invocados pelo sistema Android.

Um dos métodos especiais dessa classe é o onCreate. Ele é chamado pelo sistema Android toda vez que a Activity deve ser criada, que pode acontecer em algumas situações como:

  • Quando o usuário deseja executar a aplicação, clicando no seu ícone;
  • Quando o usuário gira o aparelho, colocando-o em modo paisagem;
  • Quando o usuário altera a configuração de idioma do aparelho e a tela precisa ser redesenhada.

As duas últimas condições são chamadas de alteração de configuração da tela. Quando isso acontece, a tela precisa ser redesenhada totalmente, pois houve uma configuração em que não é possível alterar sua aparência sem destruí-la e recriá-la novamente. O capítulo seguinte irá tratar esse assunto com um pouco mais de detalhe. O importante agora é saber que esse método é chamado quando a tela precisa ser criada.

Veja também que o método onCreate recebe um parâmetro chamado savedInstanceState do tipo Bundle. Ele também será detalhado no capitulo seguinte.

Dentro desse método existe a instrução setContentView, que recebe como parâmetro um recurso de layout para ser exibido, que é justamente a tela activity_main que estava sendo construída na seção anterior desse capítulo. Essa instrução é a responsável por, finalmente, exibir a tela dentro da Activity para o usuário.

6.5.1 - View binding

Agora que a tela já está sendo exibida para o usuário, pode-se começar a criar o código para interagir com ela, mas para isso é necessário criar as referências dos componentes gráficos dentro da classe ActivityMain. Dessa forma, o código em Kotlin poderá manipulá-los.

Existem algumas formas diferentes para a criação das referências dos componentes gráficos dentro do código Kotlin. Uma das formas mais modernas até o momento é a utilização de uma técnica chamada View binding. Para implementar essa técnica é necessário realizar os seguintes passos:

a) Indicar ao Android Studio que o projeto deve utilizar a técnica:

Para isso, abra o arquivo build.gradle , vá até a seção android e acrescente a subseção dataBinding no final, como no trecho a seguir:

    dataBinding {
        enabled = true
    }
}

O Android Studio solicitará que o projeto seja sincronizado novamente, através de uma mensagem no canto superior direito da tela. Execute esse passo para que o projeto seja preparado para se trabalhar com View Binding.

b) Envolver o componente ScrollView de activity_main em um componente do tipo layout:

Para isso, abra o arquivo activity_main.xml e altere seu início para ficar com o trecho a seguir:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

Da mesma forma, altere seu fim para que as tags do XML fechem corretamente:

    </ScrollView>
</layout>

Isso fará com que o Android Studio gere as classes necessárias para representar todos os componentes dessa tela, facilitando muito o trabalho a ser desenvolvido na classe MainActivity.

c) Criar o atributo ActivityMainBinding na classe MainActivity:

Depois que os passos anteriores foram realizados, o Android Studio gera automaticamente uma classe do tipo ActivityMainBinding , que contém a referência para todos os componentes gráficos da tela definida em activity_main.xml. Os identificadores únicos que foram definidos nesse arquivo são utilizados para definir os nomes das referências dentro de ActivityMainBinding.

Agora, basta criar um atributo desse tipo dentro da classe MainActivity, como no trecho a seguir:

import br.com.siecola.androidproject01.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

A última linha do trecho anterior é a criação do atributo do tipo ActivityMainBinding, da classe MainActivity. Repare que ele está com o modificador lateinit, para garantir o Kotlin que ele será inicializado antes de ser utilizado. Sem isso, o compilador geraria um erro.

Finalizando, para que esse atributo seja inicializado, é necessário associá-lo com o recurso de layout de tela que será exibido. Isso deve ser feito dentro do método onCreate, logo após a instrução super.onCreate(savedInstanceState), como no trecho a seguir:

binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

Essa instrução deve substituir a que estava em seu lugar:

setContentView(R.layout.activity_main)

Ou seja, essa linha deve ser removida dessa função.

A partir desse ponto, o atributo binding possui todas as referências dos componentes criados em activity_main.xml, e podem ser utilizados para a definição do comportamento dessa tela.

6.5.2 - Criando o comportamento da tela

As seguintes ações podem ser seguidas para definir o comportamento da tela de uma aplicação Android:

  • Reagir ao evento de clique em um botão;
  • Ler uma caixa de texto editável com o valor digitado pelo usuário;
  • Atualizar um conteúdo em uma caixa de texto;
  • Alterar uma imagem em um ImageView.
  • E vários outros.

Cada evento pode ser tratado e implementado de forma diferente, dependendo do componente e do evento, mas a ideia principal é indicar ao componente que existe uma função especial que deve ser invocada quando o evento acontecer.

Para exemplificar, pegue a referência do botão btnSave dentro do atributo binding da classe ActivityMain , criado em activity_main.xml e configure-o para executar uma função que imprime uma mensagem de log, como no trecho a seguir, que deve ser colocado no final da função onCreate:

binding.btnSave.setOnClickListener {
	Log.d("MainActivity", "Save button pressed")
}

Basicamente, esse trecho executa os seguintes passos:

  • Pega o atributo binding, que possui todas as referências dos componentes gráficos criados em activity_main.xml;
  • Acessa o componente de identificação btnSave;
  • Define o comportamento para o listener invocado quando o botão é clicado para executar a função anônima delimitada por { };
  • Dentro dessa função anônima, a instrução Log.d("MainActivity", "Save button pressed") imprime uma mensagem de log.

A classe Log é a responsável por imprimir mensagens no Logcat do Android Studio. O primeiro parâmetro é chamado de tag, que é utilizado para diferenciar mensagens de contextos diferentes. Normalmente esse parâmetro leva o nome da classe em que está sendo executado. O segundo parâmetro é a mensagem em si.

Para testar essa implementação, execute a aplicação novamente. Assim que ela estiver rodando, clique no botão Save e veja que o log foi impresso no Logcat, localizado nessa aba na parte inferior do Android Studio:

Exibindo uma mensagem de log
Exibindo uma mensagem de log

Tenha certeza de selecionar o dispositivo correto, bem como o nome do aplicativo e configurar o filtro de mensagens para D/MainActivity, que é o nível de log em debug e o nome da classe que o gerou.

Agora que o evento de clique no botão btnSave está funcionando, é possível finalizar a implementação desse aplicativo, exibindo os detalhes do produto, que foram digitados pelo usuário, nas caixas de texto localizadas após o botão de salvar. Para isso, acrescente o seguinte trecho de código na função que trata o evento de clique do botão btnSave:

binding.txtName.text = binding.edtName.text
binding.txtDescription.text = binding.edtDescription.text
binding.txtCode.text = binding.edtCode.text
binding.txtPrice.text = binding.edtPrice.text

Como o atributo da classe binding possui a referência de todos os componentes da tela, basta acessar cada uma das caixas de texto editáveis, os EditText, buscando pela propriedade text e atribuir seu valor ao TextView correspondente. Isso fará com que a informação digitada pelo usuário seja exibida no final da tela.

Veja como deve ficar toda a classe MainActivity:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.databinding.DataBindingUtil
import br.com.siecola.androidproject01.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        binding.btnSave.setOnClickListener {
            Log.d("MainActivity", "Save button pressed")

            binding.txtName.text = binding.edtName.text
            binding.txtDescription.text = binding.edtDescription.text
            binding.txtCode.text = binding.edtCode.text
            binding.txtPrice.text = binding.edtPrice.text
        }
    }
}

Para testar a implementação, execute novamente a aplicação, preencha os campos com os detalhes de um produto qualquer e clique no botão Save. Os campos de texto deverão ficar preenchidos com tais informações, como mostra a figura a seguir:

Testando a aplicação
Testando a aplicação

Essa aplicação poderia ficar melhor. Pelo menos poderia tratar a condição quando o usuário não digitar um valor para o nome do produto, considerando que somente ele fosse necessário. Nesse caso, uma mensagem de erro poderia ser lançada na tela. Para isso, acrescente uma condição para validar esse teste:

if (!binding.edtName.text.isEmpty()) {
    binding.txtName.text = binding.edtName.text
    binding.txtDescription.text = binding.edtDescription.text
    binding.txtCode.text = binding.edtCode.text
    binding.txtPrice.text = binding.edtPrice.text
} else {
    Toast.makeText(this, "Please, enter the name.", Toast.LENGTH_SHORT).show()
}

Na primeira linha desse trecho, foi verificado se o atributo text do componente edtName não está vazio. Se ele não estiver, significa que o usuário digitou algo nesse campo e então os detalhes do produto podem ser lidos.

Caso não haja informação dentro do atributo text de edtName, uma mensagem é lançada na tela, através da instrução Toast.makeText. Essa instrução recebe os seguintes parâmetros:

  • Uma referência da Activity na qual a mensagem deve aparecer;
  • A mensagem de texto em si;
  • A duração em que a mensagem deve ficar exibida na tela.

Por último, o método .show() é chamado para exibir a mensagem na tela ao usuário.

Por fim, para manter a estratégia coerente de possibilitar que esse aplicativo seja traduzido para outros idiomas, é necessário adicionar a string Please, enter the name como um recurso do projeto. Isso pode ser feito colocando o cursor sobre esse texto e acessando a opção Extract string resource da lâmpada amarela que aparecer do lado esquerdo. Para finalizar, basta digitar um nome para o recurso, por exemplo str_enter_name.

Com essa última modificação, o Android Studio se encarrega de alterar o código Kotlin para buscar a string do recurso definido, como pode ser visto no trecho a seguir:

Toast.makeText(this, getString(R.string.str_enter_name), Toast.LENGTH_SHORT).show()

Quando esse aplicativo for traduzido para outros idiomas, o Android se encarregará de pegar o texto no idioma correto para ser exibido.

6.6 - Conclusão

Esse capítulo apresentou alguns conceitos iniciais de um projeto Android, bem como os passos para a construção de interfaces gráficas utilizando o ConstraintLayout, o que faz com que a tela fique adaptável a diversos tamanhos de dispositivos.

Também apresentou o conceito de View binding, uma técnica moderna que facilita a associação e utilização das referências dos componentes gráficos dentro do código em Kotlin.

Por fim, iniciou o leitor na construção de comportamentos da aplicação, com interação direta com a interface gráfica do usuário.

O próximo capítulo traz conceitos mais aprofundados sobre Activity, introduzindo conceitos de ciclo de vida e gerenciamento de seus estados.