Bienvenidos sean a este post, hoy haremos un interfaz de entrada para nuestra app porque hasta ahora cada vez que la abrimos siempre nos muestra la vista llamada edicion_lugar.xml y ahora la modificaremos para mostrar los contenidos en nuestra app, para lograr esto utilizaremos una vista ListView la cual tiene como particularidad la posibilidad de utilizar layouts como elementos de la misma pero lo iremos viendo durante el post y sin mas preambulos comencemos con la modificacion.

Anuncios

Abramos MisLugares, una vez dentro del editor haremos click con el boton derecho sobre el recurso layout, seleccionaremos New -> Layout resource file como se ve en la siguiente imagen

android45

Una vez seleccionado nos aparecera el siguiente cuadro

android46

Aca debemos modificar el campo File Name, le asignaremos el nombre activity_main, luego modificaremos a Root element donde le asignaremos LinearLayout, despues dejamos todo como se ve y pulsamos Ok, esto cerrara el cuadro y generara el nuevo archivo y quedando como se ve en la siguiente imagen

android47

Ahora procedamos a modificar nuestro nuevo archivo pero primero veamos su codigo actual:

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

</LinearLayout>

Ahora vamos a modificarlo por el siguiente codigo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
    <ListView
         android:id="@+id/ListaVista"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:drawSelectorOnTop="false" />
</LinearLayout>

Como pueden ver agregamos el elemento ListView, le dimos un id y seteamos una propiedad llamada drawSelectorOnTop al estado falso (false), con esto hemos creado nuestro elemento ahora procederemos a modificar la clase MainActivity para llamar a este nuevo layout y llenar nuestra lista, veamos el codigo actual de nuestra clase MainActivity:

package org.example.mislugares;

import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

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

    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    public void lanzarAcercaDe(View view){
        Intent i = new Intent(this,AcercaDe.class);
        startActivity(i);
    }

    public void lanzarVistaLugar(View view){
        final EditText entrada = new EditText(this);
        entrada.setText("0");
        new AlertDialog.Builder(this)
          .setTitle("Seleccion del Lugar")
          .setMessage("Indica su id")
          .setView(entrada)
          .setPositiveButton("Ok", 
                 new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, 
                            int whichButton) {
                long id = Long.parseLong(entrada.getText().toString());
                Intent i = new Intent(MainActivity.this, VistaLugar.class);
                i.putExtra("id",id);
                startActivity(i);
             }
          })
          .setNegativeButton("Cancelar",null)
          .show();
    }

    public boolean onOptionsItemSelected(MenuItem item){
        int id = item.getItemId();
        if (id == R.id.config){
            return true;
        }
        if (id == R.id.buscar){
            lanzarVistaLugar(null);
            return true;
        }
        if (id == R.id.about){
            lanzarAcercaDe(null);
        }
        return super.onOptionsItemSelected(item);
    }
}
Anuncios

Ahora lo modificaremos por el siguiente codigo:

package org.example.mislugares;

import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

    public AdaptadorLugares adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adaptador = new AdaptadoreLugares(this);
        ListView listavista = (ListView) findViewById(R.id.ListaVista);
        listavista.setAdapter(adaptador);
    }

    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    public void lanzarAcercaDe(View view){
        Intent i = new Intent(this,AcercaDe.class);
        startActivity(i);
    }

    public void lanzarVistaLugar(View view){
        final EditText entrada = new EditText(this);
        entrada.setText("0");
        new AlertDialog.Builder(this)
           .setTitle("Seleccion del Lugar")
           .setMessage("Indica su id")
           .setView(entrada)
           .setPositiveButton("Ok",
                 new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog,
                                   int whichButton) {
                long id = Long.parseLong(entrada.getText().toString());
                Intent i = new Intent(MainActivity.this, VistaLugar.class);
                i.putExtra("id",id);
                startActivity(i);
                }
           })
           .setNegativeButton("Cancelar",null)
           .show();
    }

    public boolean onOptionsItemSelected(MenuItem item){
        int id = item.getItemId();
        if (id == R.id.config){
            return true;
        }
        if (id == R.id.buscar){
            lanzarVistaLugar(null);
            return true;
        }
        if (id == R.id.about){
            lanzarAcercaDe(null);
        }
        return super.onOptionsItemSelected(item);
    }
}

Analicemos el codigo, tendremos una linea donde indicara un error:

