Google I/O 2014 será recordado por ser uno de los más android-céntricos de todos, no solo presentando novedades a nivel de móviles como estábamos acostumbrados, si no incursionando en campos nuevos para la plataforma como: wearables y automóviles. Además, por primera vez, una versión Developer Preview llamada: Android L, para que podamos experimentar con el SDK y generar el mayor feedback posible, antes del lanzamiento oficial en dispositivos.
Android L es uno de los cambios más grandes que a tenido Android en mucho tiempo, lo que se siente como una verdadera actualización más que una extensión. Dichos cambios a grosso modo se dividen en:
- Una nueva UI:
Se estrena Material Design, por lo que ahora, tanto el operativo, como las aplicaciones deben de seguir los principios del nuevo lenguaje de diseño de Google. Material Design contiene todos los elementos a nivel de UI, movimiento e interacción, para generar UX nunca vista en la plataforma. Además se agregan 2 nuevos widgets:
- CardView:
Nos permite agrupar casi cualquier tipo y número de elementos en una vista que, al final, resulta un tipo “Tarjeta” como lo visto en Google Now. Al venir de la librería de soporte, este nuevo widget funciona igual en versiones anteriores a L.
RecyclerView:
Una actualización de ListView. Esta vez es mas fácil de usar, optimiza recursos, y ofrece animaciones predeterminadas. Útil para su uso en colecciones dinámicas (ListView y GridView).
Haciendo que todo fluya como la seda, sin embargo, las aplicaciones ahora requieren más espacio de almacenamiento en tu dispositivo, pero velocidad y optimización de batería lo valen.
Nuevo Runtime:
ART (Android RunTime) se vuelve la máquina virtual por defecto sustituyendo a Dalvik, incluye tres importantes cambios:
- Compilación por delante del tiempo.
Mejora del recolector de basura.
Mejora las opciones de debug.
Renovado Sistema de Notificaciones:
Las notificaciones es algo que a tenido Android desde su primera versión, ahora no solo siguen los principios de Material Design, sino que, tenemos disponibles nuevos valores para ellas:
- Visibilidad privada:
Muestra información básica, como el icono de la notificación, pero oculta el contenido completo de la notificación.
Visibilidad publica:
Muestra el contenido completo de la notificación.
Visibilidad secreta:
No muestra más que el icono de la notificación en la barra de estado.
Incremento de Eficiencia:
Sumado a todo, se agregaron elementos que ayudan a monitorear nuestra aplicación y consultar varios estados de ella, tal es el caso de Project Volta, un API capaz de mostrarnos el consumo de energía a nivel de aplicación, así podemos parar o matar los procesos que están consumiendo mas recursos de los necesarios o que no es necesario que se estén ejecutando.
Tu primera aplicación en Android L
Ahora, vamos a crear una aplicación con algunas de las novedades de Android L. La aplicación simulará un feed de los cursos de Mejorando.la. Usaremos los dos nuevos widgets: Card View y Recycler View, ademas de un Float Button, todo siguiendo los principios del nuevo Material Design. Es complicado hacer un tutorial paso a paso de ciertos temas extras que contiene la aplicación y solo hare énfasis en los temas nuevos de Android L.
El código se encuentra disponible en: https://github.com/thespianartist/FeedCursosMejorandola
- Requerimientos
Android Studio Beta (Su version mas reciente)
Dispositivo corriendo Android L o en su defecto crear una Máquina Virtual con dicho nivel de API.
Con el SDK Manager tener instalados:
- Android SDK Platform-Tools 20
Android SDK Build-Tools 20
SDK Platform Android L (API 20, L Preview) y cualquier System Image si se requiere una máquina virtual.
Android Support Library 20
Android Support Repository 6
Ya verificando que se tienen todo instalado, podremos crear un nuevo proyecto “Hola mundo” con ese nivel de API para comprobar que todo esta bien, el ejemplo que usaremos, solo contiene una actividad con un fragmento en ella.
Declarando el tema: Material Design
Lo único que necesitamos para que una aplicación tenga aspecto Material Design es el configurarlo como tema. Si observamos los archivos de styles.xml, contenidos en las diferentes carpetas de values, en la carpeta donde se guardan todos los recursos no java res nos daremos cuenta que tenemos disponible un nuevo tema parent llamado: Material.
Material tiene las mismas variaciones de Holo (como Light con Dark ActionBar) pero ademas, nos ayuda a personalizar los colores de la UI de manera más sencilla. De inmediato podemos asignar 3 campos al tema: colorPrimary, colorPrimaryDark y accent.
colorPrimary debe ser el color característico de la marca a la que pertenece la aplicación, colorPrimaryDark su variación un poco más oscura pero nada ajeno al color primario original y por último accent será un color que resalte sobre toda nuestra aplicación y lo hace un contraste interesante, para más información sobre los colores a usar visita http://www.google.com/design/spec/style/color.html
Ahora también podemos declarar algunos valores globales de color para que sean utilizados en cualquier parte de la aplicación gracias a la etiqueta<color>. En el ejemplo configuramos los 3 valores de color de personalización de tema, ademas de un cuarto color que corresponde al color que usaremos en el Float Button. La imagen de abajo describe la personalización completa de la aplicación en styles.xml:
Código :
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar"> <item name="android:colorPrimary">@color/primary</item> <!-- darker variant of colorPrimary (for status bar, contextual app bars) --> <item name="android:colorPrimaryDark">@color/primary_dark</item> <!-- theme UI controls like checkboxes and text fields --> <item name="android:colorAccent">@color/accent</item> </style> <color name="primary_dark">#056f00</color> <color name="primary">#259b24</color> <color name="accent">#ffea00</color> <color name="acent_button">#ffff00</color> </resources>
Uso de CardView
Para usar los dos nuevos widgets necesitamos compilar las dependencias correspondientes, estas se encuentra dentro de el conjunto de librerías de soporte y pueden ser incluidas de la siguiente manera, en el archivo build.gradle de la raíz del directorio app:
El uso de CardView es muy sencillo, al final se trata de un widget que otorga dicho UI a lo que se encuentre entre el. Uno de sus atributos es el poder asignar bordes redondeados a la carta: card_view:cardCornerRadius="2dp". Ademas existe un atributo android:foreground="?android:attr/selectableItemBackground" para que la tarjeta obtenga la animación característica de Material Design al hacer clic sobre ella. La vista que tenemos como preview es la de un curso sin datos, a esto lo llamaremos itemLayout (row.xml) y será usado para nuestro RecyclerView.
En el ejemplo, cada curso se muestra como tarjeta, dicho curso esta compuesto de un ImageView y 2 TextView acomodados mediante un RelativeLayout. Lo único que falta para que dicho UI tome forma de tarjeta es, como mencione anteriormente, colocarlos entre las etiquetas <android.support.v7.widget.CardView> con la configuración que usted quiera. En el ejemplo se consideró de la siguiente manera:
Código :
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:foreground="?android:attr/selectableItemBackground" android:clickable="true" android:layout_margin="10dp" android:id="@+id/card_view" android:layout_width="wrap_content" android:layout_height="wrap_content" card_view:cardCornerRadius="2dp"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:src="@drawable/backend" android:layout_width="150dp" android:layout_height="150dp" android:scaleType="centerCrop" android:id="@+id/image"/> <TextView android:paddingLeft="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Large Text" android:id="@+id/name" android:layout_alignParentTop="true" android:layout_toEndOf="@+id/image" /> <TextView android:paddingLeft="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text" android:id="@+id/description" android:layout_below="@+id/name" android:layout_toEndOf="@+id/image" /> </RelativeLayout> </android.support.v7.widget.CardView>
Uso de RecyclerView
RecyclerView es una mejora de lo antes visto en ListView o GridView. Es un widget que despliega vistas que comparten la misma estructura de vista de los datos, ósea , son vistas que se “repiten” en forma, pero no en información.
RecyclerView nos proporciona unLayoutManager que es el encargado de asignar el acomodo de los elementos (Grid o Linear), aunque por el momento solo esta disponible Linear (como lista). Para que esto funcione necesitamos construir nuestro Adapter y a su vez, el Adapter necesita de un Dataset, ósea un conjunto (arreglo) de objetos.
El Dataset requiere de un arreglo de objetos a mostrar. Regularmente un objeto se crea mediante algo llamado POJO (Plain Old Java Object) y dicho POJO contiene todas las características del objeto. En este caso, el Objeto es cada curso y el curso contiene: ID, name y description. Ya abran notado que estos son los campos que se tienen para llenar cada elemento dentro del CardView, el Dataset de esta aplicación es un arreglo de objetos tipo curso. Este dataset es construido a partir de un JSON local llamado “cursos.json”, el parseo y manejo se encuentra en una clase llamada ReadLocalJSON por si tienen inquietud de como consumir un archivo JSON local.
Código :
public class Course { private Integer id; private String name; private String description; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } }
Crear el Adapter no es tan complicado, lo primero que debemos hacer es crear una clase (en la aplicación se llama CoursesAdapter) que extienda de RecyclerView.Adapter<CoursesAdapter.ViewHolder> e Implementar los métodos requeridos. El constructor recibe dos parámetros, uno es el Dataset (Arreglo de objetos del tipo Curso) y el otro es el ItemLayout (es el layout que creamos con el CardView y describe cada curso)
Código :
private ArrayList<Course> courses; private int itemLayout; public CoursesAdapter(ArrayList<Course> data, int itemLayout){ courses = data; this.itemLayout = itemLayout; }
La clase interna ViewHolder que extiende de RecyclerView.ViewHolder contiene todos los llamados a los widgets contenidos en el ItemLayout (compuesto de un ImageView y 2 TextView), por lo que se garantiza que el llamado es solo una vez, haciendo que consuma menos recursos a nivel de batería y procesamiento. Anteriormente un ViewHolder era una buena práctica, ahora es algo obligatorio. Ademas se implementa un AdapterView.OnClickListener para que cada elemento en el listado tenga un evento OnClick, por el momento solo muestra un pequeño mensaje.
Código :
public static class ViewHolder extends RecyclerView.ViewHolder implements AdapterView.OnClickListener { public ImageView image; public TextView name; public TextView description; public ViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); image = (ImageView) itemView.findViewById(R.id.image); name = (TextView) itemView.findViewById(R.id.name); description = (TextView) itemView.findViewById(R.id.description); } @Override public void onClick(View view) { Toast.makeText(view.getContext(),"OnItemClick :D", Toast.LENGTH_SHORT).show(); } }
El método onCreateViewHolder se encarga de inflar la vista del ItemLayout y el método onBindViewHolder es el encargado de pasar la información del Dataset a sus respectivos lugares en el ItemLayout. Ademas de recordarle al viewHolder el estado actual de los elementos del ItemLayout. Al final el método getItemCount nos permite conocer el tamaño o cantidad de elementos que contiene nuestro RecyclerView que es el mismo que el tamaño deldataset. Y listo, todo lo anterior en conjunto crea nuestro Adapter para poder usar nuestro RecyclerView.
Código :
@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(itemLayout, viewGroup, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder viewHolder, int position) { Course course = courses.get(position); viewHolder.name.setText(course.getName()); viewHolder.description.setText(course.getDescription()); switch (course.getId()){ case 1: viewHolder.image.setImageResource(R.drawable.disenio); break; case 2: viewHolder.image.setImageResource(R.drawable.android); break; case 3: viewHolder.image.setImageResource(R.drawable.swift); break; case 4: viewHolder.image.setImageResource(R.drawable.backend); break; } viewHolder.itemView.setTag(course); } @Override public int getItemCount() { return courses.size(); }
Hasta este punto no hemos creado más que lo necesario para que el UI principal funcione (recordar que solo tenemos una Actividad con un Fragmento en ella). La vista del fragmento (cursos_fragment.xml) contiene un widget del tipo <android.support.v7.widget.RecyclerView> ademas de un <ImageButton> (que es el Float Button con la explicación más adelante). La clase onCreateView del Fragmento es la encargada de preparar nuestra vista, mientras que en onActivityCreated hacemos el llamado a todo aquello que usaremos para completar dicha vista, en este punto es donde hacemos el llamado a recyclerView, le seteamos el adapter que creamos (CoursesAdapter que para construirlo recibe un el dataset y la ItemLayout) y le indicamos al LayoutManager que sea un LinearLayoutManager (vista de lista).
Código :
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <android.support.v7.widget.RecyclerView android:scrollbars="vertical" android:id="@+id/my_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageButton android:id="@+id/fab_1" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_width="@dimen/fab_size" android:layout_height="@dimen/fab_size" android:background="@drawable/riple" android:layout_marginBottom="16dp" android:layout_marginRight="16dp" android:stateListAnimator="@anim/anim" android:src="@drawable/reply" android:elevation="10dp" /> </RelativeLayout>
Código :
ArrayList<Course> courses; ReadLocalJSON readLocalJSON = new ReadLocalJSON(); courses = readLocalJSON.getCourses(getActivity()); RecyclerView recyclerView = (RecyclerView) getActivity().findViewById(R.id.my_recycler_view); recyclerView.setHasFixedSize(true); recyclerView.setAdapter(new CoursesAdapter(courses, R.layout.row)); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.setItemAnimator(new DefaultItemAnimator());
Creando un Float Button
Lo último de este ejemplo es crear el Float Button, como podemos ver en la vista del fragmento se trata de un ImageButton (src="@drawable/reply" , que es la imagen de la flecha) con android:background="@drawable/riple", el ripple (riple.xml contenido en la carpeta drawable) es el que crea el un fondo background shape oval, siendo el color el declarado en el tema en un inicio: @color/acent_button, el tamaño del shape se encuentra declarado en cada uno de los archivos dimens.xml en las carpetas de values, contiene un android:elevation="10dp", ósea que va 10dp arriba del eje Z, lo cual, lo coloca por delante de cualquier cosa que muestre RecyclerView.
Ademas (aunque no se pueda ver en este ejemplo) preparamos una animación de translationZ declarada en anim.xml en la carpeta anim, esta solo será visible cuando se pasa de una actividad a otra, por el momento no lo usaremos pero así es como se declara.
Código :
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight"> <item> <shape android:shape="oval"> <solid android:color="@color/acent_button"/> </shape> </item> </ripple>
Código :
<resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> <dimen name="spacing_xsmall">2dp</dimen> <dimen name="fab_size">56dp</dimen> <dimen name="button_elevation">4dp</dimen> <dimen name="button_press_elevation">4dp</dimen> </resources>
Código :
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true" android:state_pressed="true"> <objectAnimator android:duration="500" android:propertyName="translationZ" android:valueFrom="@dimen/button_elevation" android:valueTo="@dimen/button_press_elevation" android:valueType="floatType" /> </item> <item> <objectAnimator android:duration="500" android:propertyName="translationZ" android:valueFrom="@dimen/button_press_elevation" android:valueTo="@dimen/button_elevation" android:valueType="floatType" /> </item> </selector>
Ya por último en la clase del fragmento debemos declarar los Outline (Las sombras que hace ver el botón por estar mas arriba del eje Z).
Código :
int size = getResources().getDimensionPixelSize(R.dimen.fab_size); Outline outline = new Outline(); outline.setOval(0, 0, size, size); ImageButton imageButton = (ImageButton) getActivity().findViewById(R.id.fab_1); imageButton.setOutline(outline); imageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getActivity(),"Mejorando.la: Aprende a crear el futuro de la Web", Toast.LENGTH_LONG).show(); } }); }
Listo!, eso es a grosso modo una aplicación que usa Material Design ademas de los nuevos widgets, no duden en preguntar o demostrar alguna inquietud sobre el tema, quedo a sus ordenes por cualquier medio: @thespianartist
¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.
Por Andyg el 14 de Agosto de 2014
Por Julian Moreno el 14 de Agosto de 2014
Informo que no puedo ver las imágenes porque al parecer tienen el hipervínculo roto.
¡Salduos!
Por Androide el 19 de Septiembre de 2014
Por notch el 23 de Septiembre de 2014
Por Jose el 26 de Septiembre de 2014
Por Amarante el 26 de Septiembre de 2014
Por thespianartist el 29 de Septiembre de 2014
Amarante-blog :
Para programar nativo por el momento es la única opción, pero como comente un día, se que Java no es el lenguaje mas "elegante" de todo y que es estrictamente tipado y estructurado, pero, ¿Ve todas las posibilidades que te estas perdiendo?, se que unos tenemos un lenguaje preferido y te comento que Java tampoco es mi favorito, pero el ver una aplicación correr en mis dispositivos vale mucho la pena. Espero que pronto Google piense en cambiar de lenguaje como lo hizo Apple con Objective-C. Pero por el momento toca el implementar con Java y especificamente con el framework Dalvik que lo hace mas amigable
Por marcoabarrios el 04 de Octubre de 2014
Por mani el 22 de Octubre de 2014
Por thespianartist el 22 de Octubre de 2014
marcoabarrios :
Ve al repositorio del codigo, se encuentra en el layout del Activity
Por Damian el 30 de Octubre de 2014
Por juvasquezg el 22 de Enero de 2015
Por Cubel el 18 de Febrero de 2015
Lo digo porque estoy empezando con estoy y voy un poco liado. Me sale algún error que otro y supongo que es porque algo no lo he colocado donde toca y por eso me gustaría ver el código entero.
Por Hugo el 21 de Febrero de 2015