Sunteți pe pagina 1din 11

21/12/2010 Conocimientos básicos: Mover un obje…

Gmail Calendar Docs Reader La Web Más ▼


serranopitalua.pedro@gmail.com | Mis grupos | Favorites | Profile | Help | My Account | Sign out

desarrolladores- Buscar en este grupo Buscar en Grupos


android
Grupos de Google no continuará manteniendo las funciones Páginas y Archivos. A Contenido
partir del 13 de enero, no será posible subir ningún contenido nuevo, aunque aún se
Tutoriales
podrá visualizar y descargar el contenido existente. Consulta este anuncio para
obtener más información y para conocer otras opciones de almacenamiento del
Dudas y preguntas
contenido.
Archivos
Conocimientos básicos: Mover un objeto por la pantalla
Acerca de este grupo
En este ejemplo vamos a hacer una aplicación que muestre una imagen de fondo Editar mi suscripción
a pantalla completa y mostraremos otra imagen más pequeña que podamos
mover con los cursores. La forma de realizar animaciones no es la mejor, ni la Invitar a miembros
más rápida, pero por ahora nos apañaremos. Tampoco vamos a hacer caso al
Enlaces patrocinados
ciclo de vida de una aplicación para Android, con la consiguiente perdida de la
posición del objeto en el caso de que Android decida congelar/reanudar la Felices Fiestas
ejecución de la misma. Todo esto lo veremos en otro tutorial. Sólo aviso de que Llevamos la Navidad a todo el
hay cosas que por ahora no haré símplemente por no complicar por ahora las mundo
cosas. Descubre cómo y haz tu felicitación
yasuenalanavidad.es
Lo primero que vamos a hacer es un proyecto nuevo en Eclipse.
Los pasos ya deberás sabértelos. Si no, échale un vistazo al comienzo de este Información del grupo
tutorial. Miembros: 1080
Idioma: Español
Estos son los datos del proyecto:
Categorías de grupo:
Informática > Software
Informática > Programación
Región: Europa > España
Más información sobre el grupo »

Páginas y archivos recientes


Conocimientos básicos:18
Mover
jun un objeto
Live Wallpaper - Fondo 14
animado
ene de nieve
FondoAnimado.zip 14 ene
devicen.png 14 ene
Ejemplos 14 ene
Consejos para que tus aplicaciones
25 jul ahor
Manuales 25 jul
Obtener todos los número
28 de
abrteléfono de
Primera aplicación de ejemplo:
4 ene Eurocalcu
Eurocalculadora_v0.6.zip4 ene

Pulsa Finish.

Ahora descárgate los gráficos pulsando aquí.


Ahora tienes que descomprimirlos en
C:\AndoidSDK\Proyectos\TutorialJuego1\res Sobreescribiendo en caso de que
te lo solicitara el sistema operativo.

Este directorio debería de quedar así:

…google.com/…/conocimientos-bsicos… 1/11
21/12/2010 Conocimientos básicos: Mover un obje…

Vamos a hacer un repaso de lo que hay en cada directorio:

drawable. Elementos que sirven para dibujarse en pantalla


independientemente del dispositivo.
drawable-land. Elementos que sirven para dibujarse en una pantalla de
320x240.
drawable-port. Elementos que sirven para dibujarse en un pantalla de
241x320.
layout. Contendrá XMLs para especificar interfaces gráficas.
values. Contendrá los textos a mostrar en la aplicación.

drawable-land y drawable-port contendrán los mismos archivos. Sólo que


dependiendo de cómo tenga la pantalla el dispositivo en el que se ejecute, se
cargarán los gráficos de un directorio o de otro. En cada directorio los gráficos
están adaptados a cada tipo de pantalla.

En el ejemplo que vamos a hacer tenemos estos dos tipos de fondos llamados
fondo.png:

¡Vamos a comenzar!

La esrtucturación de la interfaz gráfica de una aplicación para Android es muy


sencilla. Se compone de:
- Vistas (View). Que son los componentes que vemos en la aplicación. Botones,
Cuadros de texto, Etiquetas, etc.
- Contenedores de vistas (ViewGroup). Contendrán una o más vistas dentro,
mostrándolas en varias disposiciones.

