Android Touch En este tutorial aprenderemos a utilizar la pantalla

Transcripción

Android Touch En este tutorial aprenderemos a utilizar la pantalla
Android Touch En este tutorial aprenderemos a utilizar la pantalla táctil de los dispositivos para sacar ventaja de ello en nuestras aplicaciones. Para este tutorial tomaremos como base el tutorial anterior, puedes crear un proyecto nuevo o seguir trabajando sobre el proyecto creado en el tutorial anterior. Si vas a crear un proyecto nuevo crea uno para la plataforma 2.2 y nombra a la Actividad principal TutorialElefanteTouch. La aplicación que desarrollaremos mostrará en pantalla el mismo elefante de la aplicación anterior solo que en esta ocasión podremos modificar su dirección de desplazamiento al tocar la pantalla del dispositivo. La mayoría del código se queda tal cual como en el tutorial anterior por lo cual aquí nos enfocaremos únicamente en las modificaciones que se tienen que hacer. Empecemos por la clase Elefante, dado a que ahora el elefante podrá desplazarse tanto en el eje x como en el eje y necesitamos añadir dos nuevas contantes en la definición de la clase para indicar la dirección del movimiento del elefante. public class Elefante { public static final int LEFT = 1; //Dirección del Elefante, Izquierda public static final int RIGHT = 2; //Dirección del Elefante, Derecha public static final int UP = 3; //Dirección del Elefante, Arriba public static final int DOWN = 4; //Dirección del Elefante, Abajo En esta misma clase modificamos también el método avanza() de tal manera que ahora el elefante pueda desplazarse también en el eje y. public void avanza() { //Avanza a la derecha if (dir == RIGHT) x += 5; //Avanza a la izquierda if (dir == LEFT) x -­‐= 5; //Avanza arriba if (dir == UP) y -­‐= 5; //Avanza abajo if (dir == DOWN) y += 5; } Tanto la clase Animacion como el manifiesto de la aplicación permanecen sin cambio alguno por lo cual continuaremos ahora con los cambios a realizar en la Actividad. Empezamos por importar las clases necesarias para la Actividad donde ahora necesitaremos importar también las clases View y OnTouchListener. En la definición de la clase implementaremos la interfase OnTouchListener y definiremos dos nuevos miembros que nos ayudarán a mapear los toques que se hagan en la pantalla táctil. import android.app.Activity; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Rect; import android.media.AudioManager; import android.media.SoundPool; import android.os.Bundle; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnTouchListener; import android.view.Window; import android.view.WindowManager; import java.io.IOException; import java.io.InputStream; public class TutorialElefanteTouch extends Activity implements OnTouchListener { //Vista de la Actividad ElefanteFastRenderView renderView; //Candado para evitar que el dispositivo duerma WakeLock wakeLock; //Objeto Elefante Elefante elefante; //Objeto Animacion Animacion elefanteAnim; //Colección de sonidos SoundPool pool; //Identificador de sonido int soundId = -­‐1; //Posiciones 'x' y 'y' int x, y; //Objetos Bitmap para el manejo de imágenes Bitmap cuadro, frameBuffer; //Escala en 'x' y 'y' float scaleX, scaleY; Dado a que nosotros primero dibujamos nuestra animación en un buffer virtual y posteriormente lo proyectamos a la vista que se mostrará en la pantalla necesitamos mapear los toques que se hacen en la pantalla táctil. El buffer virtual en el que dibujamos es por defecto de 320 x 480 pixeles, sin embargo el tamaño de la pantalla en la cual se proyectará la imagen no será precisamente de estas mismas medidas por lo cuál al proyectar el buffer en la pantalla es necesario escalar el buffer para que se muestre en pantalla conservando su proporción original y de esta manera garantizar que la imagen se vea siempre igual en proporción en cualquier dispositivo en el cual se corra la aplicación. Dado a que el buffer será escalado es importante para nosotros conocer esa escala que se hará en cada uno de los ejes de tal manera que podamos escalar el toque que se haga en la pantalla para que las coordenadas del toque coincidan con las coordenadas del buffer virtual donde se encuentra el elefante. Los miembros scaleX y scaleY nos ayudarán a calcular la escala que se aplique a cada uno de los ejes. En el método onCreate() de la Actividad, justo después de crear nuestro buffer virtual calculamos la escala en cada uno de los ejes y los guardamos en los miembros scaleX y sacleY. //Determina la orientación del dispositivo y crea un buffer en base //a esta boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; //Ancho del buffer int frameBufferWidth = isLandscape ? 480 : 320; //Alto del buffer int frameBufferHeight = isLandscape ? 320 : 480; //Crea el buffer frameBuffer = Bitmap.createBitmap(frameBufferWidth, frameBufferHeight, Config.RGB_565); //Escala en x basada en el ancho del buffer y el ancho de la //pantalla del dispositivo scaleX = (float) frameBufferWidth / getWindowManager().getDefaultDisplay().getWidth(); //Escala en y basada en el alto del buffre y el alto de la pantalla del //dispositivo scaleY = (float) frameBufferHeight / getWindowManager().getDefaultDisplay().getHeight(); Dentro del mismo método utilizamos el método setOnTouchListener() para indicar que la Actividad se encargará de manejar los eventos de toque. Esto lo añadimos justo después de que creamos nuestra vista. //Crea y establece la vista de la Actividad y establece un //OnTouchListener para esta renderView = new ElefanteFastRenderView(this); renderView.setOnTouchListener(this); setContentView(renderView); Sobreescribimos ahora el método onTouch() requerido por la interfase OnTouchListener para manejar los eventos de toque en la Actividad. En este cambiaremos la dirección de movimiento del objeto Elefante dependiendo de la posición donde el usuario toque la pantalla. Al obtener las coordenadas del toque las multiplicamos por los valores de la escala para ajustarlos al tamaño del buffer virtual. /** * Método onTouch sobrescrito de la interface OnTouchListener * Maneja los eventos de contacto en la Actividad * @param v es la vista que contiene el OnTouchListener * @param event son los eventos de contacto atrapados por el *OnTouchListener * @return regresa verdadero cuando es llamado */ @Override public boolean onTouch(View v, MotionEvent event){ //Maneja los eventos de contacto switch (event.getAction()) { //Cuando se hace contacto con el dedo case MotionEvent.ACTION_DOWN: // break; //Cuando se mueve el dedo haciendo contacto case MotionEvent.ACTION_MOVE: // break; case MotionEvent.ACTION_CANCEL: // break; //Cuando se deja de hacer contacto case MotionEvent.ACTION_UP: //Cambia la dirección de movimiento del //objeto Elefante dependiendo del punto de //contacto if ((event.getX() * scaleX) < elefante.x) elefante.dir = Elefante.LEFT; else if ((event.getX() * scaleX) > elefante.x + elefante.animacion.getCuadro().getWidth()) elefante.dir = Elefante.RIGHT; else if ((event.getY() * scaleY) < elefante.y) elefante.dir = Elefante.UP; } else if ((event.getY() * scaleY) > elefante.y + elefante.animacion.getCuadro().getHeight()) elefante.dir = Elefante.DOWN; break; } return true; Finalmente en el método actualizaElefante() nos aseguramos de checar que el elefante no salga por ninguna de las orillas de la pantalla. /** * Método actualizaElefante * Llamado para actualizar el objeto Elefante * @param tiempo es el tiempo transcurrido desde la última * vez que se actualizó */ private void actualizaElefante(float tiempo) { //Guarda el tiempo transcurrido tiempoTick += tiempo; //Actualiza mientras el tiempo transcurrido sea mayor al //tiempo de actualización while(tiempoTick > tick) { tiempoTick -­‐= tick; //Actualiza la posición del objeto Elefante elefante.avanza(); //Checa colisión con las orillas de la pantalla if(elefante.x + elefante.animacion.getCuadro().getWidth() > frameBuffer.getWidth() || elefante.x < 0){ //Cambia la dirección en base a la dirección //actual if (elefante.dir == Elefante.RIGHT) elefante.dir = Elefante.LEFT; else elefante.dir = Elefante.RIGHT; //Actualiza la posición del objeto Elefante elefante.avanza(); //Si el sonido ya estaba en reproducción lo //detiene pool.stop(soundId); //Reproduce el efecto de sonido pool.play(soundId, 1, 1, 0, 0, 1); } if(elefante.y + elefante.animacion.getCuadro().getHeight() > frameBuffer.getHeight() || elefante.y < 0){ //Cambia la dirección en base a la dirección } } //actual if (elefante.dir == Elefante.UP) elefante.dir = Elefante.DOWN; else elefante.dir = Elefante.UP; //Actualiza la posición del objeto Elefante elefante.avanza(); //Si el sonido ya estaba en //reproducción lo detiene pool.stop(soundId); //Reproduce el efecto de sonido pool.play(soundId, 1, 1, 0, 0, 1); } 

Documentos relacionados