PDM Xestión de Eventos

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

Introdución


  • Nos móbiles, o usuario normalmente interactúa coas aplicacións tocando sobre a pantalla táctil.
Este tipo de eventos denomínanse Input Events.


  • A forma en que Android ten para xestionar os eventos é mediante o uso de Interfaces.
Este tipo de interface denomínanse xestores de eventos ou EventListener.
  • A idea é que aquela compoñente que se queira xestionar algún evento, terá que rexistrar a interface asociada para dito evento.
Unha vez rexistrada (iso se fai facendo uso dun método, o veremos a continuación) poderemos implementar o código da Interface, no que estarán definidos os métodos que conforman o evento a controlar.
Ditos métodos serán chamados polo S.O. Android cando se produza o evento sobre o compoñente gráfico.


  • Para xestionar os eventos de calquera compoñente gráfico teremos que dirixirnos a páxina dese compoñente e ver cales son as interfaces que pode implementar para xestionar os diferentes tipos de evento.
Se ides á paxina de referencia de AndroidDeveloper e escolledes a categoría de Android.View => Interfaces, podedes ver todos os eventos que poden xestionar os view e por extensión, calquera compoñente gráfico. Podedes consultar este enlace.
PDM eventos 1.jpg
  • Como dixemos antes, os eventos no que o usuario iteraciona son os Event Listener.
Estes eventos se atopan definidos en interfaces e dentro delas están definidos algún dos seguintes métodos:


PDM eventos 2.jpg
Imaxe obtida dende developer.android.com
Na imaxe anterior están suliñadas as interfaces asociadas a cada evento.
Neste enlace tedes os método que deberíamos empregar nun view para rexistrar algunha das interfaces anteriores.


  • Cabe indicar que poden producirse varios eventos 'á vez' e estes son xestionados por medio dunha cola FIFO.
Por exemplo, cando prememos unha lista na pantalla e mantemos premido durante un rato, normalmente aparece un menú emerxente con opcións sobre a lista.
Nese caso produciuse dous eventos: OnLongClick e Click sobre a lista. Primeiro se lanzará o 'Long Click' e despois o 'Click'.



Preparación proxecto

  • Partimos que xa temos creado o proxecto inicial como xa indicamos anteriormente.
  • Comezaremos creando un novo paquete de nome: Eventos.


  • Para informar ao usuario imos facer uso da clase Toast.
É un tipo de notificación e serve para amosar unha mensaxe curta que aparece e desaparece automaticamente. Non require intervención por parte do usuario.
PDM eventos 3.jpg
A forma mais sinxela de chamala é:
1    Toast.makeText(getApplicationContext(),"AVISO",Toast.LENGTH_LONG).show();
  • O primeiro parámetro é unha referencia ao contexto. O contexto é unha interface (todas as activities derivan dela) que nos vai servir para acceder aos recursos da aplicación.
Normalmente se obtén chamando ao método getApplicationContext()
  • O segundo parámetro é o texto que queremos amosar ao usuario.
Lembrade que no voso proxecto tedes que ter soporte para varios idiomas, polo tanto as mensaxes teñen que referenciarse da forma: R.id.
  • O terceiro parámetro é o tempo que vai amosarse a mensaxe. Pode ser Toast.LENGTH_LONG ou Toast.LENGTH_SHORT
  • Por último se chama ao método show() do obxecto creado para amosar a mensaxe.


Nota: Nos exemplos seguintes vaise facer uso da interface que xestionar os eventos de click sobre os botóns, pero os conceptos e como facelo se pode aplicar a calquera tipo de evento.



Xestión Eventos: 1ª Opción-Clases anónimas

  • Dentro do paquete Eventos crear unha nova 'Empty Activity' de nome: UD02_01_Eventos 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.


  • Para xestionar calquera dos eventos temos que asociar dito evento ao view, por medio do rexistro dunha das intercaces anteriores, onde estará definido o método ao que o S.O. chamará cando se produza o evento.
