Ratio: 0 / 5

Inicio desactivadoInicio desactivadoInicio desactivadoInicio desactivadoInicio desactivado
 

En esta segunda parte, comenzamos a trabajar en nuestra app y las funcionalidades básicas. En la sección adjuntos, podemos bajar el proyecto exportado con lo que realizaremos en esta segunda parte de la serie de artículos.

Artículo anterior: Android: Listview con búsqueda con SearchView + PHP + MySQL + Imágenes + Cache (parte 1)

Creamos un nuevo proyecto, con los valores por defecto que nos propone ADT, excepto los siguiente valores : sdk minimo 11 y los siguientes nombres de proyecto

Como primer paso, necesitaremos editar los permisos para nuestra app para que pueda acceder a internet. En AndroidManifest.xml

...
...
<uses-sdk android:minSdkVersion="11"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
...
...

Y agregamos/editamos algunas strings que necesitaremos en nuestro proyecto.

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="app_label">ListViewPHPMySQL2</string>
   <string name="app_name">ListViewPHPMySQL2</string>
   <string name="hello_world">Hello world!</string>
   <string name="action_settings">Settings</string>
   <string name="str_buscar">Buscar &#8230;</string>
   <string name="str_Cancelar">Cancelar</string>
   <string name="str_ComidaTitulo">Título comida</string>
   <string name="str_Categoria">Categoría</string>
   <string name="str_descripcion">Descripción</string>
   <string name="str_ContentDescription">Imagen</string>
   <string name="str_idComida">id</string>
   <string name="str_precio">precio</string>
</resources>

Bajamos los siguientes archivos y los importamos a la carpeta drawable.

 


estrella_llena.png

estrella_vacia.gif

nodisponible.png

Editamos el layout de manera de agregar lo básico de nuestra aplicación. En este punto sólo agregaremos un spinner para hacer el filtrado por categorías y el ListView donde mostraremos los datos.


fragment_main.xml

<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/LinearLayout1"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   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="ar.com.probandocosas.listviewphpmysql2.MainActivity$PlaceholderFragment" >
   <Spinner
      android:id="@+id/spin_categoria"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />
   <ListView
      android:id="@+id/lv_comidas"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" >
   </ListView>
</LinearLayout>

Ahora crearemos el layout para nuestro ListView. Tendremos TextView para mostrar datos varios de cada comida que ofrecemos, una imagen y dentro de un LinearLayout, la calificación que obtendremos de nuestra base de datos.


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/RelativeLayout1"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical" >
   <ImageView
      android:id="@+id/imgComida"
      android:layout_width="75dip"
      android:layout_height="75dip"
      android:layout_alignParentLeft="true"
      android:layout_alignParentTop="true"
      android:layout_marginLeft="3dp"
      android:layout_marginTop="3dp"
      android:contentDescription="@string/str_ContentDescription"
      android:src="@drawable/nodisponible" />
   <TextView
      android:id="@+id/txtvw_idComida"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignTop="@id/imgComida"
      android:layout_marginLeft="3dp"
      android:layout_toRightOf="@id/imgComida"
      android:text="@string/str_idComida"
      android:textSize="22sp" />
   <TextView
      android:id="@+id/txtvw_ComidaTitulo"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignTop="@id/imgComida"
      android:layout_marginLeft="3dp"
      android:layout_toRightOf="@id/txtvw_idComida"
      android:text="@string/str_ComidaTitulo"
      android:textSize="22sp" />
   <LinearLayout
      android:id="@+id/Calificacion"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_below="@id/txtvw_ComidaTitulo"
      android:layout_marginLeft="5dp"
      android:layout_toRightOf="@id/imgComida"
      android:orientation="horizontal" >
   </LinearLayout>
   <TextView
      android:id="@+id/txtvw_precio"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentRight="true"
      android:layout_below="@id/txtvw_ComidaTitulo"
      android:layout_marginRight="3dp"
      android:text="@string/str_precio"
      android:textStyle="bold" />
   <TextView
      android:id="@+id/txtvw_categoria"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentRight="true"
      android:layout_below="@id/txtvw_precio"
      android:layout_marginRight="3dp"
      android:text="@string/str_Categoria"
      android:textStyle="bold" />
   <TextView
      android:id="@+id/txtvw_descripcion"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentRight="true"
      android:layout_below="@id/txtvw_categoria"
      android:layout_marginRight="3dp"
      android:text="@string/str_descripcion" />
</RelativeLayout>

Se vería de la siguiente manera

Comenzamos trabajando ya en el código.

Definimos variables que utilizaremos luego.


MainActivity.java

...
...
public PlaceholderFragment() {
}
   ListView lvComidas;
   Spinner spCategorias;
   List<String> listaCategorias;
...
...

Proseguimos inicializando nuestro Spinner con las categorías. Para simplificar este artículo, la posición de los ítems en el spinner será igual al id de la categoría en la base de datos. Es decir, en la posición 0, para no filtrar por categorías, 1 para pastas, 2 para postres, etc