public AdaptadorLugares adaptador;

Pero no se hagan problema porque si bien ahora nos devuelve un error mas adelante lo solucionaremos prosigamos con modificacion realizada en nuestro metodo onCreate():

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    adaptador = new AdaptadoreLugares(this);
    ListView listavista = (ListView) findViewById(R.id.ListaVista);
    listavista.setAdapter(adaptador);
}

Nuestras modificaciones son la linea del metodo setContentView() donde la apuntaremos al nuevo archivo XML creado, activity_main.xml, definiremos nuestro objeto creado anteriormente (adaptador), luego crearemos el vinculo entre Java y el elemento del XML y en la ultima linea le asignaremos el adaptador a nuestra listView. Ahora comenzaremos a corregir los errores, primero vamos a generar el layout de cada uno de los elementos del ListView, vamos al recuros layout y hacemos click con el boton derecho, seleccionamos New -> Layout resource file como se ve en la siguiente imagen

android45

Donde nos aparecera el siguiente cuadro

android48

Aca deberemos completar el campo File Name con elemento_lista, luego en Root element debemos seleccionar RelativeLayout, dejamos el resto como se ve y pulsamos Ok, esto cerrara el cuadro y generara el archivo. Ahora veamos el codigo fuente de este nuevo archivo:

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

</RelativeLayout>

Lo modificaremos de la siguiente forma:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeight">
    <ImageView
         android:id="@+id/foto"
         android:layout_width="?android:attr/listPreferredItemHeight"
         android:layout_height="?android:attr/listPreferredItemHeight"
         android:layout_alignParentLeft="true"
         android:contentDescription="fotografia"
         android:src="@drawable/bar"/>
    <TextView
         android:id="@+id/nombre"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="Nombre del lugar"
         android:layout_toRightOf="@id/foto"
         android:layout_alignParentTop="true"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:singleLine="true"/>
    <TextView
         android:id="@+id/direccion"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@id/nombre"
         android:layout_toRightOf="@id/foto"
         android:gravity="center"
         android:singleLine="true"
         android:text="direccion del lugar" />
    <RatingBar
         android:id="@+id/valoracion"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:layout_below="@id/direccion"
         android:layout_toRightOf="@id/foto"
         style="?android:attr/ratingBarStyleSmall"
         android:isIndicator="true"
         android:rating="3" />
</RelativeLayout>
Anuncios

En este nuevo codigo agregamos cuatro elementos, primero una foto, luego el nombre ubicado a la derecha de la foto y arriba, luego la direccion por debajo del nombre y a la derecha de la foto y por ultimo la barra de rating por debajo de direccion y a la derecha de la foto. Esto lo logramos por medio de los atributos layout_below (ubica por debajo de donde se le dice), layout_toRightOf (ubica a la derecha del objeto mencionado), layout_gravity (lo ubica en donde lo designamos), layout_alignParentLeft (lo ubica a la izquierda total), layout_alignParentRight (al igual que el anterior pero a la derecha), layout_alignParentTop (lo ubica arriba de todo) y layout_alignParentBottom (este lo ubica al final de todo). Todo esto se logra gracias al tipo de vista (RelativeLayout) pero para lograr hacer funcionar todo lo mencionado anteriormente debemos generar una ultima clase. Ahora haremos click con el boton derecho sobre el contenedor de clases java, seleccionando New -> Java class como se ve en la siguiente imagen

android33

Despues de esto aparecera el siguiente cuadro

android49

Aca modificaremos el campo Name por AdaptadorLugares, dejamos el resto como se ve en la imagen, pulsamos Ok se cerrara el cuadro y se generara la clase quedando de la siguiente forma

android50

Ahora abramos el nuevo archivo para agregar el nuevo codigo pero antes veamos el codigo actual:

package org.example.mislugares;

public class AdaptadorLugares {
}

Procedamos a modificar la clase con el siguiente codigo:

package org.example.mislugares;

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

public class AdaptadorLugares extends BaseAdapter {