Para iso podemos facer uso das Clases anónimas.
A forma de implementar anonimante unha interface é: obxectoView.setXXXXXXListener(new XXXXXXXListener(){ ....................});
  • Como vemos teremos:
  • Ter unha referencia ao view sobre o que queremos xestionar o evento.
  • Chamar ao método setXXXXInterface, por exemplo, setOnCLickListener sería o evento para xestionar o evento de click sobre un botón.
  • Dito método espera como parámetro un obxecto dunha clase que implemente a interface. No noso caso faremos uso das clases anónimas e faremos un new XXXXXXXListener, é dicir, da interface. No caso anterior do botón, a interface se chama OnClickListener (mirar imaxe anterior).
  • Ao facer o new, automaticamente o AndroidStudio implementa os métodos da Interface. No caso do exemplo, o método onClick.


Vexamos un exemplo.
  • Imos facer unha activity cun botón e imos xestionar o seu evento de 'click' amosando unha mensaxe (notificación) de tipo Toast.
PDM eventos 9.jpg


Código XML do layout da activity:
 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=".Eventos.UD02_01_Eventos">
 8 
 9     <Button
10         android:id="@+id/btnAceptar_UD02_01"
11         android:layout_width="wrap_content"
12         android:layout_height="wrap_content"
13         android:layout_marginBottom="8dp"
14         android:layout_marginEnd="8dp"
15         android:layout_marginStart="8dp"
16         android:layout_marginTop="8dp"
17         android:text="Button"
18         app:layout_constraintBottom_toBottomOf="parent"
19         app:layout_constraintEnd_toEndOf="parent"
20         app:layout_constraintStart_toStartOf="parent"
21         app:layout_constraintTop_toTopOf="parent" />
22 </android.support.constraint.ConstraintLayout>
Temos un botón de nome btnAceptar_UD02_01.
Nota: Na vosa práctica os controis terán un esquema de nomeamento parecido a este.
  • Agora no código da Activity faremos os pasos indicados para xestionar o evento Click():


Sempre despois da chamada a setContentView do método onCreate (que é onde asociamos o layout á activity):
 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Eventos;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.widget.Button;
 6 
 7 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 8 
 9 public class UD02_01_Eventos extends Activity {
10 
11     @Override
12     protected void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14         setContentView(R.layout.activity_ud02_01__eventos);
15 
16         // Obtemos a referencia ao botón por medio do método findViewById
17         Button btnAceptar = findViewById(R.id.btnAceptar_UD02_01);
18         
19 
20     }
21 }
Facemos uso do método findViewById para obter unha referencia ao botón.
Como parámetro leva un número. Este o obtemos da clase R (comentada en anteriores puntos) a cal cada vez que compilamos a aplicación, asocia cada recurso do cartafol /res cun número.
Por iso é importante que o nome do control gráfico (o botón neste caso) sexa identificativo, xa que podemos facer referencia a controis de outras activities e polo tanto teríamos un valor null para o control.


Nota: Ao facer 'enter' no Android Studio cando sea o nome da interface, xa xera automaticamente os métodos da mesma.
 1 public class UD02_01_Eventos extends Activity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_ud02_01__eventos);
 7 
 8         // Obtemos a referencia ao botón por medio do método findViewById
 9         Button btnAceptar = findViewById(R.id.btnAceptar_UD02_01);
10         btnAceptar.setOnClickListener(new View.OnClickListener() {
11             @Override
12             public void onClick(View v) {
13                 
14             }
15         });
16 
17     }
18 }


  • Agora dentro do método onClick poderemos poñer o código que queiramos.
Comentar que dito método leva como parámetro un obxecto da clase View que é o obxecto que ten rexistrado o evento e sobre o cal se fixo o evento (neste caso o botón).
Podemos facer un cast de dito obxecto para acceder a todas as propiedades e métodos do botón, aínda que no caso das interfaces anónimas non ten moito sentido xa que, como no exemplo, podemos acceder a btnAceptar que é o botón.
1         btnAceptar.setOnClickListener(new View.OnClickListener() {
2             @Override
3             public void onClick(View v) {
4 
5                 Button btn = (Button)v;    // Sería o mesmo que btnAceptar
6                 Toast.makeText(getApplicationContext(),"Botón pulsado: "+ btn.getText(),Toast.LENGTH_LONG).show();
7             }
8         });


  • Aviso: Se elixides esta forma de xestionar os eventos, deberedes de facelo nun método aparte onde estean as chamadas a setOnClickListener, e chamalo dende o método onCreate.