Toda la pantalla donde dibujaremos en nuestra aplicación sera una vista (View),
es decir, un componente que llamaremos VistaJuego1. La situaremos dentro de
un ViewGroup. En este caso, dentro de un LinearLayout. (que ya lo
conocemos.)

Para hacer la vista, necesitamos añadir un archivo nuevo al proyecto. Para ello,
hacemos clic con el botón derecho sobre nuestro paquete dentro de src y
seleccionamos New > Class.

En el cuadro de diálogo que aparece especificamos los valores que se muestran


en la siguiente imagen:

…google.com/…/conocimientos-bsicos… 2/11
21/12/2010 Conocimientos básicos: Mover un obje…

Veamos una descripción de los campos más importantes:

Name: Nombre de la clase que queremos crear.


Modifiers: Accesibilidad de la clase. Para nuestro juego, queremos que
sea pública.
Superclass: Especificamos el comportamiento que queremos que tenga.
(La clase de la que queremos que herede.)
Constructors from superclass: Para que nos genere la clase con los
constructores ya creado.

Pulsamos sobre Finish.

Abrimos el archivo creado VistaJuego1.java haciéndole doble clic. Eliminamos


estos dos constructorres:

public VistaJuego1(Context context) {


super(context);
// TODO Auto-generated constructor stub
}

[...] Nos quedamos con el del centro [...]

public VistaJuego1(Context context, AttributeSet attrs, Map inflateParams,


int defStyle) {
super(context, attrs, inflateParams, defStyle);
// TODO Auto-generated constructor stub
}

Ahora vamos a editar el layout/main.xml para que nos muestre nuestro


VistaJuego1 a pantalla completa. Deberá de quedar tal que así:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<desarrolladores.android.com.tutorial.juego1.VistaJuego1
id="@+id/VistaJuego1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/fondo" />
…google.com/…/conocimientos-bsicos… 3/11
21/12/2010 Conocimientos básicos: Mover un obje…
android:background="@drawable/fondo" />
</LinearLayout>

Sobre el LinearLayout (Contenedor de vistas) no hay mucho que decir,


símplemente que ocupará todo el ancho y alto de la pantalla. La orientación nos
da igual, ya que sólo vamos a insertar un elemento.

Ahora lo interesante. Notar cómo dentro del archivo de VistaJuego1.java


estamos diciendo que se comporte como una vista (View).

public class VistaJuego1 extends View

Esto quiere decir, que lo podremos utilizar como si fuera un TextView, EditText
o cualquier otra vista.

Así que dentro del LinearLayout definimos una etiqueta llamada


desarrolladores.android.com.tutorial.juego1.VistaJuego1
(Tenemos que dar la ruta completa. Exáctamente la que aparece como paquete
dentro del directorio del proyecto, añadiendo ".VistaJuego1" al final.)

En los atributos de esta etiqueta estamos asignándole el identificador


VistaJuego1. (id="@+id/VistaJuego1")
Diciéndole que ocupe el máximo espacio que le deje su padre, tanto en horizontal
(width), como en vertical (height). (En este caso el LinearLayout que está
ocupando la pantalla entera.)

android:layout_width="fill_parent"
android:layout_height="fill_parent"

También le decimos que (android:background="@drawable/fondo") establezca


como imagen de fondo, la imagen (fondo.png. Se supone que son archivos .png)
que se encuentra en res/drawable. (Android buscará en el directorio drawable
y en el drawable que corresponda a la configuración del dispositivo en el que
estemos ejecutando la aplicación drawable-land o drawable-port.)

Vamos a ejecutar la aplicación. Deberemos de ver la imagen a pantalla


completa.
(Para instrucciones sobre cómo ejecutar la aplicación, mira este tutorial.)

¡Qué mal! Aparece la barra de título. ¡Vamos a quitarla! Para ello, vamos a editar
el código fuente de la Actividad. (La clase principal) Hacemos doble clic sobre
TutorialJuego1.java y dejamos el método onCreate de esta forma:

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

requestWindowFeature(Window.FEATURE_NO_TITLE);
…google.com/…/conocimientos-bsicos… 4/11
21/12/2010 Conocimientos básicos: Mover un obje…
requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.main);
}

Con esta instrucción estamos diciéndole a la ventana que alberga nuestra


