Diferencia entre revisiones de «ListView»

De MediaWiki
Ir a la navegación Ir a la búsqueda
Línea 559: Línea 559:
  
 
<br />
 
<br />
 +
====Operación de baixa====
 +
* Para dar de baixa un elemento necesitamos gardar a posición clickeada polo usuario.
 +
 +
 +
<br />
 +
=====Accedendo ao adaptador=====
 +
: Supoñemos que non temos acceso ao array de datos (por estar definido localmente, por exemplo).
 +
<syntaxhighlight lang="java" enclose="div" highlight="7-9">
 +
    private void xestionarEventos(){
 +
        findViewById(R.id.btnBaixa).setOnClickListener(new View.OnClickListener() {
 +
            @Override
 +
            public void onClick(View view) {
 +
                if (posElemListaSelec==-1) return;
 +
 +
                ArrayAdapter<String> adapter = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
 +
                String objeto = adapter.getItem(posElemListaSelec);
 +
                adapter.remove(objeto);
 +
                EditText et = findViewById(R.id.edtEditElemLista);
 +
                et.setText("");
 +
            }
 +
        });
 +
 +
        ListView lsvLista = findViewById(R.id.lsvLista);
 +
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
 +
            @Override
 +
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
 +
                posElemListaSelec = i;
 +
                EditText et = findViewById(R.id.edtEditElemLista);
 +
                et.setText(datos.get(i));
 +
            }
 +
        });
 +
 +
 +
    }
 +
</syntaxhighlight>
 +
: Liña 7: Ao non ter acceso ao array de datos, calquera operación a temos que facer a través do adaptador. Polo tanto necesitamos obter unha referencia ao adaptador da ListView.
 +
: Liña 8: A través do adaptador podemos acceder ao elemento seleccionado pola posición que temos gardada previamente no método onItemClick.
 +
: Liña 9: Eliminamos o elemento do adaptador. Automaticamente xa se refresca o ListView e desaparece o elemento.
 +
 +
<br />
 +
=====Accedendo ao array de datos=====
 +
 +
* Neste caso podemos acceder ao array de datos que está cargado no adaptador (polo telo definido a nivel de Activity, non localmente nun método).
 +
<syntaxhighlight lang="java" enclose="div" highlight="6-8">
 +
        findViewById(R.id.btnBaixa).setOnClickListener(new View.OnClickListener() {
 +
            @Override
 +
            public void onClick(View view) {
 +
                if (posElemListaSelec==-1) return;
 +
 +
                datos.remove(posElemListaSelec);
 +
                ArrayAdapter adaptador = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
 +
                adaptador.notifyDataSetChanged();
 +
                EditText et = findViewById(R.id.edtEditElemLista);
 +
                et.setText("");
 +
            }
 +
        });
 +
</syntaxhighlight>
 +
: Liña 6: Eliminamos o elemento do array de datos.
 +
: Liña 8-9: Necesitamos informar ao ListView que ten que recargar a lista, chamando ao método notifyDataSetChanged() do adaptador.
 +
 +
 +
 +
 +
<br />
 +
 
====Operacións sobre o Adaptador====
 
====Operacións sobre o Adaptador====
  
Línea 575: Línea 640:
  
 
<br />
 
<br />
 +
 
====Facendo que o elemento da lista quede seleccionado====
 
====Facendo que o elemento da lista quede seleccionado====
  

Revisión del 11:25 16 nov 2020

Introdución

  • Un ListView é unha view de que lle permite ao usuario seleccionar un elemento.
  • A diferencia dun Spinner unha lista amosa todos os seus elementos na pantalla.

Listview.png

  • A imaxe recolle un exemplo de lista, cada item pode conter un só dato, ou múltiples datos. O primeiro caso é o que se vai ver neste curso.



  • Ao igual que no Spinner usaremos unha fonte de datos (array estático, array dinñamico, recurso xml, etc) para enlazalo co adaptador e este co ListView.


  • Tamén podemos facer uso de layouts 'predefinidos'.



  • Todo o visto có Spinner no uso de adaptadores pódese empregar neste view tendo en conta estas diferenzas:
  • Os layout 'predefinidos' son de tipo listview, non spinner.
  • A xestión de eventos sobre un elemento da lista (seleccionalo) se fai coa interface OnItemClickListener.



  • Se queremos que ao premer sobre a lista, visualmente apareza seleccionado o elemento (digo visualmente, non queda seleccionado a nivel de programación) podemos cambiar estas propiedades no deseñador de Layout sobre o ListView:
        android:choiceMode="singleChoice"
        android:listSelector="@color/colorPrimary"
Nota: @color/colorPrimary é un recurso de tipo 'color' cunha cor definida.



  • Nota Importante: Na actualidade recoméndase empregar o RecyclerView en vez do ListView, xa que consume moita menos memoria.
Un ListView vai 'xerar' todos os compoñentes gráficos que conforman cada fila para todos os elementos da lista, mentres que o RecyclerView soamente xera aqueles compoñentes que se visualizan.



Caso Base

  • O que imos aprender en primeiro lugar é o funcionamento básico da lista.
  • Como cargar datos na lista.
  • Como modificar visualmente o aspecto de cada elemento da lista.
  • Como xestionar o evento de click sobre un elemento da lista.
  • Como acceder ao elemento seleccionado da lista.
  • Como borrar, modificar ou engadir novos elementos á lista.
  • Posteriormente veremos outras posibilidades que nos brinda este control


Preparando a Activity

  • Imos crear unha Activity que visualmente teña este aspecto.
PDM listview base 1.jpg


  • Dentro do paquete Adaptadores crear unha nova 'Empty Activity' de nome: UD04_01_ListViews_base de tipo Launcher.
Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.



Código do Layoout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".adaptadores.UD04_01_ListViews_base">

    <Button
        android:id="@+id/btnAlta"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="Alta"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/btnBaixa"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btnBaixa"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="Baixa"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/btnModificar"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnAlta" />

    <Button
        android:id="@+id/btnModificar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="Modificar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnBaixa" />

    <EditText
        android:id="@+id/edtEditElemLista"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:hint="Texto Elemento Lista"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline" />

    <ListView
        android:id="@+id/lsvLista"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_blue_dark"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>



Cargando datos

  • O primeiro que temos que lograr facer é cargar os datos na lista.
Isto o podemos facer de dúas formas:
  • Graficamente, a través da propiedade entreis do ListView.
  • Por código, facendo uso dun ArrayAdapter.


Cargando datos dende o Layout

  • Primeiro debemos crear un recurso nun dos arquivos /res/values de tipo 'array'.
No exemplo está creado no arquivo /res/values/strings.xml.
    <array name="array_datos_lista">
        <item>Valor 1</item>
        <item>Valor 2</item>
        <item>Valor 3</item>
    </array>
Estes son valores que vai cargar a lista.
Nota: Fixarse que estes valores poden estar traducidos a diferentes idiomas coma xa vimos na sección de internacionalización.



Cargando datos dende o código

  • Nota: Quitamos a carga de datos se a temos na propiedade 'entries' do ListView como vimos no punto anterior.


Para iso temos que facer uso dun Adapter, concretamente imos a empregar o ArrayAdapter
Lembrar que xa expliquei o que era un adaptador.
  • Se nos fixamos nos contructores do adaptador:
PDM listview base 5.jpg
Nos imos a empregar o terceiro constructor.
Necesitimos indicarlle o layout que vai empregar para visualizar os elementos da lista. Podemos empregar calquera sempre que teña a lo menos un TextView.
Android proporciona xa uns predeterminados que podemos empregar, concretamente : android.R.layout.simple_list_item_1 (podedes ver o deseño dende Android Studio premendo a tecla Control e premendo có rato sobre simple_list_item_1).
Por outra banda necesitamos algún tipo de array que garde os datos.
public class UD04_01_ListViews_base extends AppCompatActivity {

    private void cargarDatos(){

        String[]datos = getResources().getStringArray(R.array.array_datos_lista);

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,datos);
        ListView listView = findViewById(R.id.lsvLista);
        listView.setAdapter(adapter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_u_d04_01__list_views_base);

