Neste tutorial, vamos analisar a criação e utilização de uma visão personalizada do reciclador com caixas de seleção ou radiobuttons e como lidar com seus estados.
Conceitos que você irá aprender
Este tutorial, através de exemplos, visa ajudar você a aprender o seguinte:
- Como criar uma visão do reciclador com caixas de seleção ou radiobuttons e lidar adequadamente com seus estados.
- Como renderizar dados do banco de dados mysql, incluindo dados booleanos, em uma vista de reciclagem com caixas de seleção.
- Como pesquisar/filtrar a vista do reciclador com caixas de seleção enquanto mantém seus estados marcados/desmarcados.
Demos
Aqui estão algumas das demonstrações que serão criadas:
**CheckBox Demo***
**RadioButton Demo***
Exemplo 1: Android RecyclerView CheckBoxes - Manter Estados verificados
Este é um tutorial de visualização de andróides para recicladores. Queremos ver como primeiro renderizar caixas de seleção, imagens e textos em uma visão personalizada de reciclagem com visualizações de cartões. Em seguida, obtenha as visões de cartão selecionadas ou verificadas e mostre n uma mensagem de brinde. Trabalhamos com várias caixas de seleção para que possamos selecionar vários itens em nosso RecyclerView.
Isto nos ensinará como reter corretamente os estados marcados de nossas caixas de seleção em nossa visão de reciclagem, apesar da reciclagem de nossas visões de cartão com caixas de seleção.
Então, o usuário pode clicar em um botão de ação flutuante para obter os itens selecionados e mostrá-los em uma mensagem de brinde.
Estamos Construindo uma Comunidade Vibrante no YouTube
Aqui está este tutorial em formato de vídeo.
Etapa 1: Dependências
Não precisamos de nenhuma dependência especial para este projeto. Tudo o que utilizamos são as dependências padrão dos andróides, como a vista da reciclagem e a vista do cartão.
Passo 2: Criar o layout da atividade principal
activity_main.xml
Este será nosso principal layout de atividade e nós escrevemos em XML. XML é uma linguagem de marcação que não só é usada para criar interfaces de usuário, mas também dados extecnológicos, neste caso usamos para criar nossa interface de usuário androide.
Este layout será inflado em nossa atividade principal. Na raiz, teremos um RelativeLayout.
Temos um TextView que é nosso cabeçalhoTextView para exibir o cabeçalho de nossa aplicação androide.
Depois temos um RecyclerView que, neste caso, é a nossa visão do adaptador. Este RecyclerView irá renderizar imagens, textos e caixas de seleção.
Abaixo do RecyclerView teremos um Botão de Ação Flutuante. Quando os usuários clicarem neste botão FAB, mostraremos os itens que foram selecionados na Recyclerview. Lembre-se de que nossa visão da recicladora será composta de visualizações de cartões que possuem imagens, textos e caixas de seleção.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
tools_context="info.camposha.checkablerecyclerviews.MainActivity">
<TextView
android_id="@+id/headerTextView"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="Spiritual Teachers"
android_textAlignment="center"
android_textAppearance="@style/TextAppearance.AppCompat.Large"
android_textColor="@color/colorAccent" />
<androidx.recyclerview.widget.RecyclerView
android_id="@+id/myRecycler"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentStart="true"
android_layout_below="@+id/headerTextView"
android_layout_marginTop="30dp" />
<android.support.design.widget.FloatingActionButton
android_id="@+id/fab"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentBottom="true"
android_layout_alignParentEnd="true"
android_layout_alignParentRight="true"
android_layout_gravity="bottom|end"
android_src="@android:drawable/ic_dialog_email" />
</RelativeLayout>
Passo 3: Criar um item RecyclerView
model.xml
Este layout modelará uma única visualização de cartão a ser entregue entre outros cartões em nossa visão de reciclagem.
Este layout irá modelar todas estas visualizações de cartões. Na raiz, temos o CardView como nosso elemento. O CardView reside no namespace android.support.v7.widget
.
Eu configurei a elevação do CardView para 5dp
e o raio do CardView para 10dp
.
Dentro dele, tenho um RelativeLayout para organizar meus widgets em relação uns aos outros.
Primeiro temos o ImageView para renderizar nossa imagem. Em seguida, o TextViews para renderizar nossos textos.
À extrema direita de nosso CardView teremos um CheckBox que conterá a propriedade de seleção de cada CardView. As CheckBoxes podem ser verificadas ou desmarcadas.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
android_orientation="horizontal" android_layout_width="match_parent"
android_layout_margin="5dp"
card_view_cardCornerRadius="10dp"
card_view_cardElevation="5dp"
android_layout_height="match_parent">
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent">
<ImageView
android_layout_width="150dp"
android_layout_height="150dp"
android_id="@+id/teacherImageView"
android_padding="5dp"
android_src="@drawable/cle" />
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceLarge"
android_text="Teacher Name"
android_id="@+id/nameTextView"
android_padding="5dp"
android_textColor="@color/colorAccent"
android_layout_alignParentTop="true"
android_layout_toRightOf="@+id/teacherImageView" />
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceMedium"
android_text="Teacher Description..."
android_id="@+id/descritionTextView"
android_padding="5dp"
android_layout_alignBottom="@+id/teacherImageView"
android_layout_toRightOf="@+id/teacherImageView" />
<CheckBox
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_id="@+id/myCheckBox"
android_layout_alignParentRight="true"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
Passo 4: MainActivity.java
Especificar o pacote e adicionar Importações
Nossa classe java residirá em um pacote, portanto especificamos um e acrescentamos as importações apropriadas.
Estes incluem nosso RecyclerView do pacote android.support.v7.widget
e CheckBox do pacote android.widget
.
package info.camposha.checkablerecyclerviews;
import android.content.Context;
import android.support.design.widget.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
Criar Atividade
Uma atividade é um componente andróide que representa uma interface de usuário.
Para transformar nossa classe comum em uma atividade, nós a faremos derivar de `AppCompatActivity':
public class MainActivity extends AppCompatActivity {..}
Criar nosso POJO
Em seguida, criaremos uma classe POJO, Objeto Java simples OLd. Isto representará um único Objeto Professor.
Cada SpiritualTecaher terá várias propriedades. Cada objeto será renderizado em seu próprio CardView em nosso RecyclerView.
public class SpiritualTeacher {
//our properties.
}
Uma dessas propriedades será a propriedade 'isSelected', um valor booleano que nos manterá o estado verificado do nosso CardView.
Criar nosso View Holder
Vamos criar nossa classe RecyclerView ViewHolder derivando da classe RecyclerView.ViewHolder
.
Também a classe estará implementando a interface View.OnClickListener
. Isto nos permitirá capturar os eventos de clique de cada CardView.
static class MyHolder extends RecyclerView.ViewHolder implements View.OnClickListener{...}
Criar Adaptador RecyclerView
Em seguida, criamos nossa classe RecyclerView.Adapter, a classe que será nossa classe adaptador.
static class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> {..}
Como uma classe adaptadora, esta classe tem duas funções principais:
- Insuflar nosso Layout de Modelo Personalizado em um Objeto de Visualização.
- Ligar o conjunto de dados a nossas vistas inflacionadas.
Os dados a serem vinculados virão de uma matriz personalizada, neste caso, uma matriz de Professores Espirituais:
public MyAdapter(Context c, SpiritualTeacher[] teachers) {
this.c = c;
this.teachers = teachers;
}
Esta classe também manterá um arrailista que segurará nossos artigos de batota.
ArrayList<SpiritualTeacher> checkedTeachers=new ArrayList<>();
Os usuários verificarão os itens de reciclagem e nós mantemos os itens verificados neste arraylist. Mais tarde, poderemos exibir estes itens checados em uma mensagem de brinde.
Inflacionar o layout em Vista
Isto acontecerá em nosso adaptador RecyclerView, como combinamos. Precisamos de uma classe 'LayoutInflater' para fazer isso.
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model,null);
MyHolder holder=new MyHolder(v);
return holder;
}
Então, como você pode ver, passamos o objeto de visão inflada para nosso construtor RecyclerView ViewHolder.
Em seguida, devolvemos a instância "View Holder".
Dados Vinculativos
Nós ligamos os dados dentro do método 'onBindViewHolder':
@Override
public void onBindViewHolder(MyHolder holder, int position) {
final SpiritualTeacher teacher=teachers[position];
holder.nameTxt.setText(teacher.getName());
holder.posTxt.setText(teacher.getQuote());
holder.myCheckBox.setChecked(teacher.isSelected());
holder.img.setImageResource(teacher.getImage());
...
}
Primeiro recebemos a posição do item em nossa visão de reciclagem e a utilizamos para obter o professor atual de nossa matriz.
Depois definimos os widgets TextView, imageView e CheckBox com valores daquele objeto.
Manter Itens Checked e UnChecked
Em seguida, ouvimos os eventos de nosso CardView com clique. Obviamente, clicar no CheckBox mudará o estado dessa caixa de seleção.
Nós verificamos essas mudanças. Se a caixa de seleção for clicada, adicionaremos o item em nosso arraylist.
Se estiver desmarcada, removeremos o item do arraylist.
holder.setItemClickListener(new MyHolder.ItemClickListener() {
@Override
public void onItemClick(View v, int pos) {
CheckBox myCheckBox= (CheckBox) v;
SpiritualTeacher currentTeacher=teachers[pos];
if(myCheckBox.isChecked()) {
currentTeacher.setSelected(true);
checkedTeachers.add(currentTeacher);
}
else if(!myCheckBox.isChecked()) {
currentTeacher.setSelected(false);
checkedTeachers.remove(currentTeacher);
}
}
});
Vejamos o código fonte completo.
Código completo
Aqui está o código completo da MainActivity.
package info.camposha.checkablerecyclerviews;
import android.content.Context;
import android.support.design.widget.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
public class SpiritualTeacher {
private String name,quote;
private int image;
private boolean isSelected;
public SpiritualTeacher(String name, String quote, int image) {
this.name = name;
this.quote = quote;
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getQuote() {
return quote;
}
public int getImage() {
return image;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
}
static class MyHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView img;
TextView nameTxt,posTxt;
CheckBox myCheckBox;
ItemClickListener itemClickListener;
public MyHolder(View itemView) {
super(itemView);
nameTxt= itemView.findViewById(R.id.nameTextView);
posTxt= itemView.findViewById(R.id.descritionTextView);
img= itemView.findViewById(R.id.teacherImageView);
myCheckBox= itemView.findViewById(R.id.myCheckBox);
myCheckBox.setOnClickListener(this);
}
public void setItemClickListener(ItemClickListener ic)
{
this.itemClickListener=ic;
}
@Override
public void onClick(View v) {
this.itemClickListener.onItemClick(v,getLayoutPosition());
}
interface ItemClickListener {
void onItemClick(View v,int pos);
}
}
static class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> {
Context c;
SpiritualTeacher[] teachers;
ArrayList<SpiritualTeacher> checkedTeachers=new ArrayList<>();
public MyAdapter(Context c, SpiritualTeacher[] teachers) {
this.c = c;
this.teachers = teachers;
}
//VIEWHOLDER IS INITIALIZED
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model,null);
MyHolder holder=new MyHolder(v);
return holder;
}
//DATA IS BOUND TO VIEWS
@Override
public void onBindViewHolder(MyHolder holder, int position) {
final SpiritualTeacher teacher=teachers[position];
holder.nameTxt.setText(teacher.getName());
holder.posTxt.setText(teacher.getQuote());
holder.myCheckBox.setChecked(teacher.isSelected());
holder.img.setImageResource(teacher.getImage());
holder.setItemClickListener(new MyHolder.ItemClickListener() {
@Override
public void onItemClick(View v, int pos) {
CheckBox myCheckBox= (CheckBox) v;
SpiritualTeacher currentTeacher=teachers[pos];
if(myCheckBox.isChecked()) {
currentTeacher.setSelected(true);
checkedTeachers.add(currentTeacher);
}
else if(!myCheckBox.isChecked()) {
currentTeacher.setSelected(false);
checkedTeachers.remove(currentTeacher);
}
}
});
}
@Override
public int getItemCount() {
return teachers.length;
}
}
private SpiritualTeacher[] getTeachers() {
SpiritualTeacher[] spiritualTeachers={
new SpiritualTeacher("Rumi","Out beyond ideas of wrongdoing and rightdoing there is a field.I'll meet you there.",R.drawable.rumi),
new SpiritualTeacher("Anthony De Mello","Don't Carry Over Experiences from the past",R.drawable.anthony_de_mello),
new SpiritualTeacher("Eckhart Tolle","Walk as if you are kissing the Earth with your feet.",R.drawable.eckhart_tolle),
new SpiritualTeacher("Meister Eckhart","Man suffers only because he takes seriously what the gods made for fun.",R.drawable.meister_eckhart),
new SpiritualTeacher("Mooji","I have lived with several Zen masters -- all of them cats.",R.drawable.mooji),
new SpiritualTeacher("Confucius","I'm simply saying that there is a way to be sane. I'm saying that you ",R.drawable.confucius),
new SpiritualTeacher("Francis Lucille","The way out is through the door. Why is it that no one will use this method?",R.drawable.francis_lucille),
new SpiritualTeacher("Thich Nhat Hanh","t is the power of the mind to be unconquerable.",R.drawable.thich),
new SpiritualTeacher("Dalai Lama","It's like you took a bottle of ink and you threw it at a wall. Smash! ",R.drawable.dalai_lama),
new SpiritualTeacher("Jiddu Krishnamurti","A student, filled with emotion and crying, implored, 'Why is there so much suffering?",R.drawable.jiddu_krishnamurti),
new SpiritualTeacher("Osho","Only the hand that erases can write the true thing.",R.drawable.osho),
new SpiritualTeacher("Sedata","Many have died; you also will die. The drum of death is being beaten.",R.drawable.sedata),
new SpiritualTeacher("Allan Watts","Where there are humans, You'll find flies,And Buddhas.",R.drawable.allant_watts),
new SpiritualTeacher("Leo Gura","Silence is the language of Om. We need silence to be able to reach our Self.",R.drawable.sadhguru),
new SpiritualTeacher("Rupert Spira","One day in my shoes and a day for me in your shoes, the beauty of travel lies ",R.drawable.rupert_spira),
new SpiritualTeacher("Sadhguru","Like vanishing dew,a passing apparition or the sudden flashnof lightning",R.drawable.sadhguru)
};
return spiritualTeachers;
}
StringBuilder sb=null;
MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter=new MyAdapter(this,getTeachers());
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sb=new StringBuilder();
int i=0;
do {
SpiritualTeacher spiritualTeacher=adapter.checkedTeachers.get(i);
sb.append(spiritualTeacher.getName());
if(i != adapter.checkedTeachers.size()-1){
sb.append("n");
}
i++;
}while (i < adapter.checkedTeachers.size());
if(adapter.checkedTeachers.size()>0)
{
Toast.makeText(MainActivity.this,sb.toString(),Toast.LENGTH_SHORT).show();
}else
{
Toast.makeText(MainActivity.this,"Please Check An Item First", Toast.LENGTH_SHORT).show();
}
}
});
//RECYCLER
RecyclerView rv= (RecyclerView) findViewById(R.id.myRecycler);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setItemAnimator(new DefaultItemAnimator());
//SET ADAPTER
rv.setAdapter(adapter);
}
}
Exemplo 2: SingleChoice RecyclerView - com RadioButtons
Android SingleChoice RecyclerView Tutorial
Neste tutorial, queremos ver como criar uma visão de reciclagem de escolha única. Esta é uma visão do reciclador com
radiobuttons. O usuário pode selecionar um único item e nós abrimos a atividade detalhada do item mostrando assim os seus dados.
Por que SingleChoice RecyclerView?
Bem, a alternativa é o RecyclerView de múltipla escolha, ou seja, o RecyclerView com caixas de seleção. Entretanto, em alguns casos
você só quer que o usuário seja capaz de selecionar um único item da visão do reciclador. É aqui que entram os radiobuttons.
No entanto, em nosso caso, abriremos uma atividade detalhada quando o usuário selecionar um determinado radiobutton. Em seguida, utilizamos os intentos para
passar dados para a atividade de detalhe.
O que mostramos?
Bem, mostramos imagens, textos e radiobuttons. Normalmente as imagens são renderizadas em imageview. O texto
será apresentado em formato de texto. Por outro lado, os radiobuttons
mostram para nós um estado composto, basicamente verificado ou não.
Passo 1: Roteiros de Gradle
(a) Build.gradle
Não é necessária nenhuma dependência especial. Acrescentamos CardView e Reciclerview como nossas dependências.
O CardView irá conter nossos objetos Galaxy. O RecyclerView terá várias visualizações de cartão. A AppCompat nos dará o
AppCompatActivity do qual se estende nossa MainActivity.
Passo 2: Criar layouts
Temos três layouts
1. activity_main.xml
Este layout será inflado na MainActivity. Ele simplesmente contém nosso RecyclerView. Eu dei ao meu um costume
cor de fundo.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_background="#009968"
android_layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android_id="@+id/mRecylcerview"
android_layout_width="match_parent"
android_layout_height="match_parent" />
</RelativeLayout>
2. activity_detail.xml
O Layout para nossa atividade de Detalhe. Contém imageviews e textviews.para mostrar
nossos dados.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_background="#009688"
tools_context=".DetailsActivity"
tools_showIn="@layout/activity_detail">
<androidx.cardview.widget.CardView
android_layout_width="match_parent"
android_layout_height="match_parent"
android_layout_margin="3dp"
card_view_cardCornerRadius="3dp"
card_view_cardElevation="5dp">
<ScrollView
android_layout_width="match_parent"
android_layout_height="match_parent">
<LinearLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_orientation="vertical">
<ImageView
android_id="@+id/galaxyImg"
android_layout_width="match_parent"
android_layout_height="200dp"
android_layout_alignParentTop="true"
android_padding="5dp"
android_scaleType="fitXY"
android_src="@drawable/placeholder" />
<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_orientation="vertical">
<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_orientation="horizontal">
<TextView
android_id="@+id/nameLabel"
android_layout_width="0dp"
android_layout_weight="1"
android_layout_height="wrap_content"
android_maxLines="1"
android_padding="5dp"
android_text="NAME"
android_textColor="@color/colorAccent"
android_textAppearance="?android:attr/textAppearanceSmall"
android_textStyle="bold" />
<TextView
android_id="@+id/nameTxt"
android_layout_width="0dp"
android_layout_weight="2"
android_layout_height="wrap_content"
android_maxLines="1"
android_padding="5dp"
android_text="Milky Way"
android_textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_orientation="horizontal">
<TextView
android_id="@+id/dateLabel"
android_layout_width="0dp"
android_layout_weight="1"
android_layout_height="wrap_content"
android_maxLines="1"
android_textColor="@color/colorAccent"
android_padding="5dp"
android_text="DATE"
android_textAppearance="?android:attr/textAppearanceSmall"
android_textStyle="bold" />
<TextView
android_id="@+id/dateDetailTextView"
android_layout_width="0dp"
android_layout_weight="2"
android_layout_height="wrap_content"
android_maxLines="1"
android_padding="5dp"
android_text="Today"
android_textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_orientation="horizontal">
<TextView
android_id="@+id/descLabel"
android_layout_width="0dp"
android_layout_weight="1"
android_layout_height="wrap_content"
android_maxLines="1"
android_textColor="@color/colorAccent"
android_padding="5dp"
android_text="DESCRIPTION : "
android_textAppearance="?android:attr/textAppearanceSmall"
android_textStyle="bold" />
<TextView
android_id="@+id/descTxt"
android_layout_width="0dp"
android_layout_weight="2"
android_layout_height="wrap_content"
android_maxLines="10"
android_padding="5dp"
android_text="Description..."
android_textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</androidx.cardview.widget.CardView>
</RelativeLayout>
3. model.xml
Este é nosso esquema de visualização de itens. Ele será inflado em nossos itens de visualização de reciclagem. Isto será feito por nosso RecyclerView
adaptador.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
android_orientation="horizontal" android_layout_width="match_parent"
android_layout_margin="1dp"
card_view_cardCornerRadius="1dp"
card_view_cardElevation="5dp"
android_layout_height="135dp">
<RelativeLayout
android_layout_width="wrap_content"
android_layout_height="match_parent">
<ImageView
android_layout_width="120dp"
android_layout_height="120dp"
android_id="@+id/mGalaxyImageView"
android_padding="5dp"
android_scaleType="fitXY"
android_src="@drawable/placeholder" />
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceSmall"
android_text="Name"
android_id="@+id/mNameTxt"
android_padding="5dp"
android_textColor="@color/colorAccent"
android_layout_alignParentTop="true"
android_layout_toRightOf="@+id/mGalaxyImageView" />
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceSmall"
android_text="Description"
android_textStyle="italic"
android_maxLines="3"
android_id="@+id/mDescTxt"
android_padding="5dp"
android_layout_alignBottom="@+id/mGalaxyImageView"
android_layout_toRightOf="@+id/mGalaxyImageView" />
<RadioButton
android_id="@+id/mRadioButton"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentRight="true" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
Passo 4: Escreva o código Java.
Temos as seguintes classes java para este projeto:
- Galaxy.java
- RecicladorAdaptador.java
- DetalhesAtividade.java
- MainActivity.java
(a).Galaxy.java
Isto representará nosso objeto de dados. É nossa classe de modelo e representa uma galáxia com propriedades como:
- Nome.
- Descrição
- Imagem.
Aqui está o código completo.
package info.camposha.singlechoicerecyclerview_vela;
import java.io.Serializable;
/**
* Please take note that our data object will implement Serializable.This
* will allow us to pass this serialized object to DetailsActivity,
*/
public class Galaxy implements Serializable{
private String name,description;
private int image;
public Galaxy(String name, String description,int image) {
this.name = name;
this.description = description;
this.image=image;
}
public String getName() {return name;}
public String getDescription() {return description;}
public int getImage() {return image;}
}
Você pode ver que nós implementamos a interface Serializável. Isto nos permite serializar nosso objeto de dados de forma
que ela pode ser transportada para a atividade DetailsActivity como um todo através da intenção.
(b). RecicladorAdaptador.java
Esta é nossa classe adaptador. Ela irá inflar nosso modelo de layout em um objeto de visualização que pode ser renderizado pela visão do reciclador.
Ele também ligará os dados aos objetos de visão inflados.
package info.camposha.singlechoicerecyclerview_vela;
import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.TextView;
import java.util.List;
public class RecyclerAdapter extends RecyclerView.Adapter<
RecyclerAdapter.RecyclerViewHolder> {
/**
* Let's start by defining our instance fields
*/
private int selectedStarPosition = -1;
private List<Galaxy> galaxies;
private Context c;
private AdapterView.OnItemClickListener onItemClickListener;
/**
* Let's create our constructor
* @param context
* @param mGalaxies
*/
public RecyclerAdapter(Context context, List<Galaxy> mGalaxies) {
this.c = context;
this.galaxies = mGalaxies;
}
/**
* OnCreateViewHolder - here is where we inflate our model layout
* @param viewGroup
* @param i
* @return
*/
@Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
final View v = LayoutInflater.from(c).inflate(R.layout.model, viewGroup, false);
return new RecyclerViewHolder(v, this);
}
/**
* OnBindViewHolder - Here's where we bind our data
* @param viewHolder
* @param position
*/
@Override
public void onBindViewHolder(RecyclerViewHolder viewHolder, final int position) {
Galaxy galaxy = galaxies.get(position);
try {
viewHolder.bindData(galaxy, position);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Let's return the number of items to be bound to our adapter.
* @return
*/
@Override
public int getItemCount() {
return galaxies.size();
}
/**
* Let's receive our onItemClickListener and assign it to our local one.
* @param onItemClickListener
*/
public void setOnItemClickListener(AdapterView.OnItemClickListener
onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
/**
* When user clicks our itemView, we still invoke the onItemClick
* @param holder
*/
public void onItemHolderClick(RecyclerViewHolder holder) {
if (onItemClickListener != null)
onItemClickListener.onItemClick(null, holder.itemView,
holder.getAdapterPosition(), holder.getItemId());
}
/**
* Let's come create our ViewHolder class.
*/
class RecyclerViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
private RecyclerAdapter mAdapter;
private RadioButton mRadioButton;
private TextView mNameTxt,mDescTxt;
private ImageView mGalaxyImg;
/**
* In our constructor, we reference our itemView widgets.
* @param itemView
* @param mAdapter
*/
public RecyclerViewHolder(View itemView, final RecyclerAdapter mAdapter) {
super(itemView);
this.mAdapter = mAdapter;
mNameTxt = itemView.findViewById(R.id.mNameTxt);
mDescTxt = itemView.findViewById(R.id.mDescTxt);
mRadioButton = itemView.findViewById(R.id.mRadioButton);
mGalaxyImg=itemView.findViewById(R.id.mGalaxyImageView);
itemView.setOnClickListener(this);
mRadioButton.setOnClickListener(this);
}
/**
* Let's create a method that allows us bind our data.
* @param galaxy
* @param position
*/
public void bindData(Galaxy galaxy, int position) {
mRadioButton.setChecked(position == selectedStarPosition);
mNameTxt.setText(galaxy.getName());
mDescTxt.setText(galaxy.getDescription());
mGalaxyImg.setImageResource(galaxy.getImage());
}
/**
* Let's override our OnClick method.
* @param v
*/
@Override
public void onClick(View v) {
selectedStarPosition = getAdapterPosition();
notifyItemRangeChanged(0, galaxies.size());
mAdapter.onItemHolderClick(RecyclerViewHolder.this);
}
}
}
//end
(c). DetalhesAtividade.java
Nossa classe de atividade detalhada. Isto mostrará os detalhes da galáxia clicada.
package info.camposha.singlechoicerecyclerview_vela;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DetailsActivity extends AppCompatActivity {
TextView nameTxt, descTxt, dateDetailTextView;
ImageView galaxyImg;
//We start by initializing our widgets.
private void initializeWidgets() {
nameTxt = findViewById(R.id.nameTxt);
descTxt = findViewById(R.id.descTxt);
dateDetailTextView = findViewById(R.id.dateDetailTextView);
descTxt = findViewById(R.id.descTxt);
galaxyImg = findViewById(R.id.galaxyImg);
}
//This method will get todays date and return it as a string
private String getDateToday() {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
String today = dateFormat.format(date);
return today;
}
//I'll create a method to receive and show data.
private void receiveAndShowData() {
//RECEIVE DATA FROM ITEMS ACTIVITY VIA INTENT
Intent i = this.getIntent();
Galaxy g= (Galaxy) i.getSerializableExtra("GALAXY_KEY");
//SET RECEIVED DATA TO TEXTVIEWS AND IMAGEVIEWS
nameTxt.setText(g.getName());
descTxt.setText(g.getDescription());
dateDetailTextView.setText(getDateToday());
galaxyImg.setImageResource(g.getImage());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
initializeWidgets();
receiveAndShowData();
}
}
//end
(d). MainActivity.java
Nossa principal classe de atividade. É aqui que referenciamos nossa visão do reciclador e definimos nossa fonte de dados.
package info.camposha.singlechoicerecyclerview_vela;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
RecyclerView mRecyclerView;
private RecyclerAdapter mAdapter;
/**
* Let's start by defining our data source.
* @return
*/
private ArrayList<Galaxy> getData()
{
ArrayList<Galaxy> galaxies=new ArrayList<>();
Galaxy g=new Galaxy("Whirlpool",
"The Whirlpool Galaxy, also known as Messier 51a, M51a, and NGC 5194, is an interacting grand-design spiral Galaxy with a Seyfert 2 active galactic nucleus in the constellation Canes Venatici.",
R.drawable.whirlpool);
galaxies.add(g);
g=new Galaxy("Ring Nebular",
"The Ring Nebula is a planetary nebula in the northern constellation of Lyra. Such objects are formed when a shell of ionized gas is expelled into the surrounding interstellar medium by a red giant star.",
R.drawable.ringnebular);
galaxies.add(g);
g=new Galaxy("IC 1011",
"C 1011 is a compact elliptical galaxy with apparent magnitude of 14.7, and with a redshift of z=0.02564 or 0.025703, yielding a distance of 100 to 120 Megaparsecs. Its light has taken 349.5 million years to travel to Earth.",
R.drawable.ic1011);
galaxies.add(g);
g=new Galaxy("Cartwheel",
"The Cartwheel Galaxy is a lenticular galaxy and ring galaxy about 500 million light-years away in the constellation Sculptor. It is an estimated 150,000 light-years diameter, and a mass of about 2.9–4.8 × 10⁹ solar masses; it rotates at 217 km/s.",
R.drawable.cartwheel);
galaxies.add(g);
g=new Galaxy("Triangulumn",
"The Triangulum Galaxy is a spiral Galaxy approximately 3 million light-years from Earth in the constellation Triangulum",
R.drawable.triangulum);
galaxies.add(g);
g=new Galaxy("Small Magellonic Cloud",
"The Small Magellanic Cloud, or Nubecula Minor, is a dwarf galaxy near the Milky Way. It is classified as a dwarf irregular galaxy.",
R.drawable.smallamgellonic);
galaxies.add(g);
g=new Galaxy("Centaurus A",
" Centaurus A or NGC 5128 is a galaxy in the constellation of Centaurus. It was discovered in 1826 by Scottish astronomer James Dunlop from his home in Parramatta, in New South Wales, Australia.",
R.drawable.centaurusa);
galaxies.add(g);
g=new Galaxy("Ursa Minor",
"The Milky Way is the Galaxy that contains our Solar System." +
" The descriptive milky is derived from the appearance from Earth of the Galaxy – a band of light seen in the night sky formed from stars",
R.drawable.ursaminor);
galaxies.add(g);
g=new Galaxy("Large Magellonic Cloud",
" The Large Magellanic Cloud is a satellite galaxy of the Milky Way. At a distance of 50 kiloparsecs, the LMC is the third-closest galaxy to the Milky Way, after the Sagittarius Dwarf Spheroidal and the.",
R.drawable.largemagellonic);
galaxies.add(g);
g=new Galaxy("Milky Way",
"The Milky Way is the Galaxy that contains our Solar System." +
" The descriptive milky is derived from the appearance from Earth of the Galaxy – a band of light seen in the night sky formed from stars",
R.drawable.milkyway);
galaxies.add(g);
g=new Galaxy("Andromeda",
"The Andromeda Galaxy, also known as Messier 31, M31, or NGC 224, is a spiral Galaxy approximately 780 kiloparsecs from Earth. It is the nearest major Galaxy to the Milky Way and was often referred to as the Great Andromeda Nebula in older texts.",
R.drawable.andromeda);
galaxies.add(g);
g=new Galaxy("Messier 81",
"Messier 81 is a spiral Galaxy about 12 million light-years away in the constellation Ursa Major. Due to its proximity to Earth, large size and active galactic nucleus, Messier 81 has been studied extensively by professional astronomers.",
R.drawable.messier81);
galaxies.add(g);
g=new Galaxy("Own Nebular",
" The Owl Nebula is a planetary nebula located approximately 2,030 light years away in the constellation Ursa Major. It was discovered by French astronomer Pierre Méchain on February 16, 1781",
R.drawable.ownnebular);
galaxies.add(g);
g=new Galaxy("Messier 87",
"Messier 87 is a supergiant elliptical galaxy in the constellation Virgo. One of the most massive galaxies in the local universe, it is notable for its large population of globular clusters—M87 contains",
R.drawable.messier87);
galaxies.add(g);
g=new Galaxy("Cosmos Redshift",
"Cosmos Redshift 7 is a high-redshift Lyman-alpha emitter Galaxy, in the constellation Sextans, about 12.9 billion light travel distance years from Earth, reported to contain the first stars —formed ",
R.drawable.cosmosredshift);
galaxies.add(g);
g=new Galaxy("StarBust",
"A starburst Galaxy is a Galaxy undergoing an exceptionally high rate of star formation, as compared to the long-term average rate of star formation in the Galaxy or the star formation rate observed in most other galaxies. ",
R.drawable.starbust);
galaxies.add(g);
g=new Galaxy("Sombrero",
"Sombrero Galaxy is an unbarred spiral galaxy in the constellation Virgo located 31 million light-years from Earth. The galaxy has a diameter of approximately 50,000 light-years, 30% the size of the Milky Way.",
R.drawable.sombrero);
galaxies.add(g);
g=new Galaxy("Pinwheel",
"The Pinwheel Galaxy is a face-on spiral galaxy distanced 21 million light-years away from earth in the constellation Ursa Major. ",
R.drawable.pinwheel);
galaxies.add(g);
g=new Galaxy("Canis Majos Overdensity",
"The Canis Major Dwarf Galaxy or Canis Major Overdensity is a disputed dwarf irregular galaxy in the Local Group, located in the same part of the sky as the constellation Canis Major. ",
R.drawable.canismajoroverdensity);
galaxies.add(g);
g=new Galaxy("Virgo Stella Stream",
" Group, located in the same part of the sky as the constellation Canis Major. ",
R.drawable.virgostellarstream);
galaxies.add(g);
return galaxies;
}
/**
* Let's create a method to open our detail activity and pass our object.
* @param galaxy
*/
private void openDetailActivity(Galaxy galaxy)
{
Intent i=new Intent(this,DetailsActivity.class);
i.putExtra("GALAXY_KEY",galaxy);
startActivity(i);
}
/**
* Let's implemenent our onItemClick method
* @param parent
* @param view
* @param position
* @param id
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Galaxy g=getData().get(position);
Toast.makeText(MainActivity.this,String.valueOf(position)+". "+ g.getName()+" Chosen.", Toast.LENGTH_SHORT).show();
openDetailActivity(g);
}
/**
* Let's override our onCreate callback
* @param savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView=findViewById(R.id.mRecylcerview);
mAdapter = new RecyclerAdapter(this, getData());
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(this);
}
}
Download
Você pode baixar o código fonte completo abaixo ou assistir ao vídeo a partir do link fornecido.
No. | Location | Link |
---|---|---|
1. | GitHub | Direct Download |
2. | GitHub | Browse |
3. | YouTube | Video Tutorial |
4. | YouTube | ProgrammingWizards TV Channel |
Exemplo 3: Kotlin Android RecyclerView - CardView com CheckBox,Imagens,Texto e ItemClick
Kotlin Android RecyclerView com CheckBoxes, Imagens, texto e ItemClick suporta Tutorial e Exemplo.
Quero mostrar como você pode trabalhar com a visão do reciclador neste tutorial e fazer coisas comuns como usá-lo com caixas de seleção, imagens, visão de texto e também com suporte a eventos de clique. Tudo isso nós fazemos em um único arquivo MainActivity.kt
.
Tutorial em vídeo
Se você preferir um vídeo tutorial, verifique aqui:
O que você aprende
Aqui estão os conceitos que você aprende:
- Como usar o Recyclerview em andróide com a linguagem de programação Kotlin.
- Como usar o CheckBox com Recyclerview e manipular os estados da caixa de seleção de forma apropriada.
- Como criar uma Recyclerview com imagens e texto.
- Como suportar um evento de clique no item em recicl reciclview.
Ferramentas utilizadas
Aqui estão as ferramentas que usei para este projeto:
- Linguagem de programação : Kotlin
- Estrutura - Android
- IDE - Estúdio Android.
- Emulador - Nox Player
- OS : Windows 8.1
Vamos começar.
Demonstração
Aqui está a demonstração para este projeto:
(a). Build.gradle
Nosso nível de aplicação build.gradle
.
É aqui que adicionamos nossas dependências. Especialmente, estamos interessados em três delas principais:
- AppCompat - Para nos dar a AppCompatActivity da qual nossa
MainActivity
derivará. - Design Support - Para nos dar o RecyclerView.
- CardView - Para nos dar o Cardview.
(b). activity_main.xml
Este é nosso principal [atividade] (https://camposha.info/android/activity) layout. Aqui estão os componentes que utilizamos:
- RelativeLayout - Para organizar nossos outros widgets em relação uns aos outros.
- TextView - Para renderizar o texto do cabeçalho.
- RecyclerView - Para renderizar nossos dados.
- Botão de Ação Flutuante - Para mostrar os itens verificados quando clicados.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
tools_context="com.devosha.kotlin_recyclerview_checkbox.MainActivity">
<TextView
android_id="@+id/headerTextView"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="Spiritual Teachers"
android_textAlignment="center"
android_textAppearance="@style/TextAppearance.AppCompat.Large"
android_textColor="@color/colorAccent" />
<androidx.recyclerview.widget.RecyclerView
android_id="@+id/myRecycler"
class="androidx.recyclerview.widget.RecyclerView"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentStart="true"
android_layout_below="@+id/headerTextView"
android_layout_marginTop="30dp" />
<android.support.design.widget.FloatingActionButton
android_id="@+id/fab"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentBottom="true"
android_layout_alignParentEnd="true"
android_layout_alignParentRight="true"
android_layout_gravity="bottom|end"
android_src="@android:drawable/ic_dialog_email" />
</RelativeLayout>
(c). model.xml
Este layout definirá nossas visões dos itens para nossa visão da reciclagem, ele os modelará. Basicamente, ele renderizará dados para um único objeto 'EspiritualTeacher'. Na raiz, temos um CardView. Então, também temos:
- ImageView - Para renderizar imagem para o objeto
SpiritualTeacher
. - TextVIew - Para renderizar seu nome, bem como descrição.
- CheckBox - Para nos permitir selecionar e desselecionar as CardViews.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
android_orientation="horizontal" android_layout_width="match_parent"
android_layout_margin="5dp"
card_view_cardCornerRadius="10dp"
card_view_cardElevation="5dp"
android_layout_height="match_parent">
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent">
<ImageView
android_layout_width="150dp"
android_layout_height="150dp"
android_id="@+id/teacherImageView"
android_padding="5dp"
android_src="@drawable/cle" />
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceLarge"
android_text="Teacher Name"
android_id="@+id/nameTextView"
android_padding="5dp"
android_textColor="@color/colorAccent"
android_layout_alignParentTop="true"
android_layout_toRightOf="@+id/teacherImageView" />
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceMedium"
android_text="Teacher Description..."
android_id="@+id/descritionTextView"
android_padding="5dp"
android_layout_alignBottom="@+id/teacherImageView"
android_layout_toRightOf="@+id/teacherImageView" />
<CheckBox
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_id="@+id/myCheckBox"
android_layout_alignParentRight="true"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
(d). MainActivity.kt
Esta é nossa principal [atividade] (https://camposha.info/android/activity). Este é nosso único arquivo e aqui definiremos várias classes internas de kotlin. Esta classe será derivada da AppCompatActivity.
Criar objeto de dados
Começaremos definindo uma classe interna chamada "Professor Espiritual":
inner class SpiritualTeacher(var name: String?, val quote: String, val image: Int) {
var isSelected: Boolean = false
}
Essa classe é nosso objeto de dados. Ela receberá seus parâmetros através do construtor. Além disso, estamos mantendo um booleano simples, como você pode ver, que nos manterá o estado de seleção das CardViews. Na verdade, esta é a magia que nos permite selecionar e desselecionar nossos itens em nossa visão de reciclagem. Assim, nossa visão de reciclagem não perderá o estado mesmo quando rolarmos e os itens da visão de reciclagem forem reciclados. Isto porque estamos mantendo-os como dados em nosso objeto e eles não são afetados pela reciclagem.
Criar classe de Adaptador RecyclerVew
Normalmente, o Adaptador tem duas funções principais. Primeiro para inflar nossos layouts personalizados e segundo para vincular os dados aos widgets resultantes. Entretanto, a visão do reciclador vai sempre mais longe, permitindo-nos reciclar itens. Isto economiza o consumo de memória, pois a inflação é um processo caro e teria um impacto negativo em nosso aplicativo se o fizéssemos para cada item na visão do reciclador.
Portanto, criaremos um adaptador:
internal class MyAdapter(var c: Context, var teachers: Array<SpiritualTeacher>) : RecyclerView.Adapter<MyAdapter.MyHolder>() {..}
Fizemo-lo derivar da classe "RecyclerView.Adapter".
Dentro do adaptador primeiro, criaremos um arrailista que nos manterá os "professores" que foram verificados:
var checkedTeachers = ArrayList<SpiritualTeacher>()
É dentro do método onCreateViewHolder()
onde estaremos inflando nosso modelo.xml
em um objeto View. Para isso, utilizamos a classe LayoutInflater.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.model, null)
return MyHolder(v)
}
Aqui está o código fonte completo.
package com.devosha.kotlin_recyclerview_checkbox
import android.content.Context
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import java.util.ArrayList
/**
* class: MainActivity
* This class is deriving from androidx.appcompat.app.AppCompatActivity
.
*/
class MainActivity : AppCompatActivity() {
private val teachers: Array<SpiritualTeacher>
get() =
arrayOf(SpiritualTeacher("Rumi", "Out beyond ideas of wrongdoing and rightdoing there is a field.I'll meet you there.", R.drawable.rumi),
SpiritualTeacher("Anthony De Mello", "Don't Carry Over Experiences from the past", R.drawable.anthony_de_mello),
SpiritualTeacher("Eckhart Tolle", "Walk as if you are kissing the Earth with your feet.", R.drawable.eckhart_tolle),
SpiritualTeacher("Meister Eckhart", "Man suffers only because he takes seriously what the gods made for fun.", R.drawable.meister_eckhart),
SpiritualTeacher("Mooji", "I have lived with several Zen masters -- all of them cats.", R.drawable.mooji),
SpiritualTeacher("Confucius", "I'm simply saying that there is a way to be sane. I'm saying that you ", R.drawable.confucius),
SpiritualTeacher("Francis Lucille", "The way out is through the door. Why is it that no one will use this method?", R.drawable.francis_lucille),
SpiritualTeacher("Thich Nhat Hanh", "t is the power of the mind to be unconquerable.", R.drawable.thich),
SpiritualTeacher("Dalai Lama", "It's like you took a bottle of ink and you threw it at a wall. Smash! ", R.drawable.dalai_lama),
SpiritualTeacher("Jiddu Krishnamurti", "A student, filled with emotion and crying, implored, 'Why is there so much suffering?", R.drawable.jiddu_krishnamurti),
SpiritualTeacher("Osho", "Only the hand that erases can write the true thing.", R.drawable.osho),
SpiritualTeacher("Sedata", "Many have died; you also will die. The drum of death is being beaten.", R.drawable.sedata),
SpiritualTeacher("Allan Watts", "Where there are humans, You'll find flies,And Buddhas.", R.drawable.allant_watts),
SpiritualTeacher("Leo Gura", "Silence is the language of Om. We need silence to be able to reach our Self.", R.drawable.sadhguru),
SpiritualTeacher("Rupert Spira", "One day in my shoes and a day for me in your shoes, the beauty of travel lies ", R.drawable.rupert_spira),
SpiritualTeacher("Sadhguru", "Like vanishing dew,a passing apparition or the sudden flashnof lightning", R.drawable.sadhguru))
internal var sb: StringBuilder? = null
internal lateinit var adapter: MyAdapter
inner class SpiritualTeacher(var name: String?, val quote: String, val image: Int) {
var isSelected: Boolean = false
}
internal class MyAdapter(var c: Context, var teachers: Array<SpiritualTeacher>) : RecyclerView.Adapter<MyAdapter.MyHolder>() {
var checkedTeachers = ArrayList<SpiritualTeacher>()
//VIEWHOLDER IS INITIALIZED
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.model, null)
return MyHolder(v)
}
//DATA IS BOUND TO VIEWS
override fun onBindViewHolder(holder: MyHolder, position: Int) {
val teacher = teachers[position]
holder.nameTxt.text = teacher.name
holder.posTxt.text = teacher.quote
holder.myCheckBox.isChecked = teacher.isSelected
holder.img.setImageResource(teacher.image)
holder.setItemClickListener(object : MyHolder.ItemClickListener {
override fun onItemClick(v: View, pos: Int) {
val myCheckBox = v as CheckBox
val currentTeacher = teachers[pos]
if (myCheckBox.isChecked) {
currentTeacher.isSelected = true
checkedTeachers.add(currentTeacher)
} else if (!myCheckBox.isChecked) {
currentTeacher.isSelected = false
checkedTeachers.remove(currentTeacher)
}
}
})
}
override fun getItemCount(): Int {
return teachers.size
}
internal class MyHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var img: ImageView
var nameTxt: TextView
var posTxt: TextView
var myCheckBox: CheckBox
lateinit var myItemClickListener: ItemClickListener
init {
nameTxt = itemView.findViewById(R.id.nameTextView)
posTxt = itemView.findViewById(R.id.descritionTextView)
img = itemView.findViewById(R.id.teacherImageView)
myCheckBox = itemView.findViewById(R.id.myCheckBox)
myCheckBox.setOnClickListener(this)
}
fun setItemClickListener(ic: ItemClickListener) {
this.myItemClickListener = ic
}
override fun onClick(v: View) {
this.myItemClickListener.onItemClick(v, layoutPosition)
}
internal interface ItemClickListener {
fun onItemClick(v: View, pos: Int)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
adapter = MyAdapter(this, teachers)
val fab = findViewById(R.id.fab) as FloatingActionButton
fab.setOnClickListener {
sb = StringBuilder()
var i = 0
while (i < adapter.checkedTeachers.size) {
val spiritualTeacher = adapter.checkedTeachers[i]
sb!!.append(spiritualTeacher.name)
if (i != adapter.checkedTeachers.size - 1) {
sb!!.append("n")
}
i++
}
if (adapter.checkedTeachers.size > 0) {
Toast.makeText(this@MainActivity, sb!!.toString(), Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this@MainActivity, "Please Check An Item First", Toast.LENGTH_SHORT).show()
}
}
//RECYCLER
val rv = findViewById(R.id.myRecycler) as RecyclerView
rv.layoutManager = LinearLayoutManager(this)
rv.itemAnimator = DefaultItemAnimator()
//SET ADAPTER
rv.adapter = adapter
}
// end
}
Exemplo 4: Android MySQL - RecyclerView CheckBoxes - INSERT,SELECT,SHOW
Este é um tutorial de reciclagem de andróides mysql com caixas de seleção. Vemos como trabalhar tanto com texto quanto com valores booleanos com nosso banco de dados mysql.
- Hoje exploramos como trabalhar com valores booleanos e valores de texto com MySQL e RecyclerView.
- Primeiro inserimos dados no banco de dados MySQL.
- Os componentes que usamos como vistas de entrada incluem chcekbox, spinner e material edittext.
- O usuário digita o nome de sua nave espacial favorita no texto de edição, depois seleciona o propulsor da nave espacial em um spinner.
- Em seguida, ele verifica/desmarca uma caixa de seleção se essa tecnologia existe agora ou não.
- Salvamos esses dados para o MySQL em um clique de botão.
- No botão "Recuperar" clique, selecionamos dados do MySQL e ligamos este texto e booleano ao nosso Checked RecyclerView,RecyclerView com CheckBoxes.
Primeiro deixe-me dizer que temos o código fonte completo e bem comentado acima para download como uma referência completa. Incluímos o arquivo PHP que usamos. Você o colocará no diretório raiz do seu servidor e modificará coisas como nome de usuário, nome da tabela, etc.
Video Tutorial(ProgrammingWizards TV Channel)
Bem, temos um tutorial em vídeo como alternativa a isto. Se você preferir tutoriais como este, então seria bom que você assine nosso canal no YouTube.
Basicamente, temos uma TV para programação onde fazemos tutoriais diários especialmente andróides.
Android MySQL RecyclerView CheckBoxes Insert, Select Show Example
Vejamos nosso exemplo:
Tabela MySQL
Aqui está nossa estrutura de mesa mysql:
Estrutura do projeto
Aqui está nossa estrutura de projeto.
1. Código PHP
Aqui estão nossos códigos php:
(a) Constants.php
Nossa classe PHP para manter constantes de banco de dados como nome do servidor, nome do banco de dados, nome de usuário e senha. Estas credenciais serão necessárias para que possamos nos conectar ao banco de dados MySQL.
<?php
class Constants
{
//DATABASE DETAILS
static $DB_SERVER="localhost";
static $DB_NAME="galileoDB";
static $USERNAME="root";
static $PASSWORD="";
const TB_NAME="galileoTB";
//STATEMENTS
static $SQL_SELECT_ALL="SELECT * FROM galileoTB";
}
(b) CRUD.php
Este arquivo PHP nos permitirá receber dados do cliente HTTP, ouvindo e tratando as solicitações. Nós tratamos essas solicitações iniciando as ações CRUD definidas em nossa classe DBAdapater.php
.
<?php
require_once("/DBAdapter.php");
if($_POST['action']=="save"){
$dbAdapter=new DBAdapter();
$name=$_POST['name'];
$propellant=$_POST['propellant'];
$technologyexists=$_POST['technologyexists'];
$dbAdapter->insert(array($name,$propellant,$technologyexists));
}
else if($_POST['action']=="update")
{
$dbAdapter=new DBAdapter();
$id=$_POST['id'];
$name=$_POST['name'];
$propellant=$_POST['propellant'];
$technologyexists=$_POST['technologyexists'];
$dbAdapter->update($id,array($name,$propellant,$technologyexists));
}
else if($_POST['action']=="delete")
{
$dbAdapter=new DBAdapter();
$id=$_POST['id'];
$dbAdapter->delete($id);
}
?>
(c) DBAdapter.php
Este arquivo PHP conterá funções que nos permitem realizar operações CRUD em nosso banco de dados MySQL. Tais ações incluem a inserção e a recuperação de dados de e para o banco de dados.
<?php
require_once("/Constants.php");
class DBAdapter
{
/*******************************************************************************************************************************************/
/*
1.CONNECT TO DATABASE.
2. RETURN CONNECTION OBJECT
*/
public function connect()
{
$con=mysqli_connect(Constants::$DB_SERVER,Constants::$USERNAME,Constants::$PASSWORD,Constants::$DB_NAME);
if(mysqli_connect_error(!$con))
{
// echo "Unable To Connect";
return null;
}else
{
return $con;
}
}
/*******************************************************************************************************************************************/
/*
1.INSERT SPACECRAFT INTO DATABASE
*/
public function insert($s)
{
// INSERT
$con=$this->connect();
if($con != null)
{
$sql="INSERT INTO galileoTB(name,propellant,technologyexists) VALUES('$s[0]','$s[1]','$s[2]')";
try
{
$result=mysqli_query($con,$sql);
if($result)
{
print(json_encode(array("Success")));
}else
{
print(json_encode(array("Unsuccessfull")));
}
}catch (Exception $e)
{
print(json_encode(array("PHP EXCEPTION : CAN'T SAVE TO MYSQL. "+$e->getMessage())));
}
}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
mysqli_close($con);
}
/*******************************************************************************************************************************************/
/*
1.SELECT FROM DATABASE.
*/
public function select()
{
$con=$this->connect();
if($con != null)
{
$retrieved=mysqli_query($con,Constants::$SQL_SELECT_ALL);
if($retrieved)
{
while($row=mysqli_fetch_array($retrieved))
{
// echo $row["name"] ," t | ",$row["propellant"],"</br>";
$spacecrafts[]=$row;
}
print(json_encode($spacecrafts));
}else
{
print(json_encode(array("PHP EXCEPTION : CAN'T RETRIEVE FROM MYSQL. ")));
}
}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
mysqli_close($con);
}
/*******************************************************************************************************************************************/
/*
1.UPDATE DATABASE.
*/
public function update($id, $s)
{
// UPDATE
$con=$this->connect();
if($con != null)
{
$sql="UPDATE galileoTB SET name='$s[0]',propellant='$s[1]',technologyexists='$s[2]' WHERE id='$id'";
try
{
$result=mysqli_query($con,$sql);
if($result)
{
print(json_encode(array("Successfully Updated")));
}else
{
print(json_encode(array("Not Successfully Updated")));
}
}catch (Exception $e)
{
print(json_encode(array("PHP EXCEPTION : CAN'T UPDATE INTO MYSQL. "+$e->getMessage())));
}
}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
mysqli_close($con);
}
/*******************************************************************************************************************************************/
/*
1.DELETE SPACECRAFT FROM DATABASE.
*/
public function delete($id)
{
$con=$this->connect();
if($con != null)
{
// $name=$_POST['Name'];
// $pos=$_POST['Position'];
// $team=$_POST['Team'];
$sql="DELETE FROM galileoTB WHERE id='$id'";
try
{
$result=mysqli_query($con,$sql);
if($result)
{
print(json_encode(array("Successfully Deleted")));
}else
{
print(json_encode(array("Not Successfully Deleted")));
}
}catch (Exception $e)
{
print(json_encode(array("PHP EXCEPTION : CAN'T DELETE FROM MYSQL. "+$e->getMessage())));
}
}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
mysqli_close($con);
}
}
(d) Index.php
<?php
require_once("/DBAdapter.php");
$dbAdapter=new DBAdapter();
$dbAdapter->select();
?>
2. Roteiros de Gradle Scripts
Aqui estão nossos roteiros de graduação em nosso(s) arquivo(s) build.gradle
(a). build.gradle(app)
Aqui está nosso arquivo de nível app build.gradle
. Temos as dependências DSL onde adicionamos nossas dependências.
Este arquivo é chamado de app level build.gradle
, uma vez que está localizado na pasta app do projeto.
Se você estiver utilizando o Android Studio versão 3 e superior, utilize a palavra-chave implementation' enquanto que se estiver utilizando uma versão menor que 3, então ainda utilize a palavra-chave
compile'.
Uma vez que você tenha modificado este arquivo build.gradle
, você tem que sincronizar seu projeto. O Android Studio de fato o incentivará a fazer isso.
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:24.2.0'
implementation 'com.android.support:design:24.2.0'
implementation 'com.android.support:cardview-v7:24.2.0'
implementation 'com.amitshekhar.android:android-networking:0.2.0'
}
Estamos usando a Fast Android Networking Library como nosso cliente HTTP. Você pode usar versões mais recentes.
3. Recursos
A plataforma Android oferece uma maneira poderosa e flexível de adicionar conteúdo estático como um recurso.
Este conteúdo estático também será empacotado no arquivo APK. O conteúdo estático será armazenado ou como um recurso ou como um ativo.
Os recursos pertencem a um determinado tipo. Estes tipos podem ser:
- Desenhos.
- Layout.
- Valor.
Comecemos analisando os recursos de layout
(a). model.xml
Nosso modelo de layout de linha.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
android_orientation="horizontal" android_layout_width="match_parent"
android_layout_margin="10dp"
card_view_cardCornerRadius="5dp"
card_view_cardElevation="5dp"
android_layout_height="200dp">
<LinearLayout
android_orientation="vertical"
android_layout_width="match_parent"
android_layout_height="match_parent">
<TextView
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceLarge"
android_text="Name"
android_id="@+id/nameTxt"
android_padding="10dp"
android_textColor="@color/colorAccent"
android_textStyle="bold"
android_layout_alignParentLeft="true"
/>
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textAppearance="?android:attr/textAppearanceLarge"
android_text="Propellant....................."
android_id="@+id/txtPropellant"
android_padding="10dp"
android_layout_alignParentLeft="true"
/>
<CheckBox
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textSize="25dp"
android_id="@+id/chkTechExists"
android_checked="true" />
</LinearLayout>
</androidx.cardview.widget.CardView>
(b). content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_paddingBottom="@dimen/activity_vertical_margin"
android_paddingLeft="@dimen/activity_horizontal_margin"
android_paddingRight="@dimen/activity_horizontal_margin"
android_paddingTop="@dimen/activity_vertical_margin"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context="com.tutorials.hp.mysqlrecyclerbool.MainActivity"
tools_showIn="@layout/activity_main">
<!--INPUT VIEWS-->
<LinearLayout
android_orientation="vertical"
android_layout_width="match_parent"
android_layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android_id="@+id/nameTxt"
android_hint="Name"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_textStyle="bold"
android_textSize="25dp"
android_enabled="true"
android_focusable="true" />
<LinearLayout
android_orientation="horizontal"
android_padding="5dp"
android_layout_width="match_parent"
android_layout_height="wrap_content">
<TextView
android_textSize="25dp"
android_text="Propellant"
android_textStyle="bold"
android_layout_width="250dp"
android_layout_height="wrap_content" />
<Spinner
android_id="@+id/sp"
android_textSize="25dp"
android_textStyle="bold"
android_layout_width="wrap_content"
android_layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android_orientation="horizontal"
android_padding="5dp"
android_layout_width="match_parent"
android_layout_height="wrap_content">
<TextView
android_textSize="25dp"
android_text="Technology Exists ??"
android_textStyle="bold"
android_layout_width="250dp"
android_layout_height="wrap_content" />
<CheckBox
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_textSize="25dp"
android_id="@+id/techExists"
android_checked="true" />
</LinearLayout>
<!--BUTTONS-->
<RelativeLayout
android_orientation="horizontal"
android_layout_width="match_parent"
android_layout_height="wrap_content">
<Button android_id="@+id/addBtn"
android_layout_width="wrap_content"
android_layout_height="60dp"
android_text="Save"
android_clickable="true"
android_padding="5dp"
android_background="#009968"
android_textColor="@android:color/white"
android_textStyle="bold"
android_textSize="20dp" />
<Button android_id="@+id/refreshBtn"
android_layout_width="wrap_content"
android_layout_height="60dp"
android_text="Retrieve"
android_padding="5dp"
android_clickable="true"
android_background="#f38630"
android_textColor="@android:color/white"
android_layout_alignParentTop="true"
android_layout_alignParentRight="true"
android_layout_alignParentEnd="true"
android_textStyle="bold"
android_textSize="20dp" />
</RelativeLayout>
<!--RECYCLERVIEW-->
<androidx.recyclerview.widget.RecyclerView
android_id="@+id/rv"
android_layout_width="match_parent"
android_layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</RelativeLayout>
(c). activity_main.xml
Este layout será inflado na interface do usuário da atividade principal. Isto acontecerá através do método 'SetContentView()setContentView()
da Activity, que exigirá que passemos a ele o layout.
Faremos isso dentro do método onCreate()
do Activity.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_fitsSystemWindows="true"
tools_context="com.tutorials.hp.mysqlrecyclerbool.MainActivity">
<android.support.design.widget.AppBarLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android_id="@+id/toolbar"
android_layout_width="match_parent"
android_layout_height="?attr/actionBarSize"
android_background="?attr/colorPrimary"
app_popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android_id="@+id/fab"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_gravity="bottom|end"
android_layout_margin="@dimen/fab_margin"
android_src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
3. Código Java.
Os aplicativos Android podem ser escritos principalmente em Java ou Kotlin. Atualmente, porém, existem muitos frameworks como Flutter, que também usam linguagens como Dart.
Nesta classe estamos usando a linguagem de programação Java.
Teremos estas classes em nosso projeto.
(a). Nave Espacial.java
Primeiro vamos definir as propriedades de nossas naves espaciais fictícias :
package com.tutorials.hp.mysqlrecyclerbool.mModel;
public class Spacecraft {
/*
INSTANCE FIELDS
*/
private int id;
private String name;
private String propellant;
private int technologyExists;
/*
GETTERS AND SETTERS
*/
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPropellant() {
return propellant;
}
public void setPropellant(String propellant) {
this.propellant = propellant;
}
public int getTechnologyExists() {
return technologyExists;
}
public void setTechnologyExists(int technologyExists) {
this.technologyExists = technologyExists;
}
/*
TOSTRING
*/
@Override
public String toString() {
return name;
}
}
(b). MySQLClient.java
Estamos usando a Biblioteca de Rede Android para nossas chamadas de rede, que é fácil de usar e rápida, e nos devolve respostas JSOn que podemos analisar facilmente.
package com.tutorials.hp.mysqlrecyclerbool.mMySQL;
import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONArrayRequestListener;
import com.tutorials.hp.mysqlrecyclerbool.mAdapter.MyAdapter;
import com.tutorials.hp.mysqlrecyclerbool.mModel.Spacecraft;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class MySQLClient {
//SAVE/RETRIEVE URLS
private static final String DATA_INSERT_URL="http://10.0.2.2/android/Aristotle/crud.php";
private static final String DATA_RETRIEVE_URL="http://10.0.2.2/android/Aristotle/index.php";
//INSTANCE FIELDS
private final Context c;
private MyAdapter adapter ;
public MySQLClient(Context c) {
this.c = c;
}
/*
SAVE/INSERT
*/
public void add(Spacecraft s, final View...inputViews)
{
if(s==null)
{
Toast.makeText(c, "No Data To Save", Toast.LENGTH_SHORT).show();
}
else
{
AndroidNetworking.post(DATA_INSERT_URL)
.addBodyParameter("action","save")
.addBodyParameter("name",s.getName())
.addBodyParameter("propellant",s.getPropellant())
.addBodyParameter("technologyexists",String.valueOf(s.getTechnologyExists()))
.setTag("TAG_ADD")
.build()
.getAsJSONArray(new JSONArrayRequestListener() {
@Override
public void onResponse(JSONArray response) {
if(response != null)
try {
//SHOW RESPONSE FROM SERVER
String responseString = response.get(0).toString();
Toast.makeText(c, "PHP SERVER RESPONSE : " + responseString, Toast.LENGTH_SHORT).show();
if (responseString.equalsIgnoreCase("Success")) {
//RESET VIEWS
EditText nameTxt = (EditText) inputViews[0];
Spinner spPropellant = (Spinner) inputViews[1];
nameTxt.setText("");
spPropellant.setSelection(0);
}else
{
Toast.makeText(c, "PHP WASN'T SUCCESSFUL. ", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(c, "GOOD RESPONSE BUT JAVA CAN'T PARSE JSON IT RECEIVED : "+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
//ERROR
@Override
public void onError(ANError anError) {
Toast.makeText(c, "UNSUCCESSFUL : ERROR IS : "+anError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
/*
RETRIEVE/SELECT/REFRESH
*/
public void retrieve(final RecyclerView rv)
{
final ArrayList<Spacecraft> spacecrafts = new ArrayList<>();
AndroidNetworking.get(DATA_RETRIEVE_URL)
.setPriority(Priority.HIGH)
.build()
.getAsJSONArray(new JSONArrayRequestListener() {
@Override
public void onResponse(JSONArray response) {
JSONObject jo;
Spacecraft s;
try
{
for(int i=0;i<response.length();i++)
{
jo=response.getJSONObject(i);
int id=jo.getInt("id");
String name=jo.getString("name");
String propellant=jo.getString("propellant");
String techExists=jo.getString("technologyexists");
s=new Spacecraft();
s.setId(id);
s.setName(name);
s.setPropellant(propellant);
s.setTechnologyExists(techExists.equalsIgnoreCase("1") ? 1 : 0);
spacecrafts.add(s);
}
//SET TO RECYCLERVIEW
adapter =new MyAdapter(c,spacecrafts);
rv.setAdapter(adapter);
}catch (JSONException e)
{
Toast.makeText(c, "GOOD RESPONSE BUT JAVA CAN'T PARSE JSON IT RECEIEVED. "+e.getMessage(), Toast.LENGTH_LONG).show();
}
}
//ERROR
@Override
public void onError(ANError anError) {
anError.printStackTrace();
Toast.makeText(c, "UNSUCCESSFUL : ERROR IS : "+anError.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
(c). MyViewHolder.java
Nossa classe ViewHolder.
package com.tutorials.hp.mysqlrecyclerbool.mAdapter;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import com.tutorials.hp.mysqlrecyclerbool.R;
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtName,txtPropellant;
CheckBox chkTechExists;
public MyViewHolder(View view) {
super(view);
txtName = (TextView) view.findViewById(R.id.nameTxt);
txtPropellant = (TextView) view.findViewById(R.id.txtPropellant);
chkTechExists = (CheckBox) view.findViewById(R.id.chkTechExists);
}
}
(d). MeuAdaptador.java
Abaixo está nossa classe RecyclerView.Adapter. Dado que o MySQL não tem um tipo de dados booleanos nativos, estaremos mapeando nossos valores booleanos para números inteiros nulos.
package com.tutorials.hp.mysqlrecyclerbool.mAdapter;
import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.tutorials.hp.mysqlrecyclerbool.R;
import com.tutorials.hp.mysqlrecyclerbool.mModel.Spacecraft;
import java.util.ArrayList;
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
/*
INSTANCE FIELDS
*/
private Context c;
private ArrayList<Spacecraft> spacecrafts;
/*
CONSTRUCTOR
*/
public MyAdapter(Context c, ArrayList<Spacecraft> spacecrafts) {
this.c = c;
this.spacecrafts = spacecrafts;
}
/*
INITIALIZE VIEWHOLDER
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(c).inflate(R.layout.model,parent,false);
return new MyViewHolder(v);
}
/*
BIND DATA
*/
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Spacecraft s=spacecrafts.get(position);
holder.txtName.setText(s.getName());
holder.txtPropellant.setText(s.getPropellant());
holder.chkTechExists.setChecked(s.getTechnologyExists()==1);
}
/*
TOTAL NUM OF SPACECRAFTS
*/
@Override
public int getItemCount() {
return spacecrafts.size();
}
}
(d). MainActivity.java
Esta é nossa atividade de lançamento, como o próprio nome sugere. Isto significa que será o principal ponto de entrada para nosso aplicativo, pois quando o usuário clica no ícone de nosso aplicativo, esta atividade será executada primeiro.
Substituímos um método chamado onCreate()
. Aqui começaremos por inflar nosso layout principal através do método setContentView()
.
Nossa atividade principal é na verdade uma atividade, uma vez que ela é derivada da AppCompatActivity.
package com.tutorials.hp.mysqlrecyclerbool;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TextInputEditText;
import androidx.appcompat.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.Toast;
import com.tutorials.hp.mysqlrecyclerbool.mAdapter.MyAdapter;
import com.tutorials.hp.mysqlrecyclerbool.mModel.Spacecraft;
import com.tutorials.hp.mysqlrecyclerbool.mMySQL.MySQLClient;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
//INSTANCE FIELDS
private TextInputEditText txtName;
private CheckBox chkTechnologyExists;
private Spinner spPropellant;
private RecyclerView rv;
private Button btnAdd,btnRetrieve;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//REFERENCE VIEWS
this.initializeViews();
populatePropellants();
//HANDLE EVENTS
this.handleClickEvents();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
rv.setAdapter(new MyAdapter(MainActivity.this,new ArrayList<Spacecraft>()));
}
});
}
/*
REFERENCE VIEWS
*/
private void initializeViews()
{
txtName= (TextInputEditText) findViewById(R.id.nameTxt);
chkTechnologyExists= (CheckBox) findViewById(R.id.techExists);
spPropellant= (Spinner) findViewById(R.id.sp);
rv= (RecyclerView) findViewById(R.id.rv);
btnAdd= (Button) findViewById(R.id.addBtn);
btnRetrieve= (Button) findViewById(R.id.refreshBtn);
rv.setLayoutManager(new LinearLayoutManager(MainActivity.this));
}
/*
HANDLE CLICK EVENTS
*/
private void handleClickEvents()
{
//EVENTS : ADD
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//GET VALUES
String name=txtName.getText().toString();
String propellant=spPropellant.getSelectedItem().toString();
Boolean technologyexists=chkTechnologyExists.isChecked();
//BASIC CLIENT SIDE VALIDATION
if((name.length()<1 || propellant.length()<1 ))
{
Toast.makeText(MainActivity.this, "Please Enter all Fields", Toast.LENGTH_SHORT).show();
}
else
{
//SAVE
Spacecraft s=new Spacecraft();
s.setName(name);
s.setPropellant(propellant);
s.setTechnologyExists(technologyexists ? 1 : 0);
new MySQLClient(MainActivity.this).add(s,txtName,spPropellant);
}
}
});
//EVENTS : RETRIEVE
btnRetrieve.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new MySQLClient(MainActivity.this).retrieve(rv);
}
});
}
private void populatePropellants()
{
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item);
adapter.add("None");
adapter.add("Chemical Energy");
adapter.add("Nuclear Energy");
adapter.add("Laser Beam");
adapter.add("Anti-Matter");
adapter.add("Plasma Ions");
adapter.add("Warp Drive");
spPropellant.setAdapter(adapter);
spPropellant.setSelection(0);
}
}
AndroidManifest.xml
Certifique-se de acrescentar permissão para conexão à Internet.
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.tutorials.hp.mysqlrecyclerbool">
<uses-permission android_name="android.permission.INTERNET"/>
<application
android_allowBackup="true"
android_icon="@mipmap/ic_launcher"
android_label="@string/app_name"
android_supportsRtl="true"
android_theme="@style/AppTheme">
<activity
android_name=".MainActivity"
android_label="@string/app_name"
android_theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android_name="android.intent.action.MAIN" />
<category android_name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Download
Ei, tudo está em referência ao código fonte que é bem comentado e fácil de entender e pode ser baixado abaixo.
Verifique também nosso vídeo tutorial, que é mais detalhado e explicado passo a passo.
No. | Location | Link |
---|---|---|
1. | GitHub | Direct Download |
2. | GitHub | Browse |
3. | YouTube | Video Tutorial |