Xestión Eventos: 2ª Opción-Implementado a interface

  • A segunda opción sería a de crear unha clase que implemente dita interface (no exemplo, ActionListener) e pasarlle un obxecto de dita clase ao método setOnClickListener.
De forma máis rápida podemos implementar dita interface na propia activity.


Vexamos un exemplo.
  • Dentro do paquete Eventos crear unha nova 'Empty Activity' de nome: UD02_02_Eventos 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.


  • Imos facer unha activity cun botón e imos xestionar o seu evento de 'click' amosando unha mensaxe (notificación) de tipo Toast, como fixemos antes, pero implementando o código doutra forma.
PDM eventos 9.jpg


Código XML do layout da activity:
 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=".Eventos.UD02_01_Eventos">
 8 
 9     <Button
10         android:id="@+id/btnAceptar_UD02_02"
11         android:layout_width="wrap_content"
12         android:layout_height="wrap_content"
13         android:layout_marginBottom="8dp"
14         android:layout_marginEnd="8dp"
15         android:layout_marginStart="8dp"
16         android:layout_marginTop="8dp"
17         android:text="Button"
18         app:layout_constraintBottom_toBottomOf="parent"
19         app:layout_constraintEnd_toEndOf="parent"
20         app:layout_constraintStart_toStartOf="parent"
21         app:layout_constraintTop_toTopOf="parent" />
22 </android.support.constraint.ConstraintLayout>


  • Agora no código da clase implementamos a interface (coidado coa Interface ClickListener.
Ao empezar a escribir o noma da interface o asistente amosará diversas opcións.
PDM eventos 5.jpg

Debemos escoller a que deriva da clase View

 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Eventos;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.view.View;
 6 
 7 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 8 
 9 public class UD02_02_Eventos extends Activity implements View.OnClickListener {
10 
11     @Override
12     protected void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14         setContentView(R.layout.activity_ud02_02__eventos);
15     }
16 }
Vos dará un erro:


  • O código da clase queda como segue:
 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Eventos;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.view.View;
 6 import android.widget.Button;
 7 import android.widget.Toast;
 8 
 9 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
10 
11 
12 public class UD02_02_Eventos extends Activity implements View.OnClickListener {
13 
14     @Override
15     protected void onCreate(Bundle savedInstanceState) {
16         super.onCreate(savedInstanceState);
17         setContentView(R.layout.activity_ud02_02__eventos);
18     }
19 
20     @Override
21     public void onClick(View v) {
22 
23         Toast.makeText(getApplicationContext(),"Botón pulsado: "+ ((Button)v).getText(),Toast.LENGTH_LONG).show();
24 
25     }
26 }
Fixarse como agora estou a facer un cast sobre o obxecto v sen necesidade de ter unha variable intermedia como fixemos antes.


  • Agora queda rexistrar esta clase como a que vai xestionar os eventos do botón:
1     @Override
2     protected void onCreate(Bundle savedInstanceState) {
3         super.onCreate(savedInstanceState);
4         setContentView(R.layout.activity_ud02_02__eventos);
5 
6 
7         Button btnAceptar = findViewById(R.id.btnAceptar_UD02_02);  // Lembrar poñer o botón 2. Se poñedes o 1 btnAceptar vale null
8         btnAceptar.setOnClickListener(this);
9     }




Múltiples views cara o mesmo evento

  • Na opción anterior, podemos ter varios views asociados ao mesmo método.
Dentro de dito método teremos que ter algunha forma de diferenciar uns botóns de outros.
Podemos empregar o id botón.
Vexamos un exemplo.
  • Dentro do paquete Eventos crear unha nova 'Empty Activity' de nome: UD02_03_Eventos 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 obxectivo desta práctica é a de poñer tres botóns e unha caixa de texto.
