Respondiendo al OnClick

Cuando tenemos un botón o una View en la que el usuario pulsa, tenemos que capturar el evento generado y reaccionar a él con nuestro código.

Por ejemplo, un botón Enviar:

Hay varias alternativas,

  1. Vinculando una función en el atributo onClick de la View en la vista de diseño (o en la vista de texto en xml)
  2. Utilizando un setOnClickListener() en el código Java.
  3. Que la clase MainActivity implemente el interfaz onClickListener()

Atributo onClick

En la paleta de atributos de la vista o botón está el atributo onClick como se muestra en la imagen.

Debemos poner el nombre de una función que tenemos que crear y que será llamada al hacer click sobre la vista.

public class MainActivity extends AppCompatActivity {

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

    }

    protected void Enviar(View view){
        Toast.makeText(this,"Hola",Toast.LENGTH_LONG).show();
    }
}

En el ejemplo se define la función Enviar (hay que poner Enviar en el atributo onClick)

Como vemos estas funciones deben recibir una View, aunque no hagamos nada con ella. Si no ponemos el parametro View fallará en tiempo de ejecución.

Esta View que recibe es la View donde se origina el evento onClick, es decir, el propio botón, por ejemplo, y podremos por tanto interactuar con ella.

En el ejemplo mostramos un Toast diciendo “Hola”. A la función Toast hay que pasarle un Context. Revisar esta entrada Contexto para ver por qué pasamos MainActivity.this y no getApplicationContext() como contexto. En esta función también podemos poner this a secas, lo que le pasa la Activity que como sabéis hereda de Context.

setOnClickListener()

Para usar esta alternativa no ponemos nada en el atributo onClick en modo de diseño. El código de ejemplo sería:  En la entrada Naming Conventions podéis ver una convención para la nomenclatura a utilizar.

public class MainActivity extends AppCompatActivity {

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

        Button  btnEnviar= (Button) findViewById(R.id.btnButton);
        btnEnviar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // código a ejecutar cuando sea pulsado
                Toast.makeText(this,"Hola",Toast.LENGTH_LONG).show();
            }
        });

    }

}

Vemos que primero creamos un objeto Button, puesto que queremos acceder al click de un botón.  Obtenemos el objeto Button con findViewById() pasándole el recurso botón.

Al recurso botón se accede mediante la clase R y de ésta queremos un id, el id del botón, que en tiempo de diseño se ha puesto btnButton, como se ve en la imagen. Por tanto usamos R.id.btnButton. Si no ponemos ID en modo diseño no podremos acceder al recurso con R.id

Una vez que tenemos instanciado el btnEnviar, llamamos a su método setOnClickListner y en el ejemplo se define objeto anónimo in-line que es el objeto OnClickListener al que se le va a pasar el evento.

Este objeto OnClickListener tendrá una función para cada evento que va a tratar, en el ejemplo tenemos el código del onClick() que como vemos recibe una View, el botón.

El código del onClick ejecuta un Toast que lleva this (la Activity) como contexto.

Implementando el Interfaz onClickListener()

Una clase que implementa la interfaz onClickListener, automáticamente recibirá los eventos onClick del interfaz de usuario, puesto que ahora es un onClickListener.

Para implementar una interfaz debemos indicarlo en la definición de la clase e implemenar los métodos que definen la interfaz. En este caso el método onClick.

El siguiente código muestra este ejemplo:

Public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    protected View btnEnviar;

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

        btnEnviar= (Button) findViewById(R.id.btnEnviar);
        btnEnviar.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        Toast.makeText(MainActivity.this,"Hola amigos", Toast.LENGTH_LONG).show();
    }
}

¿Y si tenemos más de un View en mi activity que reciba onClicks?

Pues entonces podemos jugar con la View que recibe el método onClick() que estamos implemtando y preguntando por el id de la vista podremos usar un switch para hacer una cosa u otra.

Por ejemplo, el método onClick() podría ser:

    @Override
    public void onClick(View v) {
        Button b = (Button) v;
        switch(b.getId()) {
            case R.id.btnEnviar:
                // Do something
                break;
            case R.id.btnCancelar;
                // Do something
                break;
            ...
        }
    }

Podéis ver un ejemplo en Gestionar múltiples onClicks en un sólo listener

Ejercicio

Como en el manejador (la función que recibe el evento, Enviar o el onClickListener del objeto) recibimos una Vista (el objeto donde se ha pulsado),

Podrías cambiar el texto el botón por “Enviado” tras el Toast para que el usuario vea que ya ha pulsado anteriormente?