aplicación que no muestre la barra de título.
Como nos aparece Window subrayado en rojo pulsamos Control+Shift+O para
incorporar las referencias a las nuevas clases a este archivo.

Guardamos y ejecutamos otra vez...

Podemos comprobar que si ejecutamos esta misma aplicación con el emulador


especificando como tamaño de pantalla QVGA Portrait.

Obtenemos esto...

Ahora vamos a editar la vista VistaJuego1.java haciéndole doble clic e


insertando el siguiente código justo debajo de public class VistaJuego1
extends View {

…google.com/…/conocimientos-bsicos… 5/11
21/12/2010 Conocimientos básicos: Mover un obje…
// Cuantos píxels nos moveremos a cualquier dirección cuando se pulse cada
tecla
private static int PASO_MOVIMIENTO = 5;
// Dimensiones de la pantalla del dispositivo
private int anchoPantalla, altoPantalla;
// Posición de la imagen que moveremos por la pantalla
private int posX, posY;
// Imagen que dibujaremos en la pantalla
private Drawable nube;
// Dimensiones de la imagen que dibujaremos
private int anchoNube, altoNube;

De aquí los más importantes son posX, posY (Que guardan en cada momento
donde dibujar la nube) y nube, que guardará una referencia a la imagen. (Ahora la
estableceremos.)

Como Drawable aparece subrayado en rojo, pulsamos Control+Shift+O para


que el editor nos inserte su referencia automaticamente.

Debajo de la línea super(context, attrs, inflateParams); añadimos el siguiente


código:

nube = context.getResources().getDrawable(R.drawable.nube);
anchoNube = nube.getIntrinsicWidth(); // Obtenemos el ancho de la nube
altoNube = nube.getIntrinsicHeight(); // Obtenemos el alto de la nube
setFocusable(true); // Para asegurarnos que recibimos las pulsaciones de
las teclas
setBackground(R.drawable.fondo);

La primera línea, nos sirve para cargar la imagen en memoria. (Y trabajar con ella
como si fuera un objeto Drawable. Es decir, un objeto que podemos pintar en la
pantalla.)

La segunda y tercera línea nos sirven para obtener el ancho y alto de la imagen
que acabamos de cargar.

setFocusable(true) nos sirve para indicarle a android que nuestra vista (View)
mantendrá el foco, esto quiere decir, que podremos detectar pulsaciones de
teclas que nos servirán para mover el objeto.

La última línea (gris) que muestro no tienes por qué ponerla ya que establecimos
la imagen de fondo en el XML. Esto es para que sepas que desde el código en
JAVA puedes establecer/cambiar la imagen del fondo cuando quieras.

Este sería un buen lugar para colocar el código donde le damos valores a las
variables anchoPantalla y altoPantalla, pero tenemos el problema de que en el
momento en el que se está ejecutando el constructor (este código), todavía no
sabemos las dimensiones de esta vista (View). Así que tendremos que tomarlos,
cuando se redimensione este objeto para ocupar la pantalla completa.

Para esto, hacemos clic con el botón derecho del ratón sobre el código. En el
menú que aparece seleccionamos Source > Override / Implement Methods...

En el cuadro de diálogo que aparece, marcamos onSizeChange(int, int, int,


int), onKeyDown(int, KeyEvent) y onDraw(Canvas), luego seleccionamos del
cuadro desplegable el elemento Last method para que nos inserte los métodos
que marcamos al final del archivo y para terminar pulsamos sobre el botón OK.
…google.com/…/conocimientos-bsicos… 6/11
21/12/2010
que marcamos al final del archivo y paraConocimientos básicos:
terminar pulsamos sobreMover un obje…
el botón OK.

Al final de VistaJuego1.java nos aparecerá los siguientes métodos: (Lo gris lo


he añadido yo)

// Para conocer el tamaño de la pantalla


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
}

// Para dibujar los gráficos que se mueven en pantalla


@Override
protected void onDraw(Canvas canvas) {

// TODO Auto-generated method stub


super.onDraw(canvas);
}

// Para detectar las pulsaciones de teclas


@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
return super.onKeyDown(keyCode, event);
}

Si al incluir este código aparecen algunos nombres de clase subrayados en rojo,


pulsa Control+Shift+O como hemos hecho otras veces.

