sábado, 15 de marzo de 2014

Android - Primeros Pasos - Mostrando listados 2

En el artículo anterior vimos como usar el componente ListView. Sin embargo sólo mostrabamos en cada elemento un string, vamos a ver como mostrar item mas complejos.

Para el ejemplo vamos a crear una lista que muestre fichas de personas con el nombre y la foto de la persona.

Lo primero es crear un layout en la carpeta res/layout, ya sea mediante el asistente de eclipse o creando un archivo xml con el código correspondiente. Este layout será el que indicará que elementos y como se va a mostrar cada uno de los items de la lista.



Vamos a añadir al layout dos elementos un ImageView para mostrar la foto y un TextView para el nombre de la persona.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="94dp"
        android:layout_weight="0.80"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="214dp"
        android:layout_height="46dp"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</LinearLayout>


Ahora vamos a crear dos clases, una que representa al objeto persona y otra que extenderá de la clase ArrayAdapter y que se va a encargar de generar cada uno de los items que se van a mostrar en el ListView.

Clase Persona:


package com.ljlg.programandoblog;

import android.graphics.Bitmap;

public class Persona {   
    private String nombre;   
    private Bitmap foto;
  
    public Persona(String nombre, Bitmap foto)
    {
        this.nombre = nombre;
        this.foto = foto;       
    }
    public String getNombre() {
        return nombre;
    }
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    public Bitmap getFoto() {
        return foto;
    }
    public void setFoto(Bitmap foto) {
        this.foto = foto;
    }
}


Clase PersonaAdapter


package com.ljlg.programandoblog;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;


public class PersonaAdapter extends ArrayAdapter<Persona>
{
   
    Context context;
    int layoutResourceId;
    private List<Persona> datos;


    public PersonaAdapter(Context context, int layoutResourceId, List<Persona> datos) {
        super(context, layoutResourceId, datos);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.datos = datos;
    }
   
   
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
       
        View row = convertView;
       
        if (row == null) {
            // Si la fila que se está mostrando no ha sido creada con anterioridad
            LayoutInflater inflater = (LayoutInflater) getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.persona, null);
        }
       
        Persona persona = datos.get(position);
       
        if (persona != null)
        {
            // rellenamos
            TextView nombre = (TextView) row
                    .findViewById(R.id.textView1);
            nombre.setText(persona.getNombre());
           
            ImageView foto = (ImageView) row.findViewById(R.id.imageView1);           
            foto.setImageBitmap(persona.getFoto());
        }       
        return row;       
    }
}


Finalmente sólo tendremos que hacer la craga de los valores en nuetra actividad de manera similar a como se vió en el artículo anterior:


package com.ljlg.programandoblog;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ListView;

public class MainActivity extends Activity {

    ListView listView;

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

        // listView definido en el layout
        listView = (ListView) findViewById(R.id.listView1);

        List<Persona> valores = new ArrayList<Persona>();

        // Cargar la lista de personas
        Bitmap foto = cargarFoto();
        valores.add(new Persona("Luis", foto));
        valores.add(new Persona("Juan", foto));

        // Adaptador
        PersonaAdapter adaptador = new PersonaAdapter(this, R.layout.persona,
                valores);

        // Asignar el adaptador al listview
        listView.setAdapter(adaptador);

    }

    private Bitmap cargarFoto() {
        try {
            // Para el ejemplo cargamos una foto desde la carpeta assets
            InputStream archivo = getAssets().open("foto.png");
            Bitmap bitmap = BitmapFactory.decodeStream(archivo);
            return bitmap;
        } catch (IOException e1) {

            e1.printStackTrace();
        }
        return null;
    }

}


martes, 11 de marzo de 2014

Android - Primeros Pasos - Mostrando listados

Para mostrar una lista en nuestra aplicación Android debemos usar el componente ListView.

Lo primero que debemos hacer es añadir  un elemento ListView al layout donde se desea que aparezca el listado. Si estamos trabajando con el editor gráfico de eclipse podemos encontrar el componente en el apartado Composite de la paleta, tal y como se ve en la siguiente imagen.


En código nuestro layout quedará algo como lo siguiente:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true" >

    </ListView>
</RelativeLayout>

