Escolar Documentos
Profissional Documentos
Cultura Documentos
AULA 6
● app/build.gradle
dependencies {
...
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
Figura 1 – Dependência
● activity_main.xml
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Pronto, feito isso execute o projeto novamente para validar se as
configurações foram feitas com sucesso. Se tudo funcionar, você verá uma tela
vazia, pois o RecyclerView é uma lista e, por enquanto, está vazia.
Crédito: Brostock/Shutterstock.
Para que você consiga visualizar o nosso objetivo, vamos criar uma lista
com três views, conforme mostra a próxima figura.
Crédito: Brostock/Shutterstock.
Seguindo o mesmo raciocínio, para facilitar o seu entendimento de quais
arquivos vamos criar neste exercício e do local que você precisa criar os
arquivos, veja a figura a seguir.
package com.example.hellotarefas
import java.io.Serializable
) : Serializable
package com.example.hellotarefas
object TarefaService {
init {
for (i in 1..3) {
tarefas.add(Tarefa(i,"Tarefa $i"))
}
}
package com.example.hellotarefas
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
Agora, vamos falar da classe Adapter. Essa classe contém a lógica para
preencher o conteúdo de cada célula, ou seja, preencher o conteúdo de cada
linha da lista. O adapter também é uma dupla formada pela classe Kotlin ou Java,
e o layout XML que será utilizado na célula.
Lembra da figura na qual mostramos os arquivos que vamos criar neste
exemplo? Veja-a novamente e perceba o local da classe TarefaAdapter e seu
layout XML adapter_tarefa.xml.
Dito isso, vamos criar o arquivo XML de layout para o adapter. Para isso,
utilize o wizard > New > File e digite '.xml' na extensão ao criar o arquivo. Como
padrão, os arquivos utilizados como Adapter (célula de uma lista) começam com
a palavra 'adapter_', portanto, o nome do arquivo é adapter_tarefa.xml.
● /res/layout/adapter_tarefa.xml
<TextView
android:id="@+id/tId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<TextView
android:id="@+id/tTitulo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
</LinearLayout>
package br.com.livroandroid.tarefas.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.hellotarefas.Tarefa
import com.example.hellotarefas.R
import kotlinx.android.synthetic.main.adapter_tarefa.view.*
package com.example.hellotarefas
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import br.com.livroandroid.tarefas.adapter.TarefaAdapter
import kotlinx.android.synthetic.main.activity_main.*
● /res/layout/adapter_tarefa.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<TextView
android:id="@+id/tTitulo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
Crédito: Brostock/Shutterstock.
view.setOnClickListener { }
● TarefaAdapter.kt
Crédito: Brostock/Shutterstock.
● MainActivity
package com.example.hellotarefas
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import br.com.livroandroid.tarefas.adapter.TarefaAdapter
import kotlinx.android.synthetic.main.activity_main.*
Crédito: Brostock/Shutterstock.
recyclerView.adapter = TarefaAdapter(tarefas, {
tarefa -> onClickTarefa(tarefa)
})
Neste caso, aquela variável tarefa seguida da seta pode ser omitida, pois
no Kotlin podemos usar o parâmetro it, que é implícito. Naturalmente, a variável
it só pode ser usado se a função possui apenas um único parâmetro, que é este
caso.
recyclerView.adapter = TarefaAdapter(tarefas, {
onClickTarefa(it)
})
Por fim, veja no código anterior que a lambda ficou dentro dos parênteses,
pois ela é um argumento como outro qualquer que é enviado no construtor da
classe TarefaAdapter. Mas, como também já estudamos, sempre que a lambda
for o último argumento, podemos abrir e fechar as chaves depois dos parênteses
com esta sintaxe:
recyclerView.adapter = TarefaAdapter(tarefas) {
onClickTarefa(it)
}
● Activity-Extensions.kt
package com.example.hellotarefas.extensions
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
Pronto! Agora, para fazer um toast, fica bem simples. Lembre-se que para
utilizar extensões, precisamos fazer o import, mas isso o Android Studio sempre
vai nos ajudar.
package com.example.hellotarefas
import com.example.hellotarefas.extensions.toast
Crédito: Brostock/Shutterstock.
O primeiro passo para criar o cadastro de tarefas é criar a tela que possui
o formulário para inserir ou editar uma tarefa. Essa tela, como você já sabe, será
uma nova activity, que vamos chamar de TarefaActivity.
Crie essa activity com o wizard > New > Activity > Empty Activity. Ao
utilizar o wizard, a activity será configurada automaticamente no arquivo de
manifesto:
Feito isso, vamos criar o formulário que vai conter o título da tarefa. No
formulário, não vamos mostrar o id da tarefa, ele ficará escondido para simular
o id do banco de dados.
● /res/layout/activity_tarefa.xml
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Título" />
<EditText
android:id="@+id/tTitulo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/btSalvar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Salvar" />
</LinearLayout>
● TarefaActivity
package com.example.hellotarefas
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_tarefa.*
package com.example.hellotarefas
import java.io.Serializable
) : Serializable
Observe que ao ler o parâmetro tarefa da intent, foi feito o casto para
Tarefa? com a interrogação, o que indica que este objeto pode ser nulo.
Pela regra deste aplicativo fictício, a tela com o formulário pode ser
chamada em duas situações:
Algo interessante deste exemplo e que ainda não tínhamos visto está lá
no método onCreate() da activity:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
app:tint="@android:color/white"
android:src="@android:drawable/ic_input_add"
android:layout_margin="16dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
package com.example.hellotarefas
...
import kotlinx.android.synthetic.main.activity_main.*
fab.setOnClickListener { onClickAddTarefa() }
}
import com.example.hellotarefas.Tarefa
object TarefaService {
init {
for (i in 1..3) {
tarefas.put(i, Tarefa(i,"Tarefa $i"))
count = i
}
}
fun save(t: Tarefa) {
if(t.id == 0) {
// Gera um id
t.id = ++count
}
tarefas.put(t.id, t)
}
fun remove(tarefa: Tarefa) {
tarefas.remove(tarefa.id)
}
fun getTarefas(): List<Tarefa> {
return tarefas.values.toList()
}
}
● MainActivity
package com.example.hellotarefas
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import br.com.livroandroid.tarefas.adapter.TarefaAdapter
import kotlinx.android.synthetic.main.activity_main.*
fab.setOnClickListener { onClickAddTarefa() }
}
override fun onResume() {
super.onResume()
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_tarefa.*
btSalvar.setOnClickListener { onClickSalvar() }
}
private fun setTarefa(tarefa: Tarefa?) {
if(tarefa != null) {
tTitulo.setText(tarefa.titulo)
}
}
// Cria os itens de menu na App Bar (ex: botão deletar)
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_tarefa, menu)
val item = menu?.findItem(R.id.action_delete)
if(item != null) {
item.setVisible(tarefa != null)
}
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> {
finish()
}
R.id.action_delete -> {
onClickDeletar()
}
}
return super.onOptionsItemSelected(item)
}
private fun onClickSalvar() {
val tarefa = getTarefa()
TarefaService.save(tarefa)
finish()
}
private fun onClickDeletar() {
tarefa?.let {
TarefaService.remove(it)
finish()
}
}
private fun getTarefa(): Tarefa {
val n = this.tarefa?: Tarefa()
n.titulo = tTitulo.text.toString()
return n
}
}
Esperamos que a maior parte desse código seja tranquila para você, pois
já fizemos um exemplo parecido de cadastro nas primeiras aulas. Então, vamos
ao que é mais importante.
Primeiramente, o método onCreateOptionsMenu(menu) é responsável
por configurar os botões que vão aparecer na App Bar, e para isso, temos que
criar outro arquivo XML, que vai conter essas ações. Crie uma pasta menu
dentro da pasta res e crie o arquivo menu_tarefa.xml conforme indicado na
figura a seguir:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_delete"
app:showAsAction="always"
android:icon="@android:drawable/ic_delete" />
</menu>
O XML de menu contém os itens de menu que vão aparecer na App Bar,
que no nosso caso é apenas o botão de deletar. A figura do botão deixamos com
aquele ícone de (X) padrão do Android e o id foi configurado como
action_delete. Esse id é usado para tratar o evento de quando o usuário tocar
neste item de menu lá no método onOptionsItemSelected(item).
R.id.action_delete -> {
onClickDeletar()
}
Outro ponto importante de código: veja que o objeto Tarefa foi deixado
como atributo da classe, pois precisamos acessar ele dentro dos métodos
onClickSalvar() e onClickDeletar(), assim, esse objeto possui um escopo
global dentro da classe.
Dito isso, existem duas lógicas pequenas dentro dos métodos de salvar e
deletar.
No método onClickSalvar(), é utilizado o operador Elvis explicado na aula
de Kotlin para criar o objeto tarefa. O objetivo é utilizar o objeto tarefa se ele já
existe para atualizar os dados, ou criar uma nova instância do objeto caso ele
não exista. Isso é feito nesta linha:
FINALIZANDO