...
...
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
lvComidas = (ListView) rootView.findViewById(R.id.lv_comidas);
spCategorias = (Spinner) rootView.findViewById(R.id.spin_categoria);
inicializar();
...
...
public void inicializar() {
   // Definimos las categorías para el spinner
   listaCategorias = new ArrayList<String>();
   listaCategorias.add(0, "Todos");
   listaCategorias.add(1, "Pastas");
   listaCategorias.add(2, "Postres");
   listaCategorias.add(3, "Carnes");
   listaCategorias.add(4, "Bebidas");
   listaCategorias.add(5, "Minutas");
   ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>( getActivity(),
      android.R.layout.simple_spinner_item, listaCategorias);
   spCategorias.setAdapter(spinnerAdapter);
}
...
...

En este punto, si ejecutamos nuestra app, se ve de la siguiente manera.

Proseguimos ahora con llenar los datos del ListView.

El primer paso es crear la clase objeto para nuestros items


Comida.java


public class Comida {
   private int calificacion;
   private int id_comida;
   private String comida;
   private String descripcion;
   private String urlimg;
   private String precio;
   private String categoria;
   public int getCalificacion() {
      return calificacion;
   }
   public void setCalificacion(int calificacion) {
      this.calificacion = calificacion;
   }
   public int getId_comida() {
      return id_comida;
   }
   public void setId_comida(int id_comida) {
      this.id_comida = id_comida;
   }
   public String getDescripcion() {
      return descripcion;
   }
   public void setDescripcion(String descripcion) {
      this.descripcion = descripcion;
   }
   public String getUrlimg() {
      return urlimg;
   }
   public void setUrlimg(String urlimg) {
      this.urlimg = urlimg;
   }
   public String getPrecio() {
      return precio;
   }
   public void setPrecio(String precio) {
      this.precio = precio;
   }
   public String getCategoria() {
      return categoria;
   }
   public void setCategoria(String categoria) {
      this.categoria = categoria;
   }
   public String getComida() {
      return comida;
   }
   public void setComida(String comida) {
      this.comida = comida;
   }
}

Ahora crearemos el adaptador para nuestro ListView. Nuestro adaptador usará el layout lv_custom.xml que generamos previamente. Tendra definido en el constructor un parámetro que es el objeto que será un array del objeto Comida que acabamos de generar.


ComidaAdaptador.java



public class ComidaAdaptador extends ArrayAdapter<Comida> {
   private List<Comida> items;
   public ComidaAdaptador(Context context, List<Comida> items) {
      super(context, R.layout.lv_layout, items); this.items = items;
   }
   @Override
   public int getCount() {
      return items.size();
   }
   @Override
   public View getView(int position, View convertView, ViewGroup parent) {
      View v = convertView;
      if (v == null) {
         LayoutInflater li = LayoutInflater.from(getContext());
         v = li.inflate(R.layout.lv_layout, null);
      }
      Comida com = items.get(position);
      if (com != null) {
         // calificacion
         LinearLayout califica = (LinearLayout) v
          .findViewById(R.id.Calificacion);
         if (califica != null && califica.getChildCount() == 0) {
            // La calificacion máxima es de 5 estrellas
            for (int i = 1; i <= 5; i++) {
               ImageView estrella = new ImageView(getContext());
               if (i <= com.getCalificacion()) {
                  estrella.setImageDrawable(getContext().getResources()
                   .getDrawable(R.drawable.estrella_llena));
               } else {
                  estrella.setImageDrawable(getContext().getResources()
                   .getDrawable(R.drawable.estrella_vacia));
               }
               califica.addView(estrella);
            }
         }
         // id_comida
         TextView txtvw_idcomida = (TextView) v .findViewById(R.id.txtvw_idComida);
         txtvw_idcomida.setText(String.valueOf(com.getId_comida()) + ")");
         // comida
         TextView txtvw_comida = (TextView) v .findViewById(R.id.txtvw_ComidaTitulo);
         txtvw_comida.setText(com.getComida());
         // descripcion
         TextView txtvw_descripcion = (TextView) v .findViewById(R.id.txtvw_descripcion);
         txtvw_descripcion.setText(com.getDescripcion());
         // urlimg ----- ESTO LO RESOLVEMOS LUEGO
         // precio
         TextView txtvw_precio = (TextView) v .findViewById(R.id.txtvw_precio);
         txtvw_precio.setText("$" + com.getPrecio());
         // categoria
         TextView txtvw_categoria = (TextView) v .findViewById(R.id.txtvw_categoria);
         txtvw_categoria.setText(com.getCategoria());
      }
      return v;
   }
}

Nos encargamos ahora de la clase que realizará el trabajo de traer los datos desde PHP/MySQL. La llamaremos TraerDatos.java