        cargarDatos();
    }
}
Liña 5: Como vemos obtemos os datos do string-array creado en /res/values no punto anterior.
Liña 7: Creamos un adaptador empregando un layout do S.O. e mandamos os datos.
Liña 9: Asociamos o adaptador á lista (se non facemos isto non se cargará ningún dato).


  • Podemos facer unha variante deste código e facer que os datos veñan dun ArrrayList:
    private void cargarDatos(){

        ArrayList<String>datos = new ArrayList<>(Arrays.asList("Valor 1","Valor 2", "Valor 3"));
        
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,datos);
        ListView listView = findViewById(R.id.lsvLista);
        listView.setAdapter(adapter);
    }



Personalizando o deseño

  • Antes vimos que no segundo parámetro temos que enviarlle o id do layout que vai representar cada un dos elementos da lista.
Nos podemos crear o noso propio Layout.
Por exemplo:

Layout: elemento_listview

::<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="VALOR:"
        android:textColor="@android:color/holo_purple"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/txvElemLista"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:text="TextView"
        app:layout_constraintStart_toEndOf="@+id/textView"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Agora imos decirlle ao adaptador que cargue este deseño, pero como dentro do mesmo hai dous TextView, temos que decirlle cal deles debe empregar para pasar o dato da fonte de datos ao view.
Para iso empregamos outro dos contructores vistos anteriormente:
    private void cargarDatos(){
        ArrayList<String>datos = new ArrayList<>(Arrays.asList("Valor 1","Valor 2", "Valor 3"));

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.elemento_listview,R.id.txvElemLista,datos);
        ListView listView = findViewById(R.id.lsvLista);
        listView.setAdapter(adapter);
    }
Liña 3: Fixarse en dúas cousas: Cargamos o layout deseñado por nos e enviamos como tecer parámetro o id do textview que se atopa dentro do layout.



Xestionando o evento Click sobre un elemento da lista

NOTA IMPORTANTE: Cando prememos nun elemento da lista este non queda seleccionado polo que non podemos empregar ningún método o interface que indique 'selected'.
    private void xestionarEventos(){
        ListView lsvLista = findViewById(R.id.lsvLista);
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(getApplicationContext(), adapterView.getItemAtPosition(i).toString(),Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_u_d04_01__list_views_base);

        cargarDatos();
        xestionarEventos();
    }
Liña 5: No método da interface onItemClick vai vir como parámetros:
  • O AdapterView, a través do cal
  • Podemos acceder aos elementos que están cargados na lista.
  • Podemos recuperar a referencia ao ArrayAdapter.
  • O View que foi premido (lembrar que se estamos a facer o exemplo, o view agora mesmo é o layout que fixemos con dous textview.
  • i é a posición do elemento seleccionado.
  • l é un identificador de fila (que non imos empregar).

O anterior é equivalente e isto se temos acceso aos array de datos:

public class UD04_01_ListViews_base extends AppCompatActivity {

    private ArrayList<String>datos = new ArrayList<>(Arrays.asList("Valor 1","Valor 2", "Valor 3"));

    private void cargarDatos(){

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.elemento_listview,R.id.txvElemLista,datos);
        ListView listView = findViewById(R.id.lsvLista);
        listView.setAdapter(adapter);
    }

    private void xestionarEventos(){
        ListView lsvLista = findViewById(R.id.lsvLista);
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(getApplicationContext(), datos.get(i).toString(),Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_u_d04_01__list_views_base);

        cargarDatos();
        xestionarEventos();
    }
}
Liña 3: Definimos o array a nivel de Activity para poder acceder a el dende calquera parte.
Liña 17: Accedemos á posición do array.
Curiosidade: O parámetro 'view' nos permite acceder aos views que están dentro do layout que deseñamos.
Por exemplo:
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                TextView tv = view.findViewById(R.id.txvElemLista);
                tv.setTextColor(Color.RED);
                Toast.makeText(getApplicationContext(), datos.get(i).toString(),Toast.LENGTH_SHORT).show();
            }
        });



Accedendo ao elemento seleccionado da lista

  • O ListView non selecciona ningún elemento cando prememos nela, polo que non podemos empregar os métodos como: lista.getSelectedItem()
Este tipo de chamadas devolverán sempre null no caso do ListView (si funcionan cun spinner).
A única forma de saber cal é o elemento que premeu o usuario é gardando a posición nunha propiedade da Activity, no método onItemClick que vimos anteiormente. Veremos o seu uso na operación de baixa.




Operacións sobre a lista

  • Podemos facer alta, baixas e modificacións.
Ditas operacións as podemos facer sobre o Array onde temos gardados os datos (sempre que estea definido a nivel de Activity ou de forma global) ou sobre o adaptador asociado á ListView.


  • O ArrayAdapter está 'cheo' de métodos para engadir, borrar e modificar elementos da lista.
Por exemplo:


Imos velos das dúas formas:


Operación de Alta


Accedendo ao adaptador
Supoñemos que non temos acceso ao array de datos (por estar definido localmente, por exemplo).
    private void xestionarEventos(){
        findViewById(R.id.btnAlta).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EditText et = findViewById(R.id.edtEditElemLista);
                if (et.getText().toString().length()==0) return;

                ArrayAdapter adaptador = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
                adaptador.add(et.getText().toString());
                

            }
        });

        findViewById(R.id.btnBaixa).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (posElemListaSelec==-1) return;

                ArrayAdapter<String> adapter = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
                String objeto = adapter.getItem(posElemListaSelec);
                adapter.remove(objeto);
                EditText et = findViewById(R.id.edtEditElemLista);
                et.setText("");
            }
        });

        ListView lsvLista = findViewById(R.id.lsvLista);
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                posElemListaSelec = i;
                EditText et = findViewById(R.id.edtEditElemLista);
                et.setText(datos.get(i));
            }
        });


    }
Liña 8: Ao non ter acceso ao array de datos, calquera operación a temos que facer a través do adaptador. Polo tanto necesitamos obter unha referencia ao adaptador da ListView.
Liña 9: A través do adaptador podemos engadir o novo texto.


Accedendo ao array de datos
  • Neste caso podemos acceder ao array de datos que está cargado no adaptador (polo telo definido a nivel de Activity, non localmente nun método).
        findViewById(R.id.btnAlta).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EditText et = findViewById(R.id.edtEditElemLista);
                if (et.getText().toString().length()==0) return;

                ArrayAdapter adaptador = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
                datos.add(et.getText().toString());
                adaptador.notifyDataSetChanged();

                et.setText("");
            }
        });
Liña 8: Añadimos o elemento ao array de datos.
Liña 9: Necesitamos informar ao ListView que ten que recargar a lista, chamando ao método notifyDataSetChanged() do adaptador.





Operación de Modificar

  • Necesitamos ter gardado nun atributo da clase, a posición do elemento seleccionado ao premer sobre a lista (como xa vimos nun exemplo anterior)


Accedendo ao adaptador
Supoñemos que non temos acceso ao array de datos (por estar definido localmente, por exemplo).
O máis doado neste caso é borrar e dar de alta o novo elemento.
    private void xestionarEventos(){
        findViewById(R.id.btnModificar).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EditText et = findViewById(R.id.edtEditElemLista);
                if ((et.getText().toString().length()==0) || (posElemListaSelec==-1))  return;

                ArrayAdapter adaptador = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();

                String datoSel = (String)adaptador.getItem(posElemListaSelec);
                adaptador.remove(datoSel);
                String datoNuevo = et.getText().toString();
                adaptador.insert(datoNuevo,posElemListaSelec);

            }
        });

        ListView lsvLista = findViewById(R.id.lsvLista);
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                posElemListaSelec = i;
                EditText et = findViewById(R.id.edtEditElemLista);
                et.setText(datos.get(i));
            }
        });


    }
Liña 11: Borramos o elemento seleccionado.
Liña 13: Engadimos o novo elemento.


NOTA IMPORTANTE: Se estamos a traballar con obxectos (é dicir, o que gardamos como elemento da lista é un obxecto dunha clase definida por nos, no que sobrescribimos o método toString para indicar o que queremos visualizar), podemos non borrar e crear un novo obxecto, xa que cando obtemos o elemento seleccionado estamos a obter a dirección de memoria onde ese obxecto está aloxado.
Polo tanto se modificamos o obxecto seleccionado é como si modificaramos o elemento do array de datos e podemos empregar a segunda forma (ven explicado a continuación) informando ao adaptador que houbo un cambio nos datos.


Accedendo ao array de datos
  • Neste caso podemos acceder ao array de datos que está cargado no adaptador (polo telo definido a nivel de Activity, non localmente nun método).
        findViewById(R.id.btnModificar).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EditText et = findViewById(R.id.edtEditElemLista);
                if (et.getText().toString().length()==0) return;

                ArrayAdapter adaptador = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
                datos.set(posElemListaSelec,et.getText().toString());
                adaptador.notifyDataSetChanged();
            }
        });
