Diferencia entre revisiones de «PDM RecyclerView e CardView»

De MediaWiki
Ir a la navegación Ir a la búsqueda
Línea 37: Línea 37:
 
: Se non o temos creado antes, crea un paquete de nome '''Adaptadores''' como un subpaquete do teu paquete principal.
 
: 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'''.
 
: Dentro do paquete Adaptadores, crearemos un novo paquete de nome: '''Checkboxes'''.
 +
 +
 +
* Imos crear a seguinte Activity:
 +
[[Imagen:PDM_CardView_7.jpg|500px|center]]
 +
 +
  
  

Revisión del 18:03 17 oct 2019

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.
Basicamente reutiliza os views que conforman cada un dos elementos da lista, de aí ven o seu nome 'recycler'.
  • 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




  • 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.
  • Dispoñemos tipos de adaptadores pero imos usar: ArrayAdapter, que proporciona un interface de selección a través dun array de obxecto de calquera tipo.
  • 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 un índica que nos di cal elemento da lista de datos imos visualizar graficamente.


  • 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 que 'asociar' o adaptador ao RecycleView.




-- Ángel D. Fernández González -- (2018).