Android

Android


9.GRÁFICOS INTERACTIVOS

Página 11 de 25

9.   GRÁFICOS INTERACTIVOS

La pantalla táctil es una parte esencial de los dispositivos móviles, que generalmente no tienen teclado. Android "escucha" o "siente" los eventos que ocurren cuando tocamos la pantalla o cuando arrastramos los dedos por ella. Ya hemos visto ejemplos de ello al definir el método onClick() para los botones. En este capítulo introduciremos el método onTouchEvent() de la clase View. Este método nos permite ir más allá de los botones e interaccionar directamente con los gráficos, mover objetos e incluso dibujar nosotros mismos en la pantalla.

9.1.   Evento ACTION_DOWN

La siguiente actividad ilustra el uso del método onTouchEvent(Event). Este método se ejecuta cada vez que tocamos la pantalla. Su argumento es un Evento, un objeto que "la pantalla le pasa" a nuestra actividad con la información de las coordenadas donde ha tenido lugar el evento. Los valores de las coordenadas se obtienen ejecutando los métodos getX() y getY() del objeto Event. En este ejemplo definimos un objeto View, dibujamos un círculo rojo en el punto donde la pantalla ha sido tocada y escribimos en la pantalla los valores de las coordenadas de ese punto. La pantalla debe volver a dibujarse cada vez que hay un evento. Para ello ejecutamos el método invalidate(). Una captura de pantalla se muestra en la figura 9.1.

  public class ActionDownActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        SpecialView myView=new SpecialView(this);

        setContentView(myView);

    }

    class SpecialView extends View{

     float x=50;

     float y=50;

     public SpecialView(Context context){

        super(context);

     }

     @Override

     protected void onDraw(Canvas canvas){

        canvas.drawColor(Color.LTGRAY);

        Paint paint=new Paint();

        paint.setAntiAlias(true);

        paint.setColor(Color.RED);

        canvas.drawCircle(x,y,20, paint);

        paint.setColor(Color.BLACK);

        paint.setTextSize(35);

        canvas.drawText("x= "+x, 100, 50, paint);

        canvas.drawText("y= "+y, 100, 90, paint);

     }

     @Override

     public boolean onTouchEvent(MotionEvent evento) {

        if(evento.getAction()==MotionEvent.ACTION_DOWN){

            x=evento.getX();

            y=evento.getY();

            invalidate();

        }

        return true;

        }

     }

  }

Figura 9.1. Uso de onTouchEvent() en un evento action down.

9.2.   Evento ACTION_UP

Cuando levantamos el dedo de la pantalla, esta recoge el evento action up. Esto puede suceder en el mismo punto en el que pulsamos inicialmente o en otro distinto, si arrastramos el dedo antes de levantarlo. En el siguiente ejemplo se ilustra cómo se controlan estos eventos.  Hemos modificado la actividad anterior añadiendo el caso ACTION_UP en el método onTouchEvent(). Es ilustrativo ejecutar esta aplicación en el emulador, pulsando con el ratón en un punto de la pantalla, arrastrando el ratón con el botón pulsado y luego soltarlo. El programa mostrará las coordenadas de los puntos donde se pulsó con el ratón (o con el dedo en una pantalla táctil) y donde se dejó de pulsar.  En la figura 9.2 vemos una captura de pantalla del caso action up.

Figura 9.2. Uso de onTouchEvent() en un evento action up.

  public class ActionDownActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        SpecialView myView=new SpecialView(this);

        setContentView(myView);

    }

    class SpecialView extends View{

     float x=50;

     float y=50;

     String texto="Evento";

     public SpecialView(Context context){

        super(context);

     }

     @Override

     protected void onDraw(Canvas canvas){

        canvas.drawColor(Color.LTGRAY);

        Paint paint=new Paint();

        paint.setAntiAlias(true);

        paint.setColor(Color.RED);

        canvas.drawCircle(x,y,20, paint);

        paint.setColor(Color.BLACK);

        paint.setTextSize(35);

        canvas.drawText(texto, 100, 130, paint);

        canvas.drawText("x= "+x, 100, 50, paint);

         canvas.drawText("y= "+y, 100, 90, paint);

     }

     @Override

     public boolean onTouchEvent(MotionEvent evento) {

        if(evento.getAction()==MotionEvent.ACTION_DOWN){

            texto="Action down";

            x=evento.getX();

            y=evento.getY();

            invalidate();

        }

        if(evento.getAction()==MotionEvent.ACTION_UP){

            texto="Action up";

            x=evento.getX();

            y=evento.getY();

            invalidate();

        }

        return true;

     }

   }

  }

9.3.   Evento ACTION_MOVE

El evento ACTION_MOVE permite añadir dinámica a nuestra actividad, detectando y siguiendo el movimiento del dedo cuando se arrastra por la pantalla. Para ilustrar su uso, en la actividad del ejemplo anterior modificamos el método onTouchEvent(), quedando así:

      @Override

      public boolean onTouchEvent(MotionEvent evento) {

      x=evento.getX();

      y=evento.getY();

         if(evento.getAction()==MotionEvent.ACTION_DOWN){

             texto="Action down";

         }

         if(evento.getAction()==MotionEvent.ACTION_UP){

             texto="Action up";

         }

         if(evento.getAction()==MotionEvent.ACTION_MOVE){

             texto="Action move";

         }

         invalidate();

         return true;

      }