Liña 8: Modificamos o elemento do array de datos.


Curiosidade: Podemos acceder ao view seleccionado mediante esta forma:
                View elemview = adaptador.getView(posElemListaSelec,View.inflate(getApplicationContext(),R.layout.elemento_listview,null),null);
                ((TextView) elemview.findViewById(R.id.txvElemLista)).setText(et.getText().toString());




Operación de baixa

  • Para dar de baixa un elemento necesitamos gardar a posición clickeada polo usuario.



Accedendo ao adaptador
Supoñemos que non temos acceso ao array de datos (por estar definido localmente, por exemplo).
    private void xestionarEventos(){
        findViewById(R.id.btnBaixa).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (posElemListaSelec==-1) return;

                ArrayAdapter<String> adapter = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
                String objeto = adapter.getItem(posElemListaSelec);
                adapter.remove(objeto);
                EditText et = findViewById(R.id.edtEditElemLista);
                et.setText("");
            }
        });

        ListView lsvLista = findViewById(R.id.lsvLista);
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                posElemListaSelec = i;
                EditText et = findViewById(R.id.edtEditElemLista);
                et.setText(datos.get(i));
            }
        });


    }
Liña 7: Ao non ter acceso ao array de datos, calquera operación a temos que facer a través do adaptador. Polo tanto necesitamos obter unha referencia ao adaptador da ListView.
Liña 8: A través do adaptador podemos acceder ao elemento seleccionado pola posición que temos gardada previamente no método onItemClick.
Liña 9: Eliminamos o elemento do adaptador. Automaticamente xa se refresca o ListView e desaparece o elemento.


Accedendo ao array de datos
  • Neste caso podemos acceder ao array de datos que está cargado no adaptador (polo telo definido a nivel de Activity, non localmente nun método).
        findViewById(R.id.btnBaixa).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (posElemListaSelec==-1) return;

                datos.remove(posElemListaSelec);
                ArrayAdapter adaptador = (ArrayAdapter)((ListView)findViewById(R.id.lsvLista)).getAdapter();
                adaptador.notifyDataSetChanged();
                EditText et = findViewById(R.id.edtEditElemLista);
                et.setText("");
            }
        });
Liña 6: Eliminamos o elemento do array de datos.
Liña 8-9: Necesitamos informar ao ListView que ten que recargar a lista, chamando ao método notifyDataSetChanged() do adaptador.




Operacións sobre o Adaptador

  • O ArrayAdapter está 'cheo' de métodos para engadir, borrar e modificar elementos da lista.
Por exemplo:




Facendo que o elemento da lista quede seleccionado

  • Como comentei anteriormente, a lista non selecciona o elemento ao premer sobre el.
Realmente estamos a facer click.
  • Para solucionalo podemos facer o seguinte:
O problema que ten esta solución é que ao borrar un elemento da lista, 'a fila' mantense seleccionada.
O poderíamos intentar arranxar accedendo ao View seleccionado (no método onItemClick da interface onItemClickListener, gardando o View nun atributo a nivel de Activity) e cambiando a cor de fondo a branco cando se dea de baixa.



  • Outra forma é empregar un recurso de Android denominado 'selectores'.
Os selectores son recursos que se crean no cartafol /res/drawable/. Son arquivos de texto onde se especifica, segundo o estado no que se atope un View, cambiar o que se vai debuxar (normalmente a cor de fondo).
Para probalo necesitamos acceder ao View que visualiza cada elemento da lista. Polo tanto non podemos empregar o Layout que subministra o S.O.
Como nun punto anterior xa empregamos un deseño propio, imos a empregalo.
  • Unha vez temos o selector, temos que asignar dito selector ao Constraint que deseñamos previamente.
Imos a asocialo á propiedade background do mesmo.



  • Agora a nivel de código imos a indicarlle que cargue o deseño personalizado:
    private void cargarDatos(){

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.elemento_listview,R.id.txvElemSpinner,datos);
        ListView listView = findViewById(R.id.lsvLista);
        listView.setAdapter(adapter);
    }



  • E como último paso temos que facer que cando se seleccione un elemento da lista, o view sexa 'seleccionado' e así se activaría o estado establecido no selector.
        ListView lsvLista = findViewById(R.id.lsvLista);
        lsvLista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                view.setSelected(true);
                
                posElemListaSelec = i;
                EditText et = findViewById(R.id.edtEditElemLista);
                et.setText(datos.get(i));
            }
        });




Caso Práctico 1

Se non o temos creado antes, crearemos un novo paquete de nome: Adaptadores como un subpaquete do teu paquete principal.






XML do Layout

  • Definimos no Layout unha vista de tipo ListView (Liñas 14-17).
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6 
 7     <TextView
 8         android:layout_width="match_parent"
 9         android:textSize="20sp"
10         android:layout_height="wrap_content"
11         android:text="Selecciona unha froita" />
12 
13     <ListView
14         android:id="@+id/lvFroitas_UD04_01_ListViews"
15         android:layout_width="match_parent"
16         android:layout_height="wrap_content" />
17 
18 </LinearLayout>



Código da Activity

  • A filosofía do código Java é moi semellante ao do Spinner.
 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.view.View;
 6 import android.widget.AdapterView;
 7 import android.widget.ArrayAdapter;
 8 import android.widget.ListView;
 9 import android.widget.TextView;
10 import android.widget.Toast;
11 
12 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
13 
14 public class UD04_01_ListViews extends Activity {
15 
16     private void cargarListas(){
17         //Fonte de datos
18         String[] froitas = new String[] { "Pera", "Mazá", "Plátano" };
19 
20         //Enlace do adaptador coa fonte de datos
21         ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, froitas);
22 
23         ListView lvFroitas = findViewById(R.id.lvFroitas_UD04_01_ListViews);
24         //Enlace do adaptador co ListView
25         lvFroitas.setAdapter(adaptador);
26     }
27     private void xestionarEventos(){
28 
29         ListView lvFroitas = findViewById(R.id.lvFroitas_UD04_01_ListViews);
30         //Escoitador
31         lvFroitas.setOnItemClickListener(new AdapterView.OnItemClickListener() {
32 
33             @Override
34             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
35                 // TODO Auto-generated method stub
36                 //Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(position), Toast.LENGTH_SHORT).show();
37                 Toast.makeText(getApplicationContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
38 
39             }
40         });
41     }
42 
43     @Override
44     protected void onCreate(Bundle savedInstanceState) {
45         super.onCreate(savedInstanceState);
46         setContentView(R.layout.activity_ud04_01__list_views);
47 
48         cargarListas();
49         xestionarEventos();
50     }
51 }
  • Liña 18: Ao igual que no Spinner, creamos unha fonte de datos, neste caso cun array estático.
  • Liña 21: Do mesmo xeito creamos o adaptador
  • Liña 25: E finalmente, vinculamos o adaptador ao ListView
  • Liña 31: O Escoitador asociado ao ListView.
  • Liñas 36,37: Ao igual que no spinner, neste caso a vista que recibimos cando facemos click nun ítem da view é do tipo TextView.



ListView usando un recurso XML ou un array dinámico

  • Neste caso funciona igual que o visto no Spinner que fai uso dun adaptador.



Caso Práctico 2: Utilizando un Layout con Ckeckboxes

Se non o temos creado antes, crearemos un novo paquete de nome: Adaptadores como un subpaquete do teu paquete principal.



  • Dentro do paquete Adaptadores crear unha nova 'Empty Activity' de nome: UD04_02_ListViews de tipo Launcher e sen compatibilidade.
Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.


  • Como comentamos ao inicio, ao crear o adaptador podemos facer uso de varios layouts xa definidos polo S.O. Android.
Un destes layouts permite que cada elemento da lista tenga un 'checkbox' asociado.
Para que funcione, debemos de:
  • Poñer no layout o atributo: android:choiceMode="multipleChoice"
  • Ou ben ter unha referencia ao ListView e cambia dito atributo por programación: refLista.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);



  • Se necesitamos programar algo cando se preme un elemento da lista non ten problema ningún, se fería como no Spinner. A única diferenza é que o View que ven no método 'onItemClick' da interface e de tipo 'CheckedTextView'. Facendo un cast a dito tipo, accederemos ao texto e se está checked ou non.
  • O máis complicado será no caso que necesitemos, cada vez que se pulsa un elemento, percorrer toda a lista checkeando cales dos elementos están marcados.
