ListView

De MediaWiki
Ir a la navegación Ir a la búsqueda

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.

Caso Práctico 1

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_01_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.




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         }



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