    private LayoutInflater inflador;
    TextView nombre, direccion;
    ImageView foto;
    RatingBar valoracion;
    public AdaptadorLugares(Context contexto){
        inflador = (LayoutInflater) contexto
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int posicion, View vistaReciclada,
                        ViewGroup padre) {
        Lugar lugar = Lugares.elemento(posicion);
        if (vistaReciclada == null) {
            vistaReciclada =
                    inflador.inflate(R.layout.elemento_lista, null);
        }
        nombre = (TextView) vistaReciclada.findViewById(
                R.id.nombre);
        direccion = (TextView) vistaReciclada.findViewById(
                R.id.direccion);
        foto = (ImageView) vistaReciclada.findViewById(
                R.id.foto);
        valoracion = (RatingBar) vistaReciclada.findViewById(
                R.id.valoracion);
        nombre.setText(lugar.getNombre());
        direccion.setText(lugar.getDireccion());
        int id = R.drawable.otros;
        switch(lugar.getTipo()){
            case RESTAURANTE:id = R.drawable.restaurante; break;
            case BAR:id = R.drawable.bar; break;
            case COPAS:id = R.drawable.copas; break;
            case ESPECTACULO:id = R.drawable.espectaculos; break;
            case HOTEL:id = R.drawable.hotel; break;
            case COMPRAS:id = R.drawable.compras; break;
            case EDUCACION:id = R.drawable.educacion; break;
            case DEPORTE:id = R.drawable.deporte; break;
            case NATURALEZA:id = R.drawable.naturaleza; break;
            case GASOLINERA:id = R.drawable.gasolinera; break;
        }
        foto.setImageResource(id);
        foto.setScaleType(ImageView.ScaleType.FIT_END);
        valoracion.setRating(lugar.getValoracion());
        return vistaReciclada;
    }

    public int getCount(){
        return Lugares.size();
    }

    public Object getItem(int posicion) {
        return Lugares.elemento(posicion);
    }

    public long getItemId(int posicion){
        return posicion;
    }
}

Esta clase va a ser un poco mas complicada de explicar pero no tanto, comencemos con el primer objeto creado en este caso llamado inflador el cual sera de un elemento utilizado para rellenar layouts, luego crearemos cuatro objetos para generar los vinculos entre los elementos del XML y el codigo Java (nombre, direccion, foto y valoracion) despues definiremos un constructor para asignar a nuestro objeto inflador la capacidad de rellenar nuestro layout pero utilizamos el metodo getSystemService() y vemos una intencion LAYOUT_INFLATER_SERVICE,  de la cual hablaremos mas adelante en otro post. Nuestro proximo metodo es uno propio de la clase View por lo que generara tres atributos y con los mismos nos encargaremos de vincular los elementos de nuestro layout con los objetos creados, en este caso utilizaremos vistaReciclada y por medio de findViewById() crearemos los vinculos y luego por medio del metodo setText() asignaremos el valor obtenido por medio del objeto lugar y los metodos para obtener los datos (p.e. getNombre()), nuestra parte mas interesante es la encargada de asignar el icono del elemento analicemos esta linea primero:

int id = R.drawable.otros;
Anuncios

Aca creamos una variable llamada id donde le asignaremos el valor R.drawable.otros, luego tenemos el siguiente bloque:

switch(lugar.getTipo()){
    case RESTAURANTE:id = R.drawable.restaurante; break;
    case BAR:id = R.drawable.bar; break;
    case COPAS:id = R.drawable.copas; break;
    case ESPECTACULO:id = R.drawable.espectaculos; break;
    case HOTEL:id = R.drawable.hotel; break;
    case COMPRAS:id = R.drawable.compras; break;
    case EDUCACION:id = R.drawable.educacion; break;
    case DEPORTE:id = R.drawable.deporte; break;
    case NATURALEZA:id = R.drawable.naturaleza; break;
    case GASOLINERA:id = R.drawable.gasolinera; break;
}

Aca utilizaremos un switch() donde le asignaremos el valor obtenido por medio de lugar.getTipo() y luego en cada case verificaremos a quien equivale, en caso de coincidir asignaremos a id un valor diferente al asignado y con el metodo break saldremos del switch(), en caso de no coincidir con ninguno no modificara el valor de id y utilizara ese valor, en la siguiente linea asignara el valor de id como resource para utilizar esa imagen, luego aplicara una propiedad para escalarla y con la propiedad FIT_END la ajustara hasta donde puede, por ultimo asignaremos el valor al elemento valoracion, finalizando todo con la devolucion del valor vistaReciclada y despues agregaremos algunos metodos mas para retornar posicion, tamaño y el item en cuestion, si todo salio bien deberemos tener una salida como se ve en la siguiente imagen

android51