Para facer isto temos varias aproximacións:
  • Opción a)
Definir un ArrayList<String> e gardar nel os elementos que imos seleccionando ou quitando da lista os elementos que xa non están seleccionados.
Para saber cando un elemento está seleccionado ou non:
 1             private ArrayList<String>datos = new ArrayList<>();
 2             ...............
 3             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 4                 // TODO Auto-generated method stub
 5                 CheckedTextView c = (CheckedTextView)view;
 6                 if (c.isChecked()){
 7                     datos.add(c.getText().toString());
 8                 }
 9                 else {
10                     datos.remove(c.getText().toString());
11                 }
12            }
  • Opción b)
Facer uso da clase SparseBooleanArray e do método getCheckedItemPositions o cal devolve un obxecto da clase SparseBooleanArray coas posicións dos elementos seleccionados.
Para facer iso disto temos:
1                 SparseBooleanArray elems = referenciaLista.getCheckedItemPositions();
2                 for(int cont=0; cont < referenciaLista.getCount();cont++){
3                     if (elems.get(cont)){
4                        // Está seleccionado
5                     }
6                 }






XML do Layout

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     tools:context=".Adaptadores.UD04_02_ListViews">
 8 
 9     <LinearLayout
10         android:layout_width="0dp"
11         android:layout_height="149dp"
12         android:layout_marginEnd="32dp"
13         android:layout_marginStart="32dp"
14         android:layout_marginTop="8dp"
15         android:orientation="vertical"
16         app:layout_constraintEnd_toEndOf="parent"
17         app:layout_constraintStart_toStartOf="parent"
18         app:layout_constraintTop_toTopOf="parent">
19 
20         <ListView
21             android:id="@+id/lvCoches_UD04_02_ListViews"
22             android:layout_width="match_parent"
23             android:layout_height="0dp"
24             android:layout_marginEnd="8dp"
25             android:layout_marginStart="8dp"
26             android:layout_marginTop="8dp"
27             android:layout_weight="1"
28             android:choiceMode="multipleChoice">
29 
30         </ListView>
31     </LinearLayout>
32 
33     <TextView
34         android:id="@+id/tvSeleccionados_UD04_02_ListViews"
35         android:layout_width="0dp"
36         android:layout_height="wrap_content"
37         android:layout_marginBottom="8dp"
38         android:layout_marginEnd="8dp"
39         android:layout_marginStart="8dp"
40         android:textSize="24sp"
41         app:layout_constraintBottom_toBottomOf="parent"
42         app:layout_constraintEnd_toEndOf="parent"
43         app:layout_constraintStart_toStartOf="parent"
44         tools:text="Elementos seleccionados" />
45 
46 </android.support.constraint.ConstraintLayout>



Código da Activity

 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.text.Html;
 6 import android.util.SparseBooleanArray;
 7 import android.view.View;
 8 import android.widget.AdapterView;
 9 import android.widget.ArrayAdapter;
10 import android.widget.CheckedTextView;
11 import android.widget.ListView;
12 import android.widget.TextView;
13 import android.widget.Toast;
14 
15 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
16 
17 public class UD04_02_ListViews extends Activity {
18 
19     private void cargarListas(){
20         //Fonte de datos
21         String[] coches = new String[] { "FORD", "OPEL", "SEAT","CITROEN","VOLKSWAGEN","ONDA" };
22 
23         //Enlace do adaptador coa fonte de datos
24         ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_checked, coches);
25 
26         ListView lvCoches = findViewById(R.id.lvCoches_UD04_02_ListViews);
27         //Enlace do adaptador co ListView
28         lvCoches.setAdapter(adaptador);
29     }
30 
31     private void xestionarEventos(){
32 
33         final ListView lvCoches = findViewById(R.id.lvCoches_UD04_02_ListViews);
34 
35         //Escoitador
36         lvCoches.setOnItemClickListener(new AdapterView.OnItemClickListener() {
37 
38             @Override
39             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
40                 // TODO Auto-generated method stub
41                 CheckedTextView c = (CheckedTextView)view;
42                 Toast.makeText(getApplicationContext(),c.getText(),Toast.LENGTH_LONG).show();
43 
44                 TextView mensaxe = findViewById(R.id.tvSeleccionados_UD04_02_ListViews);
45                 mensaxe.setText("");
46                 SparseBooleanArray elems = lvCoches.getCheckedItemPositions();
47                 for(int cont=0; cont < lvCoches.getCount();cont++){
48                     if (elems.get(cont)){
49                        mensaxe.append(lvCoches.getItemAtPosition(cont).toString()+ Html.fromHtml("<br />"));
50                     }
51                 }
52 
53             }
54         });
55     }
56 
57 
58     @Override
59     protected void onCreate(Bundle savedInstanceState) {
60         super.onCreate(savedInstanceState);
61         setContentView(R.layout.activity_ud04_02__list_views);
62 
63         cargarListas();
64         xestionarEventos();
65     }
66 }




Operacións especiais

  • CASO PRÁCTICO:
  • Temos uns datos locais nun array baseados nunha clase na que existe un campo booleano que nos indica se temos ou non seleccionado o elemento.
  • Temos una lista de selección múltiple de tipo checkbox no seu layout (android.R.layout.simple_list_item_checked | android:choiceMode="multipleChoice")
  • Queremos que ao cargarse a lista, aparezan seleccionados os elementos do array que teñen a propiedade boolean a true.
Posible Solución:
 1         ListView lvLista = findViewById(R.id.id_lista);
 2         ArrayList<MiClase> datos = new ArrayList<>();
 3 
 4         // CARGAMOS O ARRAY CON DATOS. PODEN VIR DUNHA BASE DE DATOS OU CALQUERA OUTRA FONTE
 5 
 6         ArrayAdapter<MiClase> arrayAdapter = new ArrayAdapter<MiClase>(this,android.R.layout.simple_list_item_checked,datos);
 7         lvLista.setAdapter(arrayAdapter);
 8 
 9         for (int i=0;i<datos.size();i++) {
10             lvLista.setItemChecked(i,datos.get(i).getPropiedadeBoolean());
11         }


Introdución

  • O RecyclerView ten como función amosar ao usuario en forma de lista con scroll.
A diferenza con respecto ao ListView ou GridView vistos ata o de agora, é que con cantidades altas de datos, este compoñente é moito máis eficiente que os dous anteriores.
  • O RecyclerView xera todos os elementos da lista que se manden inicialmente, pero se engadimos novos elementos ou borramos non ten que volver a recrear toda a lista, soamente recrea os que sufriran algún cambio.
  • En operacións de eliminación, o RecyclerView reutiliza os view´s que conforman cada un dos elementos da lista (de aí ven o seu nome 'recycler') de tal forma que ao engadir novos elementos 'reutiliza' os view´s creados previamente para engadir os novos datos.
  • Un ArrayAdapter xera os views de todos os elementos da lista estean visualmente ou non visibles na lista e se hai algún cambio ten que volver a recrealos todos.


  • Por outra banda, o compoñente CardView serve para deseñar a forma en como se presenta a información de cada compoñente de lista.
Por exemplo, podemos indicar que cada elemento da lista que se amosa facendo uso do RecyclerView estea formado por unha ImageView e un TextView.
Este compoñente permite presentar información en forma de grupos, empregando unha forma de 'tarxeta'.
PDM investigac 4.jpg


PDM CardView 1.jpg
Exemplo de cardview obtida deste enlace.



Engadindo as librerías

  • O primeiro que temas que facer é engadir as librerías que van permitir que fagamos uso de ditos compoñentes.
Se arrastrades graficamente os compoñentes, ditas librerías xa que engaden automaticamente ao arquivo build.gradle (nivel de módulo)
1     implementation 'com.android.support:recyclerview-v7:28.0.0'
2     implementation 'com.android.support:cardview-v7:28.0.0'



Caso Práctico

Se non o temos creado antes, crea un paquete de nome Adaptadores como un subpaquete do teu paquete principal.
Dentro do paquete Adaptadores, crearemos un novo paquete de nome: Checkboxes.


  • Imos crear a seguinte Activity:
PDM CardView 7.jpg


  • Podedes descargar as imaxes dos planetas:
Archivo:Planetas.zip



  • Dentro do paquete Adaptadores crear unha nova 'Empty Activity' de nome: UD04_01_RecycleViewCardView de tipo Launcher e sen compatibilidade.
Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.
O layout asociado a dita activity terá un RecycleView ocupando o 100% do espazo cun margin superior de 24dp´s:
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3 xmlns:app="http://schemas.android.com/apk/res-auto"
 4 xmlns:tools="http://schemas.android.com/tools"
 5 android:layout_width="match_parent"
 6 android:layout_height="match_parent"
 7 tools:context=".UD2.Adaptadores.UD04_01_RecycleViewCardView">
 8 
 9 <android.support.v7.widget.RecyclerView
10     android:id="@+id/rvwRecycleView"
11     android:layout_width="match_parent"
12     android:layout_height="match_parent"
13     android:layout_marginTop="24dp"
14     app:layout_constraintBottom_toBottomOf="parent"
15     app:layout_constraintEnd_toEndOf="parent"
16     app:layout_constraintStart_toStartOf="parent"
17     app:layout_constraintTop_toTopOf="parent" />
18 </android.support.constraint.ConstraintLayout>



Creando o deseño do CardView

  • O CardView ven ser coma un layout que representa como se van visualizar cada unha das filas que conforman o RecycleView.
Polo tanto creamos un arquivo en /res/layout, un arquivo de nome 'card_layout_ud04_01_recycleviewcardview'.
PDM CardView 3.jpg
Agora engadimos o layout que queremos que teña cada fila e os compoñentes que queiramos que aparezan.
Terá que engadirse o layout dentro da etiqueta <CardView>.
No exemplo imos facer que apareza unha imaxe e un texto asociado a dita imaxe e imos empregar un ContraintLayout para facelo (se podería empregar calquera dos que vimos).
Fixarse que:
  • Na altura do layout e do CardView, imos poñer 'wrap_content' para que soamente ocupe o alto do compoñente que sexa máis alto (neste exemplo a foto).
  • O ancho e alto da imaxe vai ser de 100x100 dp´s e desprazada á esquerda.
  • O texto ocupa todo o espazo restante e está centrado con respecto á foto. Ten unha separación esquerda con respecto á foto e un tamaño de texto grande.
  • O texto ten unha cor vermella defina por nos nun arquivo de recurso /res/values/


 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent" android:layout_height="wrap_content">
 6 
 7     <android.support.constraint.ConstraintLayout
 8         android:id="@+id/ConstraintLayout"
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content">
11 
12         <ImageView
13             android:id="@+id/imgImaxe_UD04_01_CardLayout"
14             android:layout_width="100dp"
15             android:layout_height="100dp"
16             android:contentDescription="Imaxe"
17             app:layout_constraintEnd_toStartOf="@+id/tvTexto_UD04_01_CardView"
18             app:layout_constraintStart_toStartOf="parent"
19             app:layout_constraintTop_toTopOf="parent"
20             app:srcCompat="@mipmap/ic_launcher2" />
21 
22         <TextView
23             android:id="@+id/tvTexto_UD04_01_CardView"
24             android:layout_width="0dp"
25             android:layout_height="wrap_content"
26             android:paddingStart="5dp"
27             android:text="Texto a amosar por fila"
28             android:textColor="@color/corvermello"
29             android:textSize="24sp"
30             app:layout_constraintBottom_toBottomOf="parent"
31             app:layout_constraintEnd_toEndOf="parent"
32             app:layout_constraintStart_toEndOf="@+id/imgImaxe_UD04_01_CardLayout"
33             app:layout_constraintTop_toTopOf="parent" />
34     </android.support.constraint.ConstraintLayout>
35 </android.support.v7.widget.CardView>


  • Fixarse que temos unha serie de propiedades específicas do cardview:
PDM CardView 4.jpg
Podedes consultar a lista completa neste enlace.
Entre as que imos modificar están:
  • cardBackgroundColor: Cor de fondo da tarxeta
  • cardCornerRadius: O perfil redondeado das tarxetas
  • cardElevation: Elevación (Material Design)
  • contentPadding: Padding de todo o contido que está dentro da tarxeta.
  • Para separar unha tarxeta de outra podemos facer uso dos margin a nivel de CardView



 1 <?xml version="1.0" encoding="utf-8"?>
 2 <?xml version="1.0" encoding="utf-8"?>
 3 <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
 4     xmlns:app="http://schemas.android.com/apk/res-auto"
 5     xmlns:tools="http://schemas.android.com/tools"
 6     android:layout_width="match_parent"
 7     android:layout_height="wrap_content"
 8     android:layout_margin="5dp"
 9     app:cardBackgroundColor="#81C784"
10     app:cardCornerRadius="12dp"
11     app:cardElevation="3dp"
12     app:contentPadding="4dp">
13 
14     <android.support.constraint.ConstraintLayout
15         android:id="@+id/ConstraintLayout"
16         android:layout_width="match_parent"
17         android:layout_height="wrap_content">
18 
19         <ImageView
20             android:id="@+id/imgImaxe_UD04_01_CardLayout"
21             android:layout_width="100dp"
22             android:layout_height="100dp"
23             android:contentDescription="Imaxe"
24             app:layout_constraintEnd_toStartOf="@+id/tvTexto_UD04_01_CardView"
25             app:layout_constraintStart_toStartOf="parent"
26             app:layout_constraintTop_toTopOf="parent"
27             app:srcCompat="@mipmap/ic_launcher2" />
28 
29         <TextView
30             android:id="@+id/tvTexto_UD04_01_CardView"
31             android:layout_width="0dp"
32             android:layout_height="wrap_content"
33             android:paddingStart="5dp"
34             android:text="Texto a amosar por fila"
35             android:textColor="@color/corvermello"
36             android:textSize="24sp"
37             app:layout_constraintBottom_toBottomOf="parent"
38             app:layout_constraintEnd_toEndOf="parent"
39             app:layout_constraintStart_toEndOf="@+id/imgImaxe_UD04_01_CardLayout"
40             app:layout_constraintTop_toTopOf="parent" />
41     </android.support.constraint.ConstraintLayout>
42 </android.support.v7.widget.CardView>



Creando o Adaptador

  • Un adaptador:
    • é un elemento intermediario entre unha fonte de datos (XML, Arrays, Ficheiros, BBDD) e un interface de usuario que amosa eses datos, por exemplo un Spinner, unha lista de Selección, etc.
    • Por cada dato crea unha View e a representa.
    • É o responsable de xerar todos os elementos de representación asociados aos datos. Imaxinar que cada ítem estivera formado por dous subcompoñentes: nome de persoa e foto. O adaptador debe ser quen de poder representar iso.
  • No caso do RecycleView, vai empregar un adaptador que deriva da clase RecycleView.Adapter.
Polo tanto imos crear unha clase que derive dela.
PDM CardView 5.jpg


Ao facelo dará un erro no que se nos informa que debemos de implementar unha serie de métodos.
 1 package cifprodolfoucha.cursoandroid.aprendiendo.UD2.Adaptadores;
 2 
 3 import android.support.annotation.NonNull;
 4 import android.support.v7.widget.RecyclerView;
 5 import android.view.ViewGroup;
 6 
 7 public class RecycleViewAdapter_UD04_01_RecycleViewCardView extends RecyclerView.Adapter {
 8     @NonNull
 9     @Override
10     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
11         return null;
12     }
13 
14     @Override
15     public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
16 
17     }
18 
19     @Override
20     public int getItemCount() {
21         return 0;
22     }
23 }
Como vemos se implementan os seguintes métodos:
  • getItemCount(): Ten que devolver o número de elementos que se van visualizar na lista.
  • onCreateViewHolder(): Este método ten que devolver un obxecto da clase ViewHolder a cal é empregada para visualizar o contido da lista. Será na clase ViewHolder onde 'cargaremos' o deseño de fila feito no paso anterior.
  • onBindViewHolder(): Este método recibe o ViewHolder do método anterior e asociamos a cada compoñente gráfico de dito View o dato que queremos que visualice.


  • Neste adaptador é onde teremos que 'obter' os datos que conformarán as filas.