TraerDatos.java

public class TraerDatos extends AsyncTask<String, Void, String> {
   private final TraerDatosListener listener;
   private String msg;
   public TraerDatos(TraerDatosListener listener) {
      this.listener = listener;
   }
   @Override
   protected String doInBackground(String... params) {
      // Obtener los parámetros de busqueda
      String categoria = params[0];
      String cadenaABuscar = params[1];
      String url = Uri.parse("http://192.168.5.141/comidas/consultas.php")
         .buildUpon().appendQueryParameter("comida", cadenaABuscar)
         .appendQueryParameter("categoria", categoria).build()
         .toString();
      try {
         // Crear conexión http
         HttpClient client = new DefaultHttpClient();
         HttpGet httpget = new HttpGet(url);
         // Conectarse
         HttpResponse response = client.execute(httpget);
         // Obtener la respuesta
         HttpEntity entity = response.getEntity();
         if (entity == null) {
            msg = "Sin respuesta desde el server";
            return null;
         }
         // Obtener el contenido de la respuesta y convertirlo a una cadena
         // json
         InputStream is = entity.getContent();
         return streamToString(is);
      } catch (IOException e) {
         msg = "Problemas en la conexión";
      }
      return null;
   }
   @Override
   protected void onPostExecute(String sJson) {
      if (sJson == null) {
         if (listener != null) listener.onFetchFailure(msg);
         return;
      }
       try {
         // Convertir la cadena json en un array json
         JSONArray aJson = new JSONArray(sJson);
         // Crear la lista
         Comida List<Comida> coms = new ArrayList<Comida>();
         for (int i = 0; i < aJson.length(); i++) {
            JSONObject json = aJson.getJSONObject(i);
            Comida com = new Comida();
            // calificacion
            com.setCalificacion(Integer.parseInt(json
               .getString("calificacion")));
            // id_comida
            com.setId_comida(Integer.parseInt(json.getString("id_comida")));
            // comida
            com.setComida(new String(json.getString("comida").getBytes("ISO-8859-1"), "UTF-8"));
            // descripcion
            com.setDescripcion(new String(json.getString("descripcion").getBytes("ISO-8859-1"), "UTF-8"));
            // imagen
            com.setUrlimg(json.getString("imagen"));
            // precio
            com.setPrecio(json.getString("precio"));
            // categoria
            com.setCategoria(json.getString("categoria"));
            // Agregar a la lista
            coms.add(com); }
            // Notificar al listener que ya están todos lo datos
            if (listener != null) listener.onFetchComplete(coms);
         } catch (JSONException e) {
            msg = "Respuesta inválida";
            System.out.println("**** Error JSON" + e.getMessage());
            if (listener != null) listener.onFetchFailure(msg);
             return;
         } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }
      }
   /**
   * Esta función convierte la respuesta en una cadena
   *
   * @param es la string que obtuvimos como respuesta
   * @return devuelve una string json
   * @throws IOException
   */
   public String streamToString(final InputStream is) throws IOException {
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      StringBuilder sb = new StringBuilder();
      String line = null;
      try {
         while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
         }
      } catch (IOException e) {
         throw e;
      } finally {
         try {
            is.close();
         } catch (IOException e) {
            throw e;
         }
      }
   return sb.toString();
   }
}

Creamos ahora la interfaz que usaremos para notificar al listview que se terminaron de bajar los datos


TraerDatosListener.java



public interface TraerDatosListener {
   public void onFetchComplete(List<Comida> data);
   public void onFetchFailure(String msg);
}

Y la implementamos en nuestra Activity principal


MainActivity.java
...
...
public static class PlaceholderFragment extends Fragment implements TraerDatosListener{
...
...

      @Override
      public void onFetchComplete(List<Comida> data) {
         // TODO Auto-generated method stub
         // setear un nuevo adaptador a nuestro listview
         lvComidas.setAdapter(new ComidaAdaptador(getActivity(), data));
      }
      @Override
      public void onFetchFailure(String msg) {
         // TODO Auto-generated method stub
         Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show();
      }
   }
}

Y finalmente, cuando inicializamos nuestra app, realizamos una consulta, sin parámetros de filtrado


public void inicializar() {
...
...
   // Hacemos la consulta inicial con los valores nulos
   TraerDatos datos = new TraerDatos(this);
   datos.execute("", "");
}

En este punto, podemos ejecutar nuestra app que se verá similar a esto

En la sección adjuntos, se puede bajar el proyecto completo exportado desde ADT en el punto actual de desarrollo de esta serie de artículos.

La tercera parte: http://joomla.probando-cosas.com.ar/index.php/item/254-android-listview-con-busqueda-con-searchview-php-mysql-imagenes-cache-parte-3

 

FacebookMySpaceTwitterDiggDeliciousStumbleuponGoogle BookmarksRedditNewsvineTechnoratiLinkedinRSS FeedPinterest
Pin It