Al ejecutarlo en el emulador y arrastrar el ratón por la pantalla, aparecerá el mensaje "Action move" y los valores numéricos de las coordenadas irán cambiando dinámicamente, siguiendo el movimiento del dedo, así como el círculo rojo. Tendremos pues la sensación de estar arrastrando el círculo por la pantalla. (figura 9.3).

Figura 9.3. Uso de onTouchEvent() en un evento action move.

9.4.   Dibujar en la pantalla

Usando la noción de evento en combinación con drawPath() es posible escribir ya una sencilla aplicación para dibujar en la pantalla. El siguiente ejemplo permite dibujar en color azul sobre un fondo color crema. En el emulador se dibuja con el ratón. En un dispositivo se dibujaría con un dedo. Vemos una captura de pantalla en la figura 9.4.

Figura 9.4. Dibujando en la pantalla usando onTouchEvent()

en combinación con drawPatch().

  package es.ugr.amaro.dibujar;

  import android.app.Activity;

  import android.content.Context;

  import android.graphics.Canvas;

  import android.graphics.Color;

  import android.graphics.Paint;

  import android.graphics.Path;

  import android.os.Bundle;

  import android.view.MotionEvent;

  import android.view.View;

  public class DibujarActivity extends Activity {

      /** Called when the activity is first created. */

      @Override

      public void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          SpecialView myView=new SpecialView(this);

          setContentView(myView);

      }

      class SpecialView extends View{

       float x=50;

       float y=50;

       String accion="accion";

       Path path=new Path();

       public SpecialView(Context context){

          super(context);

       }

       @Override

       protected void onDraw(Canvas canvas){

          canvas.drawColor(Color.rgb(255,255,150));

          Paint paint=new Paint();

          paint.setStyle(Paint.Style.STROKE);

          paint.setStrokeWidth(6);

          paint.setColor(Color.BLUE);

          if(accion=="down"){

             path.moveTo(x, y);

          }

          if(accion=="move"){

             path.lineTo(x, y);

          }

          canvas.drawPath(path, paint);

       }

       @Override

       public boolean onTouchEvent(MotionEvent evento) {

          x=evento.getX();

          y=evento.getY();

          if(evento.getAction()==MotionEvent.ACTION_DOWN){

              accion="down";

          }

          if(evento.getAction()==MotionEvent.ACTION_MOVE){

              accion="move";

          }

          invalidate();

          return true;

        }

      }

  }

9.5.   Mover objetos

En el siguiente ejemplo usamos la misma técnica para mover dos círculos por la pantalla, uno rojo y otro azul. El círculo que se debe mover se selecciona, al pulsar la pantalla, evento action down. Se calcula la distancia al centro de cada círculo. Estamos en el interior de un círculo si esa distancia es menor que su radio.

  package es.ugr.amaro.moverobjetos;

  import android.app.Activity;

  import android.content.Context;

  import android.graphics.Canvas;

  import android.graphics.Color;

  import android.graphics.Paint;

  import android.os.Bundle;

  import android.view.MotionEvent;

  import android.view.View;

  public class MoverObjetosActivity extends Activity {

      /** Called when the activity is first created. */

      @Override

      public void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          SpecialView myView=new SpecialView(this);

          setContentView(myView);

      }

      class SpecialView extends View{

       float[] x={50,50};

       float[] y={50,150};

       float[] radio={40,60};

       Paint paint[]=new Paint[2];

       Paint p;

       int seleccion=-1;

       String texto="Mueva los circulos";

       public SpecialView(Context context){

          super(context);

          paint[0]=new Paint();

          paint[1]=new Paint();

          paint[0].setColor(Color.RED);

          paint[1].setColor(Color.BLUE);

          p=new Paint();

          p.setTextSize(30);

          p.setColor(Color.BLACK);

       }

       @Override

       protected void onDraw(Canvas canvas){

          canvas.drawColor(Color.WHITE);

          canvas.drawText(texto,200,50,p);

          for(int i=0;i<2;i++){

          canvas.drawCircle(x[i],y[i],radio[i], paint[i]);

          }

       }

        @Override

        public boolean onTouchEvent(MotionEvent evento) {

          float newX= evento.getX();

          float newY=evento.getY();

          if(evento.getAction()==MotionEvent.ACTION_DOWN){

              // indice del circulo seleccionado

              // -1 si no hay seleccion

              seleccion=-1;

              for(int i=0;i<2;i++){

                  // Calcula la distancia al centro de cada

              circulo

                  double dx=newX-x[i];

                  double dy=newY-y[i];

                  float distancia= (float)

              Math.sqrt(dx*dx+dy*dy);

                  if (distancia <= radio[i]){

              // Si estamos dentro de algun circulo lo

          seleccionamos

                    seleccion=i;

                    texto="Seleccion "+i;

                    invalidate();

                  }

              }

          }

          if(evento.getAction()==MotionEvent.ACTION_MOVE){

              if (seleccion > -1){

          // si hay un circulo seleccionado lo trasladamos

       al nuevo punto

                  x[seleccion]=newX;

                  y[seleccion]=newY;

                  invalidate();

              }

          }

          return true;

       }

     }

  }

Figura 9.5. Moviendo objetos por la pantalla con touchEvent().

Ir a la siguiente página

Report Page