Poderíamos obtelos dunha consulta a unha base de datos ou de calquera outra fonte (internet, un arquivo,...).
No exemplo imos definilos localmente...
No noso exemplo tedes que descargar imaxes de varios planetas (eu o fixen con 5) e gardalas no cartafol /res/drawable
Os datos serán os seguintes (adaptalos ao voso caso):
 1 package cifprodolfoucha.cursoandroid.aprendiendo.UD2.Adaptadores;
 2 
 3 import android.support.annotation.NonNull;
 4 import android.support.v7.widget.RecyclerView;
 5 import android.view.ViewGroup;
 6 
 7 public class RecycleViewAdapter_UD04_01_RecycleViewCardView extends RecyclerView.Adapter {
 8 
 9     private String[] textos = {"Mercurio","Venus","Tierra","Jupiter","Saturno"};
10     private int[] imaxes = {R.drawable.mercurio,R.drawable.venus,R.drawable.tierra,R.drawable.jupiter,R.drawable.saturno};
11 
12     @NonNull
13     @Override
14     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
15         return null;
16     }
17     .......
Nota: Fixarse na orde e como o número de elemento dentro do array se corresponde nos dous arrays có mesmo concepto (na posición 0 do array está o texto e a imaxe de Mercurio).



Definindo a clase ViewHolder

  • Lembrar que o ViewHolder vai ser o que emprege o adaptador para 'cargar' os datos nos elementos gráficos que conforman cada fila (no noso exemplo, unha imaxe e un texto).
Creamos por tanto unha clase que derive de RecycleView.ViewHolder (poderíamos creala dentro da clase RecycleAdapter) :
PDM CardView 6.jpg
Ao facelo daranos un erro de que hai que implementar un constructor. O facemos có asistente.
 1 package cifprodolfoucha.cursoandroid.aprendiendo.UD2.Adaptadores;
 2 
 3 import android.support.annotation.NonNull;
 4 import android.support.v7.widget.RecyclerView;
 5 import android.view.View;
 6 
 7 public class ViewHolder_UD04_01_RecycleViewCardView extends RecyclerView.ViewHolder {
 8 
 9     public ViewHolder_UD04_01_RecycleViewCardView(@NonNull View itemView) {
10         super(itemView);
11     }
12 }


Esta clase vai ser a que nos permite acceder aos elementos gráficos definidos no CardView (o que está definido no layout que representa cada fila).
Desta forma dende o Adapter imos poder cargar con datos os elementos gráficos.
Ao constructor de esta clase vai vir (o veremos no seguinte paso) unha instancia de 'card_layout_ud04_01_recycleviewcardview'.
Simplemente referenciaremos ditos controis para poder manexalos dende o adaptador.
Modificamos o código polo seguinte:
 1 public class ViewHolder_UD04_01_RecycleViewCardView extends RecyclerView.ViewHolder {
 2 
 3     public ImageView itemImaxe;
 4     public TextView itemTexto;
 5 
 6     public ViewHolder_UD04_01_RecycleViewCardView(@NonNull View itemView) {
 7         super(itemView);
 8 
 9         itemImaxe = itemView.findViewById(R.id.imgImaxe_UD04_01_CardLayout);
10         itemTexto = itemView.findViewById(R.id.tvTexto_UD04_01_CardView);
11     }
12 }



Completando o funcionamento do adaptador


Instanciando o ViewHolder

  • Como dixemos antes, o método onCreateViewHolder ten que 'devolver' un obxecto ViewHolder no que se atopan os elementos gráficos que conforman a fila.
A clase na que se vai basear van ser a que fixemos nos pasos anteriores e que derivaba de ViewHolder (ViewHolder_UD04_01_RecycleViewCardView).
Para facelo temos que realizar un proceso de 'inflar' o layout que conforma cada fila (card_layout_ud04_01_recycleviewcardview.xml) a un obxecto da clase View.
E despois crear un obxecto da clase ViewHolder_UD04_01_RecycleViewCardView en base ao View obtido anteriormente.


  • Para facer isto primeiro temos que 'converter' o layout onde están definidos os elementos gráficos que conforman a fila a un View.
Para iso empregamos a clase LayoutInflater.
  • Primeiro obtemos unha referencia a dita clase dunha das seguintes forma:
  • LayoutInflater mInflater = (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  • LayoutInflater mInflater = LayoutInflater.from(viewgroup.getContext());
  • Despois chamamos ao método 'inflate' para que devolva por programación unha referencia ao layout onde están definidos os elementos gráficos da fila (un View):
  • View v = mInflater.inflate(R.layout.card_layout_ud04_01_recycleviewcardview,viewGroup,false);
  • E por último creamos o ViewHolder creando un obxecto da clase ViewHolder creada por nos previamente (ViewHolder_UD04_01_RecycleViewCardView) e pasando como parámetro no constructor o View anterior:
  • RecyclerView.ViewHolder viewHolder = new ViewHolder_UD04_01_RecycleViewCardView(v);


 1     @NonNull
 2     @Override
 3     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
 4 
 5         LayoutInflater mInflater = (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 6         //View view = (LayoutInflater.from(viewGroup.getContext()))
 7         View v = mInflater.inflate(R.layout.card_layout_ud04_01_recycleviewcardview,viewGroup,false);
 8         RecyclerView.ViewHolder viewHolder = new ViewHolder_UD04_01_RecycleViewCardView(v);
 9 
10         return viewHolder;
11     }



Engadindo datos ao ViewHolder

  • Os datos, tedes que lembrar, que están definidos en dous arrays, pero podedes ter un único arrays de obxectos dunha clase e recollelos dese array.
O que si ides ter sempre é a lo menos un array de elementos con información.
  • Outro método que vimos que se creaba cando creamos o RecycleView.Adapter era o onBindViewHolder.
Neste método imos a 'meter' os datos que queremos que aparezan no ViewHolder creado no paso anterior.^:
Para iso temos que empregar o parámetro 'i' que indica o número de elemento do array sobre o que temos que buscar a información e despois asociala aos elementos gráficos.
Por outra banda como o obxecto da clase ViewHolder pertence realmente á clase ViewHolder_UD04_01_RecycleViewCardView, podemos acceder aos seus elementos gráficos xa que están declarados como 'public' na definición da clase.
  • O código queda como o seguinte:
1     @Override
2     public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
3 
4         ViewHolder_UD04_01_RecycleViewCardView viewHolderMeu = (ViewHolder_UD04_01_RecycleViewCardView) viewHolder;
5         viewHolderMeu.itemImaxe.setImageResource(imaxes[i]);
6         viewHolderMeu.itemTexto.setText(textos[i]);
7     }



Implementando o método getItemCount

  • Como indicamos anteriormente, dito método ten que devolver o número de elementos da lista, que debe de coincidir có número de elementos do array onde están os datos.
Polo tanto:
1     @Override
2     public int getItemCount() {
3         return textos.length;
4     }



Paso final

  • Por último temos que facer dúas cousas:
  • 1º Paso: O RecycleView necesita un Layout Manager que lle diga como van distribuídos cada un dos elementos que van aparecer.
A forma máis común de facelo é cun LinearLayout e que vaian en forma de fila, pero podemos empregar outras distribucións.


PDM CardView 8.jpg
Na imaxe anterior vemos:
  • Exemplo de LinearLayout con distribución vertical (por defecto):
  • RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
  • Exemplo de LinearLayout con distribución horizontal:
  • RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
  • Exemplo de GridLayout con dúas columnas:
  • RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this,2);
Unha vez creado o LayoutManager hai que asocialo ao RecycleView.
  • 2º Paso: Hai que crear unha instancia do adaptador creado por nos (RecycleViewAdapter_UD04_01_RecycleViewCardView) e asocialo ao RecycleView.


 1 package cifprodolfoucha.cursoandroid.aprendiendo.UD2.Adaptadores;
 2 
 3 import android.support.v7.app.AppCompatActivity;
 4 import android.os.Bundle;
 5 import android.support.v7.widget.GridLayoutManager;
 6 import android.support.v7.widget.LinearLayoutManager;
 7 import android.support.v7.widget.RecyclerView;
 8 
 9 import cifprodolfoucha.cursoandroid.aprendiendo.R;
10 
11 public class UD04_01_RecycleViewCardView extends AppCompatActivity {
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_ud04_01__recycle_view_card_view);
17 
18         RecycleViewAdapter_UD04_01_RecycleViewCardView recycleAdapter = new RecycleViewAdapter_UD04_01_RecycleViewCardView();
19 
20         RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this,2);
21         RecyclerView recyclerView = findViewById(R.id.rvwRecycleView);
22         recyclerView.setLayoutManager(layoutManager);
23         recyclerView.setAdapter(recycleAdapter);
24 
25     }
26 }




