Xestion de eventos III: Listeners e clases anónimas

De MediaWiki
Revisión del 11:34 17 dic 2016 de Wiki (discusión | contribuciones) (Página creada con «==Introdución== *En Android hai moitas formas de interceptar eventos do usuario. *A clase View proporciona varias formas de xestionar eventos. *Por exemplo, cando un usuar...»)
(dif) ← Revisión anterior | Revisión actual (dif) | Revisión siguiente → (dif)
Ir a la navegación Ir a la búsqueda

Introdución

  • En Android hai moitas formas de interceptar eventos do usuario.
  • A clase View proporciona varias formas de xestionar eventos.
  • Por exemplo, cando un usuario toca un botón é chamado o método callback onTouchEvent() dese obxecto.
  • Pero para interceptar ese evento debemos estender a clase e implementar o método.
  • Pero non sería práctico para poder manexar o evento crear unha (sub)clase para cada obxecto Vista.
  • Por iso a Clase Vista (View) contén unha colección de interfaces anidadas.
  • Estas interfaces chámanse Event Listeners (Escoitadores de eventos) e están listas para capturar a iteración do usuario coa UI.
  • A continuación imos ver algunhas formas de capturar eventos:


Caso práctico

  • Comezamos creando o proxecto: U3_02_Eventos
  • Comezaremos capturado o evento Click e logo ao final veremos outros eventos.
  • A aplicación coa que se traballará é a seguinte:

Android 2013 U3 02 Eventos 01.jpg


XML do Layout

  • A liña 11 marca unha das formas máis sinxelas de capturar o evento Click sobre un compoñente.
 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     <Button
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:text="Botón1: onClick Layout"
11         android:onClick="onBotonClick"
12          />
13     
14     <Button 
15         android:id="@+id/boton2"
16         android:layout_width="match_parent"
17         android:layout_height="wrap_content"
18         android:text="Botón2: Listener"
19         />
20 	
21 	<Button 
22         android:id="@+id/boton3"
23         android:layout_width="match_parent"
24         android:layout_height="wrap_content"
25         android:text="Botón3: Clase"
26         />
27 	
28     <Button 
29         android:id="@+id/boton4"
30         android:layout_width="match_parent"
31         android:layout_height="wrap_content"
32         android:text="Botón4: Tamén de clase"
33         />
34 
35     <Button 
36         android:id="@+id/boton5"
37         android:layout_width="match_parent"
38         android:layout_height="wrap_content"
39         android:text="Botón5: Obxecto"
40         />
41     
42     <Button 
43         android:id="@+id/boton6"
44         android:layout_width="match_parent"
45         android:layout_height="wrap_content"
46         android:text="Botón6: Outro Obxecto"
47         />
48 </LinearLayout>


O Código Java

  • A continuación preséntase o código Java, pero este vai ser debullado nos seguintes apartados.


 1 package com.example.u3_02_eventos;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.view.Menu;
 6 import android.view.View;
 7 import android.view.View.OnClickListener;
 8 import android.widget.Button;
 9 import android.widget.Toast;
10 
11 public class U3_02_Eventos extends Activity {
12 
13 	@Override
14 	protected void onCreate(Bundle savedInstanceState) {
15 		super.onCreate(savedInstanceState);
16 		setContentView(R.layout.activity_u3_02__eventos);
17 
18 		Button boton2 = (Button) findViewById(R.id.boton2);
19 		boton2.setOnClickListener(new OnClickListener() {
20 
21 			@Override
22 			public void onClick(View v) {
23 				Toast.makeText(getApplicationContext(), "Premeches o Botón2", Toast.LENGTH_SHORT).show();
24 			}
25 		});
26 
27 		Button boton3 = (Button) findViewById(R.id.boton3);
28 		boton3.setOnClickListener(new XestionEventos());
29 
30 		Button boton4 = (Button) findViewById(R.id.boton4);
31 		boton4.setOnClickListener(new XestionEventos());
32 
33 		Button boton5 = (Button) findViewById(R.id.boton5);
34 		boton5.setOnClickListener(_OnClickListener);
35 
36 		Button boton6 = (Button) findViewById(R.id.boton6);
37 		boton6.setOnClickListener(_OnClickListener);
38 
39 	}
40 
41 	private OnClickListener _OnClickListener = new OnClickListener() {
42 
43 		@Override
44 		public void onClick(View v) {
45 			Button btn = (Button) v;
46 			Toast.makeText(v.getContext(), "Premeches" + btn.getText(), Toast.LENGTH_SHORT).show();
47 		}
48 	};
49 
50 	public void onBotonClick(View v) {
51 		Toast.makeText(this, "Premeches o Botón1", Toast.LENGTH_SHORT).show();
52 	}
53 
54 	@Override
55 	public boolean onCreateOptionsMenu(Menu menu) {
56 		// Inflate the menu; this adds items to the action bar if it is present.
57 		getMenuInflater().inflate(R.menu.u3_02__eventos, menu);
58 		return true;
59 	}
60 
61 }

Propiedade android:onClick

  • Como xa se viu é unha propiedade XML que teñen varios compoñentes (vistas).
  • Hai que definir un método:
    • Que sexa public
    • Que non devolva nada: void
    • Que teña un parámetro da clase View, que será quen provoque o evento.
  • No exemplo anterior son as liñas 50-52:
1 	public void onBotonClick(View v) {
2 		Toast.makeText(this, "Premeches o Botón1", Toast.LENGTH_SHORT).show();
3 	}