O texto da caixa de texto cambiará en función do botón premido.


PDM eventos 10.jpg


Código XML do layout da activity:
 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=".Eventos.UD02_03_Eventos">
 8 
 9     <Button
10         android:id="@+id/btnAceptar1_UD02_03"
11         android:layout_width="126dp"
12         android:layout_height="wrap_content"
13         android:layout_marginBottom="8dp"
14         android:layout_marginStart="8dp"
15         android:layout_marginTop="8dp"
16         android:text="Button1"
17         app:layout_constraintBottom_toBottomOf="parent"
18         app:layout_constraintStart_toStartOf="parent"
19         app:layout_constraintTop_toTopOf="parent"
20         app:layout_constraintVertical_bias="0.18" />
21 
22     <Button
23         android:id="@+id/btnAceptar2_UD02_03"
24         android:layout_width="126dp"
25         android:layout_height="wrap_content"
26         android:layout_marginEnd="8dp"
27         android:layout_marginStart="8dp"
28         android:text="Button2"
29         app:layout_constraintEnd_toStartOf="@+id/btnAceptar3_UD02_03"
30         app:layout_constraintStart_toEndOf="@+id/btnAceptar1_UD02_03"
31         app:layout_constraintTop_toTopOf="@+id/btnAceptar1_UD02_03" />
32 
33     <Button
34         android:id="@+id/btnAceptar3_UD02_03"
35         android:layout_width="127dp"
36         android:layout_height="wrap_content"
37         android:layout_marginEnd="8dp"
38         android:text="Button3"
39         app:layout_constraintEnd_toEndOf="parent"
40         app:layout_constraintTop_toTopOf="@+id/btnAceptar2_UD02_03" />
41 
42     <TextView
43         android:id="@+id/txtMensaxe_UD02_03"
44         android:layout_width="wrap_content"
45         android:layout_height="wrap_content"
46         android:layout_marginBottom="8dp"
47         android:layout_marginEnd="8dp"
48         android:layout_marginStart="8dp"
49         android:layout_marginTop="8dp"
50         android:text="Mensaxe de texto"
51         android:textSize="18sp"
52         android:textStyle="bold"
53         app:layout_constraintBottom_toTopOf="@+id/btnAceptar2_UD02_03"
54         app:layout_constraintEnd_toEndOf="parent"
55         app:layout_constraintStart_toStartOf="parent"
56         app:layout_constraintTop_toTopOf="parent" />
57 </android.support.constraint.ConstraintLayout>


  • Código da activity:
 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Eventos;
 2 
 3 import android.app.Activity;
 4 import android.graphics.Color;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 import android.widget.TextView;
 8 
 9 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
10 
11 public class UD02_03_Eventos extends Activity implements View.OnClickListener {
12 
13     /**
14      * Asociamos os eventos de click dos botóns á activity
15      */
16     private void xestionarEventos(){
17         findViewById(R.id.btnAceptar1_UD02_03).setOnClickListener(this);
18         findViewById(R.id.btnAceptar2_UD02_03).setOnClickListener(this);
19         findViewById(R.id.btnAceptar3_UD02_03).setOnClickListener(this);
20     }
21 
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.activity_ud02_03__eventos);
26 
27         // Non o facemos directamente sobre o onCreate
28         xestionarEventos();
29     }
30 
31     @Override
32     public void onClick(View v) {
33 
34         // Como en todos eles imos modificar a caixa de texto, obtemos a referencia aquí.
35         TextView caixaTexto = findViewById(R.id.txtMensaxe_UD02_03);
36         switch (v.getId()){
37 
38             case R.id.btnAceptar1_UD02_03:
39                 caixaTexto.setText(("Ben feito. Pulsaches o botón 1"));
40                 caixaTexto.setTextColor(Color.BLUE);
41                 break;
42 
43             case R.id.btnAceptar2_UD02_03:
44                 caixaTexto.setText(("Non está mal. Pulsaches o botón 2"));
45                 caixaTexto.setTextColor(Color.YELLOW);
46                 break;
47             case R.id.btnAceptar3_UD02_03:
48                 caixaTexto.setText(("Fatal. Pulsaches o botón 3"));
49                 caixaTexto.setTextColor(Color.GRAY);
50                 break;
51         }
52 
53     }
54 }
  • Liña 28: Para non ter todo o código no onCreate, o poñemos nun método separado.
  • Liñas 16-20: Método private e documentado (tedes que documentar todos os métodos creados por vos) on se indica por cada botón que clase vai xestionar o evento de click.
  • Liñas 31-51: Xestión dos eventos. Ao método van chegar 3 views diferentes ao parámetro v (cada un dos botóns). Como vemos a nivel de programación podemos referenciar calquera view e cambiar as súas propiedades.