Si bien esto ya esta funcional cuando apretemos cualquiera de los elementos no hara ninguna accion, para esto vamos a hacer una serie de modificaciones y agregar un nuevo metodo para terminar definitivamente con nuestro post de hoy. Vamos a realizar la siguiente modificacion en la clase MainActivity primero veamos este bloque:

public class MainActivity extends AppCompatActivity {

    public AdaptadorLugares adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adaptador = new AdaptadorLugares(this);
        ListView listavista = (ListView) findViewById(R.id.ListaVista);
        listavista.setAdapter(adaptador);
    }

Ahora lo modificaremos de esta manera:

public class MainActivity extends AppCompatActivity 
        implements AdapterView.OnItemClickListener {

    public AdaptadorLugares adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adaptador = new AdaptadorLugares(this);
        ListView listavista = (ListView) findViewById(R.id.ListaVista);
        listavista.setAdapter(adaptador);
        listavista.setOnItemClickListener(this);
    }

Como pueden ver agregamos dos modificaciones la primera es en esta linea:

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
Anuncios

Con esta modificacion permitiremos a la clase tener la posibilidad de poder “escuchar” al evento click sobre un item de la vista, y esta es la otra modificacion:

listavista.setOnItemClickListener(this);

Donde le diremos que ahora nuestro vista listavista estara atenta al evento click sobre ella. Luego agregaremos el siguiente metodo dentro de la clase:

public void onItemClick(AdapterView<?> parent, View vista,
                           int posicion, long id){
    Intent i = new Intent(this,VistaLugar.class);
    i.putExtra("id", id);
    startActivity(i);
}

Este servira para cuando se haga click sobre algun elemento crearemos una nueva actividad a la clase VistaLugar y la iniciaremos enviandole el id, para que esto funcione correctamente deberan agregar el paquete AdapterView pero a medida que lo vayan tipeando el editor les solicitara presionar Alt+Enter para agregarlo, con las modificaciones realizadas nuestro codigo quedara de la siguiente manera:

package org.example.mislugares;

import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity
        implements AdapterView.OnItemClickListener {

    public AdaptadorLugares adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adaptador = new AdaptadorLugares(this);
        ListView listavista = (ListView) findViewById(R.id.ListaVista);
        listavista.setAdapter(adaptador);
        listavista.setOnItemClickListener(this);
    }

    public void onItemClick(AdapterView<?> parent, View vista,
                               int posicion, long id){
        Intent i = new Intent(this,VistaLugar.class);
        i.putExtra("id", id);
        startActivity(i);
    }

    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    public void lanzarAcercaDe(View view){
        Intent i = new Intent(this,AcercaDe.class);
        startActivity(i);
    }

    public void lanzarVistaLugar(View view){
        final EditText entrada = new EditText(this);
        entrada.setText("0");
        new AlertDialog.Builder(this)
           .setTitle("Seleccion del Lugar")
           .setMessage("Indica su id")
           .setView(entrada)
           .setPositiveButton("Ok",
                 new DialogInterface.OnClickListener() {
           @Override
           public void onClick(DialogInterface dialog,
                           int whichButton) {
              long id = Long.parseLong(entrada.getText().toString());
              Intent i = new Intent(MainActivity.this,
                         VistaLugar.class);
              i.putExtra("id",id);
              startActivity(i);
           }
           })
          .setNegativeButton("Cancelar",null)
          .show();
    }

    public boolean onOptionsItemSelected(MenuItem item){
        int id = item.getItemId();
        if (id == R.id.config){
            return true;
        }
        if (id == R.id.buscar){
            lanzarVistaLugar(null);
            return true;
        }
        if (id == R.id.about){
            lanzarAcercaDe(null);
        }
        return super.onOptionsItemSelected(item);
    }
}

Y si probamos nuestra app ahora deberemos tener un resultado como se ve en el siguiente video

Como pueden ver ahora nuestra app, tiene un inicio mas bonito porque nos muestra los lugares almacenados con una breve descripcion, tambien podemos abrirlos, editarlos y borrarlos como antes, tambien podemos buscarlos y tenemos el acerca de. Como se ve esta app ya esta tomando mas forma.

Anuncios

Hoy hemos visto como trabaja una vista ListView, su practicidad, como implementarla en nuestra app y como permitirle capturar el evento click para poder utilizar nuestro ListView. Espero les haya sido util, sigueme en Twitter, Facebook o Google+ para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00