Xestionar eventos de Click´s sobre os elementos

  • Podemos modificar un par de propiedades do layout asociado ao cardview para que cando prememos apareza un efecto de 'selección' sobre o elemento premido.
 1 <?xml version="1.0" encoding="utf-8"?>
 2 
 3 <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
 4     xmlns:app="http://schemas.android.com/apk/res-auto"
 5     xmlns:tools="http://schemas.android.com/tools"
 6     android:layout_width="match_parent"
 7     android:layout_height="wrap_content"
 8     android:layout_margin="5dp"
 9     android:foreground="?android:attr/selectableItemBackground"
10     android:clickable="true"
11     android:focusable="true"
12     app:cardBackgroundColor="#81C784"
13     app:cardCornerRadius="12dp"
14     app:cardElevation="3dp"
15     app:contentPadding="4dp">
16 
17      .....


  • Podedes ler máis acerca deste tipo de animacións neste enlace.



  • Se queremos xestionar o evento do Click o podemos facer:
  • Sobre todo o conxunto de elementos que conforman a interface gráfica da fila.
  • Sobre algún dos elementos que conforman a interface gráfica da fila.


  • Caso a) Xestión do Click sobre todo o conxunto No primeiro caso temos que facer uso do obxecto itemView que se atopa dispoñible na clase ViewHolder e que representa o CardView con todo:
 1 public class ViewHolder_UD04_01_RecycleViewCardView extends RecyclerView.ViewHolder {
 2 
 3     public ImageView itemImaxe;
 4     public TextView itemTexto;
 5 
 6     public ViewHolder_UD04_01_RecycleViewCardView(@NonNull final View itemView) {
 7         super(itemView);
 8 
 9         itemImaxe = itemView.findViewById(R.id.imgImaxe_UD04_01_CardLayout);
10         itemTexto = itemView.findViewById(R.id.tvTexto_UD04_01_CardView);
11 
12         itemView.setOnClickListener(new View.OnClickListener() {
13             @Override
14             public void onClick(View v) {
15                 int posicion = getAdapterPosition();
16                 Toast.makeText(v.getContext(),"Pulsado elemento " + posicion + " da lista.",Toast.LENGTH_SHORT).show();
17             }
18         });
19     }
20 }
  • Liña 15: Dispoñemos do método getAdapterPosition() que nos devolve a posición do elemento seleccionado da lista.


Nota: Isto mesmo o podemos facer dende a clase 'RecycleViewAdapter_UD04_01_RecycleViewCardView' xa que lembrar que o view que pasamos como parámetro ao constructor do ViewHolder é o que empregamos no exemplo anterior.


  • Caso b) Xestión do Click sobre un view do conxunto
Neste caso debemos de rexistrar o evento de Click sobre o view que nos interese.
O podemos facer na clase ViewHolder ou na clase RecycleViewAdapter_UD04_01_RecycleViewCardView.
 1 public class ViewHolder_UD04_01_RecycleViewCardView extends RecyclerView.ViewHolder {
 2 
 3     public ImageView itemImaxe;
 4     public TextView itemTexto;
 5 
 6     public ViewHolder_UD04_01_RecycleViewCardView(@NonNull final View itemView) {
 7         super(itemView);
 8 
 9         itemImaxe = itemView.findViewById(R.id.imgImaxe_UD04_01_CardLayout);
10         itemTexto = itemView.findViewById(R.id.tvTexto_UD04_01_CardView);
11 
12         itemImaxe.setOnClickListener(new View.OnClickListener() {
13             @Override
14             public void onClick(View v) {
15                 int posicion = getAdapterPosition();
16                 Toast.makeText(v.getContext(),"Pulsado elemento " + posicion + " da lista.",Toast.LENGTH_SHORT).show();
17             }
18         });
19     }
20 }
Nota: Fixarse que agora soamente responderá ao evento de facer click sobre a imaxe.



Pasando información

  • Todos view´s dispoñen dunha propiedade Tag asociada na que se pode gardar calquera tipo de información, xa que permite gardar un obxecto de calquera clase.
Polo tanto podemos empregar dita propiedade para 'asociar' información a un view.
Nun exemplo real, teríamos unha clase onde gardaríamos os datos de cada elemento da lista. Por exemplo, unha clase Planeta, con datos coma o nome, ruta e nome da imaxe na sd, dimensións, velocidade de rotación,...e moitos máis datos.
No adaptador do RecycleView teríamos un ArrayList da clase Planeta e non dous arrays separados como temos agora.
Na lista soamente aparecería a imaxe e nome do planeta, pero nos querremos acceder a todos os seus datos e non soamente aos que aparecen 'visualmente'.


  • Imos modificar o exemplo para empregar esta clase Planeta:
Arquivo: Planeta_UD04_01_RecycleViewCardView.java
 1 package cifprodolfoucha.cursoandroid.aprendiendo.UD2.Adaptadores;
 2 
 3 public class Planeta_UD04_01_RecycleViewCardView {
 4 
 5     int id;
 6     String nombre;
 7     boolean habitable;
 8     int fotoId;
 9     
10     public Planeta_UD04_01_RecycleViewCardView(int id, String nombre, boolean habitable,int fotoId){
11         this.id = id;
12         this.nombre = nombre;
13         this.habitable = habitable;
14         this.fotoId = fotoId;
15     }
16 
17     public int getId() {
18         return id;
19     }
20 
21     public String getNombre() {
22         return nombre;
23     }
24 
25     public boolean isHabitable() {
26         return habitable;
27     }
28 
29     public int getFotoId() {
30         return fotoId;
31     }    
32 
33     @Override
34     public String toString(){
35         return "Planeta con id " + id + " e de nome " + nome + (habitable ? " é habitable." : " non é habitable");
36     }
37    
38 }



  • Modificamos a clase adaptadora e empregaremos un ArrayList de obxectos pertencentes á clase anterior.
Estes datos poderían vir dunha base de datos...
Clase RecycleViewAdapter_UD04_01_RecycleViewCardView
 1 package cifprodolfoucha.cursoandroid.aprendiendo.UD2.Adaptadores;
 2 
 3 import android.content.Context;
 4 import android.support.annotation.NonNull;
 5 import android.support.v7.widget.RecyclerView;
 6 import android.view.LayoutInflater;
 7 import android.view.View;
 8 import android.view.ViewGroup;
 9 
10 import java.util.ArrayList;
11 
12 import cifprodolfoucha.cursoandroid.aprendiendo.R;
13 
14 public class RecycleViewAdapter_UD04_01_RecycleViewCardView extends RecyclerView.Adapter {
15 
16     private ArrayList<Planeta_UD04_01_RecycleViewCardView>planetas = new ArrayList<Planeta_UD04_01_RecycleViewCardView>();
17 
18 
19     public RecycleViewAdapter_UD04_01_RecycleViewCardView(){
20 
21         planetas.add(new Planeta_UD04_01_RecycleViewCardView(1,"MERCURIO",false,R.drawable.mercurio));
22         planetas.add(new Planeta_UD04_01_RecycleViewCardView(2,"VENUS",false,R.drawable.venus));
23         planetas.add(new Planeta_UD04_01_RecycleViewCardView(3,"TIERRA",false,R.drawable.tierra));
24         planetas.add(new Planeta_UD04_01_RecycleViewCardView(4,"JUPITER",false,R.drawable.jupiter));
25         planetas.add(new Planeta_UD04_01_RecycleViewCardView(5,"SATURNO",false,R.drawable.saturno));
26 
27     }
28 
29     @NonNull
30     @Override
31     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
32 
33         LayoutInflater mInflater = (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
34         //View view = (LayoutInflater.from(viewGroup.getContext()))
35         View v = mInflater.inflate(R.layout.card_layout_ud04_01_recycleviewcardview,viewGroup,false);
36         RecyclerView.ViewHolder viewHolder = new ViewHolder_UD04_01_RecycleViewCardView(v);
37 
38         return viewHolder;
39     }
40 
41     @Override
42     public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
43 
44         ViewHolder_UD04_01_RecycleViewCardView viewHolderMeu = (ViewHolder_UD04_01_RecycleViewCardView) viewHolder;
45         viewHolderMeu.itemImaxe.setImageResource(planetas.get(i).getFotoId());
46         viewHolderMeu.itemTexto.setText(planetas.get(i).getNombre());
47     }
48 
49     @Override
50     public int getItemCount() {
51         return planetas.size();
52     }
53 }


  • Agora queremos pasar dalgunha forma o obxecto seleccionado (e fixarse que digo obxecto) ao view, de tal forma que cando preme sobre o elemento da lista, poida recuperar a información completa do obxecto.