Listener

  • Un Event Listener é unha interface da clase Vista (View) que contén un único método de tipo callback que hai que implementar
  • Android invoca estes métodos cando a Vista detecta que o usuario está provocando un tipo concreto de interacción con ese elemento da interface de usuario.

Existen os seguintes métodos callback:

    • onClick(): de View.OnClickListener. Este método invócase cando o usuario toca un elemento cun dedo (modo contacto), fai click coa bola de navegación (TrackBall) do dispositivo ou preme a tecla "Enter" estando nun compoñente.
    • onLongClick(): de View.OnLongClickListener. Este método chámase cando o usuario toca e mantén o dedo sobre un elemento (modo de contacto), fai click sen soltar coa bola de navegación (TrackBall) ou preme a tecla "Enter" perante un segundo estando nun elemento.
    • onFocusChange(): de View.OnFocusChangeListener. Invócase cando o usuario move o cursor cara unha Vista ou se alonxa desta utilizando a bola de navegación ou usando as teclas de navegación.

onKey(): de View.OnKeyListener. Chámase cando o usuario se centra nun elemento e preme ou libera una tecla do dispositivo.

    • ...
  • onLongClick() verase nun exemplo posterior.


  • Estes métodos son os únicos que se van implementar nas súas respectivas interfaces.
  • Estas interfaces teñen o formato: on...Listener()
  • Unha vez que temos implementada a interface témoslla que pasar como parámetro á vista (view) correspondente a través de vista.set...Listener().
  • Lembrar que en java os interfaces son clases abstractas que so definen os atributos e métodos (cos parámetros) que vai ter esa clase pero non os implementa. Por tanto sempre que se implemente unha interface hai que implementar os métodos que define.
  • Neste caso a interface View.OnClickListener está definida como segue: http://developer.android.com/reference/android/view/View.OnClickListener.html
1 public static interface View.OnClickListener {
2 public abstract void onClick (View v);
3 }
  • Neste exemplo, cando implementemos a interface View.OnClickListener debemos implementar o método onClick.
  • A continuación, a modo de exemplo, imos ver 3 formas de implementar esta interface. O que se faga con esta pódese facer dun xeito semellante con calquera outra.

Implementar a interface a través dunha clase

  • Este é o método máis sinxelo, para entender. Pero obríganos a crear unha nova clase.
  • Creamos unha nova clase que implemente o interface OnClickListener.


Android 2013 U3 02 Eventos 02.jpg

  • Código Java da clase: XestionEventos
 1 package com.example.u3_02_eventos;
 2 
 3 import android.view.View;
 4 import android.view.View.OnClickListener;
 5 import android.widget.Button;
 6 import android.widget.Toast;
 7 
 8 public class XestionEventos implements OnClickListener {
 9 
10 	@Override
11 	public void onClick(View v) {
12 		// TODO Auto-generated method stub
13 		
14 		Button btn = (Button) v;
15 		Toast.makeText(v.getContext(), "Premeches "+btn.getText(), Toast.LENGTH_SHORT).show();
16 	}
17 }


  • Observar nas Liñas 28 e 31 (do código principal) como se crea unha nova clase XestionEventos para cada botón.
  • Esa clase é a que vai implementar o método onClick(), como se ve enriba.
1 		Button boton3 = (Button) findViewById(R.id.boton3);
2 		boton3.setOnClickListener(new XestionEventos());
3 
4 		Button boton4 = (Button) findViewById(R.id.boton4);
5 		boton4.setOnClickListener(new XestionEventos());
  • Pero esta forma é un engorro, pois hai que estar creando clases.

Crear un obxecto que implemente a interface

  • Imos crear un obxecto que implemente a interface e que poida ser pasado como parámetro as vistas que desexemos cada vez que se fai click nelas.
  • _OnClickLister é un obxecto de tipo OnClickListener. Liñas 41-48 de arriba.
1 private OnClickListener _OnClickListener = new OnClickListener() {
2 
3 		@Override
4 		public void onClick(View v) {
5 			Button btn = (Button) v;
6 			Toast.makeText(v.getContext(), "Premeches" + btn.getText(), Toast.LENGTH_SHORT).show();
7 		}
8 	};


  • Pasamos ese obxecto ás vistas que desexemos cando se faga Click nelas.
1 		Button boton5 = (Button) findViewById(R.id.boton5);
2 		boton5.setOnClickListener(_OnClickListener);
3 
4 		Button boton6 = (Button) findViewById(R.id.boton6);
5 		boton6.setOnClickListener(_OnClickListener);

A través dunha clase anónima

  • Exemplo: Liñas 18-25 do código
  • Se no canto de crear un obxecto que implemente a interface e logo pasarlle ese obxecto como parámetro ao escoitador asociado ao botón podemos pasarlle como parámetro ao escoitador o código que implementa o obxecto.
  • Deste xeito, non se crea nin unha clase nin un obxecto de modo explícito ao que se lle asocia un nome. Senón que se crea un obxecto de tipo OnClickListener ao que non se lle asocia ningún nome, de aí de anónimo.
1                 Button boton2 = (Button) findViewById(R.id.boton2);
2 		boton2.setOnClickListener(new OnClickListener() {
3 
4 			@Override
5 			public void onClick(View v) {
6 				Toast.makeText(getApplicationContext(), "Premeches o Botón2", Toast.LENGTH_SHORT).show();
7 			}
8 		});






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