Ahora lo siguiente es añadir contenido al componente, el código sería el siguiente:


    ListView listView;

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

        // listView definido en el layout
        listView = (ListView) findViewById(R.id.listView1);

        // Definir lista de valores a mostrar
        String[] valores = new String[] { "Android - Primeros Pasos",
                "Android - Depurando", "Android - Botones",
                "Android - Layouts", "Android - ListView" };

        // Adaptador
        ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, android.R.id.text1,
                valores);

        // Asignar el adaptador al listview
        listView.setAdapter(adaptador);
      
        // Añadir evento
        addOnClickView();

    }

    private void addOnClickView() {
        listView.setOnItemClickListener( new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adview, View v,
                    int posicion, long id) {
                // Mostrar texto
                Toast.makeText(
                        getApplicationContext(),
                        "Valor :"
                                + (String) listView.getItemAtPosition(posicion),
                        Toast.LENGTH_LONG).show();
            }});
    }



El código es bastante sencillo, aunque es necesario explicar que es el adaptador y cuáles son los parámetros que se le pasan. El adaptador se encarga de pasar a la lista cada una de la filas con el formato indicado en un layout (en este caso se trata de un layout ya predefinido android.R.layout.simple_list_item_1). Podemos crear nuestro propio adaptador, que muestre varios elementos por fila, por ejemplo podríamos tener un adaptador que en cada fila mostrará los datos de una persona, incluyendo su foto, su nombre, etc. Como veremos en un futuro artículo que añadiré.

Para este ejemplo se ha usado un adaptador ya existe que permite mostrar una lista de valores. A su constructor se le pasan los siguientes parámetros:
  • Context.
  • Layout a aplicar para mostrar cada fila.
  • Lista de valores.
Con esto ya podemos mostrar nuestra lista. Ahora fijémonos en la función addOnClickView. En esta función se está registrando un escuchador sobre los ítems del listView de modo que cuando se pulse sobre uno de ellos podremos acceder a la información del mismo y realizar el tratamiento que queramos, para el ejemplo se muestra un mensaje.

domingo, 9 de marzo de 2014

Android - Primeros Pasos - Moviéndonos entre pantallas

Cada pantalla está asociada a una Actividad, así pues cada vez que creemos una nueva pantalla debemos crear una nueva actividad, esto lo podemos hacer a través del asistente de eclipse.

Cuando se crea una actividad en nuestro proyecto se llevan a cabo las siguientes modificaciones:

  • Se crea una clase java asociada a la actividad.
  • Se crea el correspondiente archivo de definición layout en res/layout.
  • Se añade el nombre de la pantalla en el archivo res/values/strings.xml.
  • Se modifica el archivo AndroidManifest.xml quedando registrada la nueva actividad.

En el manifiesto aparecerá algo similar a lo siguiente:


         <activity
            android:name="com.ljlg.programandoblog.Nueva"
            android:label="@string/title_activity_nueva"
            android:parentActivityName="com.ljlg.programandoblog.MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.ljlg.programandoblog.MainActivity" />
        </activity>


Una vez que tenemos nuestra nueva actividad definidad, para cargarla usaremos la clase Intents. Esta clase nos proporciona un mecanismo para invocar componentes.

Ya hemos visto como añadir acciones a los botones. Así pues vamos a añadir la carga de una nueva pantalla al pulsar un botón. Para ello vamos a añadir el siguiente código al listener asociado al botón.

        button.setOnClickListener(new OnClickListener() {          
            @Override
            public void onClick(View v) {               
                Intent intent = new Intent(v.getContext(), SegundaActivity.class);
                startActivity(intent);
            }
        });

Con esto se nos cargará la nueva pantalla al pulsar sobre el botón.
Ahora vamos a añadir en la nueva actividad un botón para volver a la pantalla desde la que se realizó la llamada. Para ello el código de la clase asociada a nuestra nueva actividad será el siguiente:


package com.ljlg.programandoblog;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SegundaActivity extends Activity {

    Button button;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_segunda);
        addListenerButtonVolver();
    }

    private void addListenerButtonVolver() {               button = (Button) findViewById(R.id.button1);              
        button.setOnClickListener(new OnClickListener() {           
            @Override
            public void onClick(View v) {               
                finish();                              
            }
        });       
    }   
}

Como vemos tan sólo es necesario añadir al listener del botón la llamada a la función finish().

viernes, 7 de marzo de 2014

Android - Primeros Pasos - Depurando y probando nuestra aplicación

La depuración es parte de cualquier desarrollo y es la que en muchos casos nos permite encontrar fallos en nuestro programa. Cuando realizamos un desarrollo software para Android además es recomendable realizar pruebas en distintos dipositivos, por un lado para ver si funciona correctamente en las diferentes versiones del sistema, como para ver si se adapta correctamente a las resoluciones mas comunes.

En anteriores entradas ya he explicado como crear una aplicación básica para Android, ahora veamos como probar nuestra aplicación.