Para iso facemos uso do método setTag() e getTag().


Clase RecycleViewAdapter_UD04_01_RecycleViewCardView

1     @Override
2     public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
3 
4         ViewHolder_UD04_01_RecycleViewCardView viewHolderMeu = (ViewHolder_UD04_01_RecycleViewCardView) viewHolder;
5 
6         viewHolderMeu.itemView.setTag(planetas.get(i));
7         viewHolderMeu.itemImaxe.setImageResource(planetas.get(i).getFotoId());
8         viewHolderMeu.itemTexto.setText(planetas.get(i).getNome());
9     }
Nota: Non se pode facer no método 'onCreateViewHolder' xa que o 'int i' non se corresponde có índice do elemento que vai visualizarse.

Clase ViewHolder_UD04_01_RecycleViewCardView

 1 public class ViewHolder_UD04_01_RecycleViewCardView extends RecyclerView.ViewHolder {
 2 
 3     public ImageView itemImaxe;
 4     public TextView itemTexto;
 5 
 6     public ViewHolder_UD04_01_RecycleViewCardView(@NonNull final View itemView) {
 7         super(itemView);
 8 
 9         itemImaxe = itemView.findViewById(R.id.imgImaxe_UD04_01_CardLayout);
10         itemTexto = itemView.findViewById(R.id.tvTexto_UD04_01_CardView);
11 
12         itemView.setOnClickListener(new View.OnClickListener() {
13             @Override
14             public void onClick(View v) {
15                 Planeta_UD04_01_RecycleViewCardView planetaSeleccionado = (Planeta_UD04_01_RecycleViewCardView) v.getTag();
16 
17                 Toast.makeText(v.getContext(),"Pulsado elemento " + getAdapterPosition() + " da lista.\n" + planetaSeleccionado,Toast.LENGTH_SHORT).show();
18             }
19         });
20     }
21 }



Engadindo-Borrando-Actualizando elementos

  • Se facemos calquera destas operacións teremos que informar ao adaptador que hai cambios para que volva a cargar os elementos da lista.
Para iso teremos que chamar o método notifyDataSetChanged().
O malo que ten esta chamada é que é pouco eficiente xa que reconstrúe todos os view´s do RecyclerView.
Normalmente se chama cando temos moitas operacións ou cambios na estructura de elementos.
É mais eficiente chamar aos seguintes métodos:
  • notifyItemChanged(int)
  • notifyItemInserted(int)
  • notifyItemRemoved(int)
  • notifyItemRangeChanged(int, int)
  • notifyItemRangeInserted(int, int)
  • notifyItemRangeRemoved(int, int)
Podedes consultar o que fai cada un neste enlace.


  • Seguindo có noso exemplo, imos agregar un botón á activity do RecyclerView (no meu caso engadín un FloatActionButton):

Layout activity_ud04_01_recycle_view_card_view

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3 xmlns:app="http://schemas.android.com/apk/res-auto"
 4 xmlns:tools="http://schemas.android.com/tools"
 5 android:layout_width="match_parent"
 6 android:layout_height="match_parent"
 7 tools:context=".UD2.Adaptadores.UD04_01_RecycleViewCardView">
 8 
 9 <android.support.v7.widget.RecyclerView
10     android:id="@+id/rvwRecycleView"
11     android:layout_width="match_parent"
12     android:layout_height="match_parent"
13     android:layout_marginTop="24dp"
14     app:layout_constraintBottom_toBottomOf="parent"
15     app:layout_constraintEnd_toEndOf="parent"
16     app:layout_constraintStart_toStartOf="parent"
17     app:layout_constraintTop_toTopOf="parent" />
18 
19     <android.support.design.widget.FloatingActionButton
20         android:id="@+id/fabAdd_ud04_01_recyclecardview"
21         android:layout_width="wrap_content"
22         android:layout_height="wrap_content"
23         android:layout_margin="20dp"
24         android:clickable="true"
25         app:layout_constraintBottom_toBottomOf="parent"
26         app:layout_constraintEnd_toEndOf="parent"
27         app:srcCompat="@android:drawable/ic_input_add" />
28 </android.support.constraint.ConstraintLayout>


  • Agora os datos van vir dende a Activity e non van estar definidos no clase Adaptadora.
Para pasar os datos a dita clase, faremos uso do constructor da clase Adaptadora.

Clase RecycleViewAdapter_UD04_01_RecycleViewCardView

 1   ..........
 2   public class RecycleViewAdapter_UD04_01_RecycleViewCardView extends RecyclerView.Adapter {
 3 
 4     private ArrayList<Planeta_UD04_01_RecycleViewCardView>planetas;
 5 
 6     public RecycleViewAdapter_UD04_01_RecycleViewCardView(ArrayList<Planeta_UD04_01_RecycleViewCardView> planetas){
 7         this.planetas = planetas;
 8     }
 9 
10    .......


  • Na activity agora é onde teríamos que buscar os datos a unha base de datos, por exemplo, e pasalos á clase Adaptadora no constructor.

Activity UD04_01_RecycleViewCardView

 1 package cifprodolfoucha.cursoandroid.aprendiendo.UD2.Adaptadores;
 2 
 3 import android.support.design.widget.FloatingActionButton;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.support.v7.widget.GridLayoutManager;
 7 import android.support.v7.widget.LinearLayoutManager;
 8 import android.support.v7.widget.RecyclerView;
 9 import android.view.View;
10 import android.widget.AdapterView;
11 import android.widget.ListView;
12 
13 import java.util.ArrayList;
14 
15 import cifprodolfoucha.cursoandroid.aprendiendo.R;
16 
17 public class UD04_01_RecycleViewCardView extends AppCompatActivity {
18 
19     private RecycleViewAdapter_UD04_01_RecycleViewCardView recycleAdapter;
20 
21     private ArrayList<Planeta_UD04_01_RecycleViewCardView>planetas;
22 
23     private void inicializarDatosPlanetas(){
24 
25         planetas = new ArrayList<>();
26 
27         planetas.add(new Planeta_UD04_01_RecycleViewCardView(1,"MERCURIO",false,R.drawable.mercurio));
28         planetas.add(new Planeta_UD04_01_RecycleViewCardView(2,"VENUS",false,R.drawable.venus));
29         planetas.add(new Planeta_UD04_01_RecycleViewCardView(3,"TIERRA",false,R.drawable.tierra));
30         planetas.add(new Planeta_UD04_01_RecycleViewCardView(4,"JUPITER",false,R.drawable.jupiter));
31         planetas.add(new Planeta_UD04_01_RecycleViewCardView(5,"SATURNO",false,R.drawable.saturno));
32 
33     }
34     private void inicializarRecycleView(){
35 
36         recycleAdapter = new RecycleViewAdapter_UD04_01_RecycleViewCardView(planetas);
37 
38         RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
39         RecyclerView recyclerView = findViewById(R.id.rvwRecycleView);
40         recyclerView.setLayoutManager(layoutManager);
41         recyclerView.setAdapter(recycleAdapter);
42 
43 
44     }
45 
46     private void xestionarEventos(){
47 
48         FloatingActionButton fab = findViewById(R.id.fabAdd_ud04_01_recyclecardview);
49         fab.setOnClickListener(new View.OnClickListener() {
50             @Override
51             public void onClick(View v) {
52                 planetas.add(new Planeta_UD04_01_RecycleViewCardView(6,"URANO",false,R.drawable.ic_menu_camera));
53                 recycleAdapter.notifyItemInserted(planetas.size());
54             }
55         });
56 
57     }
58 
59 
60     @Override
61     protected void onCreate(Bundle savedInstanceState) {
62         super.onCreate(savedInstanceState);
63         setContentView(R.layout.activity_ud04_01__recycle_view_card_view);
64 
65         inicializarDatosPlanetas();
66         inicializarRecycleView();
67         xestionarEventos();
68 
69     }
70 }
  • Liña 36: Agora pasamos os datos ao Adaptador mediante o constructor.
  • Liña 53: Fixarse como agora, cando engadimos un novo planeta ao ArrayList, chamamos ao método notifyItemInserted, indicando a posición do elemento engadido.
Probar a cambiar o código e facer que cando se preme o botón se borre o primeiro planeta da lista.




Enlace a la página principal de la UD4

Enlace a la página principal del curso




-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2018).