Xestión Eventos: 3ª Opción-Dende o layout

  • É a forma máis sinxela de desencadear unha acción.
Non é moi aconsellable xa que estamos mesturando a vista (é dicir, o deseño do layout) coa forma de controlar os eventos.
  • Consiste en poñer como propiedade do view no layout o seguinte:android:onClick="nome_método"
No nome do método é o nome que terá que definirse no código do activity.
Soamente hai que poñer o nome, sen parámetros de ningún tipo.
  • No código da activity hai que definir un método:
  • Con modificador de acceso 'public'
  • Que non devolva nada: 'void'
  • Có mesmo nome que está empregado no layout.
  • Cun parámetro de tipo view, que será o view que provocou o evento
1 public void nomeMétodo(View v){
2 
3 }


Vexamos un exemplo.
  • Dentro do paquete Eventos crear unha nova 'Empty Activity' de nome: UD02_04_Eventos 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.



  • Código 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=".Eventos.UD02_04_Eventos">
 8 
 9     <Button
10         android:id="@+id/btnAcep1_UD02_04_Event"
11         android:layout_width="wrap_content"
12         android:layout_height="wrap_content"
13         android:layout_marginStart="8dp"
14         android:layout_marginTop="8dp"
15         android:text="Aceptar 1"
16         android:onClick="pulsarBoton"
17         app:layout_constraintStart_toStartOf="parent"
18         app:layout_constraintTop_toTopOf="parent" />
19 
20     <Button
21         android:id="@+id/btnAcep2_UD02_04_Event"
22         android:layout_width="wrap_content"
23         android:layout_height="wrap_content"
24         android:layout_marginEnd="8dp"
25         android:layout_marginTop="8dp"
26         android:text="Aceptar 2"
27         android:onClick="pulsarBoton"
28         app:layout_constraintEnd_toEndOf="parent"
29         app:layout_constraintTop_toTopOf="parent" />
30 
31     <TextView
32         android:id="@+id/txtResultado_UD02_04_Event"
33         android:layout_width="wrap_content"
34         android:layout_height="wrap_content"
35         android:layout_marginBottom="8dp"
36         android:layout_marginEnd="8dp"
37         android:layout_marginStart="8dp"
38         android:layout_marginTop="8dp"
39         android:text="Este é un texto de proba"
40         android:textSize="36sp"
41         app:layout_constraintBottom_toBottomOf="parent"
42         app:layout_constraintEnd_toEndOf="parent"
43         app:layout_constraintStart_toStartOf="parent"
44         app:layout_constraintTop_toTopOf="parent" />
45 </android.support.constraint.ConstraintLayout>



  • O código da activity:
 1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Eventos;
 2 
 3 import android.app.Activity;
 4 import android.graphics.Color;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 import android.widget.TextView;
 8 
 9 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
10 
11 public class UD02_04_Eventos extends Activity {
12 
13     public void pulsarBoton(View v){
14         final TextView texto = findViewById(R.id.txtResultado_UD02_04_Event);
15         switch (v.getId()){
16             case R.id.btnAcep1_UD02_04_Event:
17                 texto.setTextColor(Color.YELLOW);
18                 break;
19             case R.id.btnAcep2_UD02_04_Event:
20                 texto.setTextColor(Color.BLUE);
21         }
22     }
23 
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_ud02_04__eventos);
28     }
29 }



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