Para depurar nuestra aplicación nos ponemos con el ratón sobre el proyecto, pulsamos el botón derecho del mismo y en el menú contextual seleccionamos Debug As -> Android Application, tal y como aparece en la imagen.

A continuación nos aparecerá la siguiente pantalla la cual nos pide que seleccionemos el dispositivo en el cual realizar la depuración. Aquí tenemos varias opciones: podemos realizar la depuración en un dispotivo real, el cual debemos tener conectado a través del cable USB o seleccionar un dispositivo virtual.

Inicialmente es muy probable que no aparezca ningún dispositvo, aunque lo tengais conectado a través del puerto USB, esto se debe a que el dispositivo debe permitir la depuración y para ello debemos activarla en el mismo. Lo hay que hacer es ir al dispositvo abrir Ajustes -> Sistema -> Opciones de desarrollador y aquí activar la opción "Depuración de USB". 

Hay que tener en cuenta que tener en cuenta que a partir de la versión Android 4.2 (Jelly Bean) las opciones de desarrollador se encuentran ocultas. Para mostralas debemos ir a Ajustes > Información del dispositivo y pulsar siete veces sobre el número de compilación. Una vez hecho esto ya aparecerán las opciones de desarrollador. 

Una vez que activamos la depuración y conectemos el dispositivo mediante USB nos aparecerá en el mismo una pantalla preguntandonos si deseamos perimitir la depuración USB, debemos responder afirmativamente, en caso contrario en la pantalla de dispositivos disponibles nos aparece el dispositivo, pero no nos permitirá usarlo para depurar (el dispositivo aparecería como con estado "??" frente a Online que es el estado correcto). 


Una vez seleccionado el dispositivo comienza la ejecución y podremos depurar nuestra aplicación como cualquier otra aplicación java.

También es posible realizar la depuración sobre un dispositivo virtual, pulsando sobre el botón Manager de la pantalla anterior es posible crear nuevos dispositivos virtuales que podrán ser usados para las pruebas. 



jueves, 6 de marzo de 2014

Estructuras arboreas en HTML

He creado una pequeña utlidad a la que podeís acceder aquí. La cual os permitirá generar una estructura de  árbol y os generará el código HTML y javascript necesario y que posteriormente podreís modificar a vuestro gusto. La estructura de árbol que se genera es como la que se presenta a continuación.

Elemento 2.1.1

Se trata de una primera versión, pero espero que os sea de utilidad.

domingo, 2 de marzo de 2014

Android - Primeros Pasos - Añadiendo acciones a los botones

Anteriormente hemos visto como desarrollar una primera aplicación para Android partiendo de cero. Partiendo de dicha aplicación vamos a ver como añadir acciones a los botones que añadamos a la aplicación.

Para añadir botones y otros componentes debemos abrir el archivo res/layout/activity_main.xml (esta es la pantalla que hemos definido como principal en el anterior artículo, en caso de que quieras trabajar con otra pantalla el nombre del archivo será el que corresponda).

Si estamos usando eclipse entonces veremos el editor gráfico en el cual podemos añadir los elementos que queramos:


Si vemos el código del archivo tendremos lo siguiente:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="17dp"
        android:text="Botón de prueba" />

</RelativeLayout>

Como vemos se han definido dos componentes uno de tipo TextView y otro de tipo Button para este ejemplo lo que vamos a hacer es mostrar la hora actual cada vez que de pulse el botón.

Así pues una vez que tenemos la pantalla definida debemos ir a la calse java que es donde debemos asociar los eventos mediante la generación de un listener asociado al botón. El código resultante es el siguiente:

package com.ljlg.programandoblog;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends Activity {
  
    Button button;

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

        // Añadir el listener
        addListenerButtonPrueba();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
  
    // Función a ejecutar al inciar la pantalla, dentro de 

    // esta función hemos definido el listener asociado 
    // a botón
    private void addListenerButtonPrueba() {
  
         button = (Button) findViewById(R.id.button1);
      
        button.setOnClickListener(new OnClickListener() {
           

            // Acción a ejecutar cada vez que se pulse el botón
            @Override
            public void onClick(View v) {
                TextView text = (TextView) findViewById(R.id.textView1);
                text.setText("Hora:" + new SimpleDateFormat("HH:mm:ss").format(new Date()));            
            }
        });     
    }

}

Como vemos en el código lo que se hace es añdir un listener asociado al botón en el momento de iniciar la aplicación (función onCreate),

Con esto ya tenemos una acción asociada a nuestro botón de modo que cada vez que pulsemos se actualizará el texto que se muestra con la hora actual.