Android llamará a onSizeChanged para indicarle/notificar a la vista (View) que


se le ha cambiado las dimensiones. Pasándole como parámetros en w (el ancho
nuevo), h (el alto nuevo), oldw (el ancho que tenía ántes de redimensionar) y
oldh (el alto que tenía ántes de redimensionar).

También llamará a onDraw(Canvas) para decirle a la aplicación que ejecute sus


instrucciones de dibujado en pantalla. (Es decir, para que la vista que hemos
creado se dibuje/actualice.)

Lo que nos interesa ahora, es dejar el método onSizeChanged así:

@Override
…google.com/…/conocimientos-bsicos… 7/11
21/12/2010 Conocimientos básicos: Mover un obje…
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);

// Una vez que conocemos nuestro ancho y alto.


anchoPantalla = w;
altoPantalla = h;
posX = (anchoPantalla / 2)-(anchoNube/2);
posY = (altoPantalla / 2)-(altoNube/2);
}

Como podréis observar, tomamos en anchoPantalla el valor de w (Que es el


ancho al que se está redimensionando la vista). Se supone que después de
crearse la vista (el objeto que se visualiza como la pantalla en el movil), Android la
intentará posicionar y dimensionar (A pantalla completa, según le especificamos
en el XML), notificándonos con una llamada a este método para que nosotros
actuemos en consecuencia. (En este caso, tomaremos las dimensiones a las
que se redimensionará. Así obtenemos el ancho y alto de la pantalla.)

También, de paso, establecemos el punto inicial donde aparecerá el objeto que


moveremos por la pantalla. En este caso, lo dibujaremos en el centro de la
pantalla. Si hubiéramos puesto sólo:

posX = (anchoPantalla / 2);


posY = (altoPantalla / 2);

posX y posY tendrían las coordenadas del centro de la pantalla, pero como
cuando dibujarmos el punto que damos es el de la esquina superior izquierda, en
este caso, estaríamos colocando la esquina superior izquierda del objeto en el
centro de la pantalla. El objeto no quedaría centrado. (Por eso, lo desplazamos la
mitad de su ancho y la mitad de su alto)

Sería importante que una vez terminado este ejemplo probaras darle valores
directamente, como por ejemplo:

posX = 0;
posY = 0;

Para darte una referencia, estas son las coordenadas (x,y) de las esquinas de la
pantalla:

Para quien no le quede claro, voy a poner un ejemplo para un tamaño de pantalla
de 320 x 240
Cuando x vale 0, indica que está en el lado izquierdo y cuando vale 320, indica
que está en el derecho. Cuando vale 160, está en la mitad.
Cuando y vale 0, indica que está arriba de la pantalla y cuando vale 240, indica
que está abajo del todo. Cuando vale 120, está en la mitad.

Ya que tenemos inicializados todos los valores y cargado el gráfico... ¡Vamos a


pintar!

…google.com/…/conocimientos-bsicos… 8/11
21/12/2010 Conocimientos básicos: Mover un obje…
Para ello, dejaremos el método onDraw así: (Se añaden las treslíneas que indico
en negrita)

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
nube.setBounds(posX, posY, posX+anchoNube, posY+altoNube);
nube.draw(canvas);
invalidate(posX-PASO_MOVIMIENTO, posY-PASO_MOVIMIENTO,
posX+anchoNube+PASO_MOVIMIENTO,
posY+altoNube+PASO_MOVIMIENTO);
}

En la primera le estamos diciendo donde queremos dibujarla indicando la esquina


superior izquierda (posX, posY) y la esquina inferior derecha (posX+anchoNube,
posY+altoNube) del cuadro donde queremos dibujar la imagen.

Si te fijas bien en este esquema, comprenderás cómo por qué para saber las
coordenadas de la esquina inferior derecha tenemos que sumar posX con
anchoNube, al igual que posY con altoNube.

En la segunda línea, le estamos diciendo que se dibuje en canvas. Podemos


pensar en un objeto Canvas como un lienzo en el que podemos dibujar. Android
nos da una referencia a este "lienzo" (Canvas canvas) cuando le "dice" a nuestro
programa (View) que se dibuje (onDraw).

En la tercera línea invalidate(posX-PASO_MOVIMIENTO, posY-


PASO_MOVIMIENTO, posX+anchoNube+PASO_MOVIMIENTO,
posY+altoNube+PASO_MOVIMIENTO); le estamos diciendo a Android que ya
no es válida la imagen que se vé en ese área y que hay que redibujar sólo la zona
que le indicamos (La zona que ocupa la nube mas un margen de
PASO_MOVIMIENTO píxeles de borde, por el movimiento que pueda hacer), de
esta forma, al no tener que dibujar la pantalla entera, va más rápido.

Podríamos haber hecho un invalidate() que invalida la pantalla entera y obliga a


Android a dibujarla por completo, pero NO lo haremos, ya que es muy costoso y
ralentizaría bastante. Por eso es mejor especificar tantos "invalidates" como
áreas pequeñas hayan podido cambiar en la pantalla. (Que es más eficiente.)

Vamos a ejecutar y veremos que ahora aparece la nube en el centro de la


pantalla...

…google.com/…/conocimientos-bsicos… 9/11
21/12/2010 Conocimientos básicos: Mover un obje…

Ahora necesitamos que se mueva cuando pulsemos las teclas correspondientes.


Para eso, vamos a rellenar el onKeyDown (que será el método que Android
llame de nuestra vista (View) cuando el usuario pulse una tecla. (De esta forma
Android nos indica qué tecla se está pulsando.)
Este método deberá quedar así:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Suponemos que vamos a procesar la pulsación
boolean procesada = true;

switch(keyCode){
case KeyEvent.KEYCODE_DPAD_UP:
posY-=PASO_MOVIMIENTO;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
posY+=PASO_MOVIMIENTO;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
posX-=PASO_MOVIMIENTO;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
posX+=PASO_MOVIMIENTO;
break;
default:
// Si hemos llegado aquí, significa que no hay pulsación que nos interese
procesada = false;
break;
}

// Si nos salimos de la pantalla, corregimos la posición


// para que no aparezca fuera.
if(posY<0)
posY=0;
if(posX<0)
posX=0;
if(posY+altoNube>altoPantalla)
posY=altoPantalla-altoNube;
if(posX+anchoNube>anchoPantalla)
posX=anchoPantalla-anchoNube;

return procesada;
}

La parte azul del código anterior está bastante clara, vamos a comprobar los
valores de la tecla pulsada, que nos vienen en keyCode. Lo hacemos con un
switch(keyCode){

Si la tecla coincide con la pulsación de arriba en el pad: case


KeyEvent.KEYCODE_DPAD_UP:
entonces posY-=PASO_MOVIMIENTO; decrementamos posY el valor de
PASO_MOVIMIENTO.
(Al hacer posY más pequeña, estamos subiendo hacia la parte de arriba de la
pantalla.)

Lo mismo con las demás pulsaciones, tendiento en cuenta que:

UP - Arriba
DOWN - Abajo
LEFT - Izquierda
RIGHT - Derecha

La parte roja del código anterior es más fácil. En ella, comprobamos que posY y
posX se encuentren dentro de los límites de la pantalla, teniendo en cuenta, que
las coordenadas que damos son las de la esquina superior izquierda de la imagen
que vamos moviendo. En cuanto detectamos que nos salimos, ponemos su valor
…google.com/…/conocimientos-bsicos… 10/11
21/12/2010 Conocimientos básicos: Mover un obje…
que vamos moviendo. En cuanto detectamos que nos salimos, ponemos su valor
justo en el borde por el que nos hemos salido. Ejemplo, si posY es menor que
cero, lo dejamos a cero. (En vez de quedarnos con un valor negativo.)

Ejecutamos otra vez... Probamos que podemos mover la nube pulsando las
teclas de dirección y que no se puede salir de la pantalla.

Si quieres bajarte el proyecto en un archivo ZIP tal y como está ahora,


puedes hacerlo pulsando aquí.
Si tienes alguna duda o sugerencia, entra en Dudas y preguntas y
coméntala. Intentaré responder lo ántes posible.

Versión: Actual por juande - 18 jun

Debatir sobre esta página Informar sobre esta página

Crear un grupo - Grupos de Google - Página principal de Google - Condiciones del servicio - Política de privacidad
©2010 Google

…google.com/…/conocimientos-bsicos… 11/11

S-ar putea să vă placă și