En esta entrada veremos como crear CardView
s personalizados, para ello solo nos enfocaremos en crear la vista y no trabajaremos en ningún otro componente de la aplicación para Android (como la actividad) ni nada por el estilo, la idea es centrarnos en cómo crear un diseño completo para un listado que pueda contar con varias opciones, algo de información básica y un campo de destacado.
Los CardView son excelentes contenedores para mostrar datos de manera resumida y detallada; son muy empleados para crear los items de los listados mediante los Lo nuevo del Material Design: Los RecyclerView.
Como puedes ver en la imagen promocional, existen ciertos elementos alineados de una manera que a primera vista puede no resultar tan fácil de deducir su organización pero que en realidad no es compleja su construcción.
Resumiendo un poco e indicando cada uno de los elementos en la siguiente imagen de manera descendente, nuestra vista contará con 3 secciones principales:
- Sección destacada.
- El
CardView
como tal. - La sección de opciones.
¿Para que sirve un CardView
?
Los CardView
son un elemento de diseño que cuentan con un diseño similar a un widget de manera nativa con el típico sombreado y bordes redondeados y son muy empleados en conjunto con los RecicleView que ya hemos tratado en una anterior entrada.
Como se ha mencionado anteriormente, contiene una seria de propiedades unicas como el redondeo de los border, una propiedad para cambiar el color de fondo etc; puedes consultar la documentación oficial para más información Crear listas y tarjetas.
Creando nuestro CardView
Finalmente se procede a detallar los pasos necesarios para crear el CardView
anterior; como contenedor padre al CardView
definiremos un RelativeLayout
; la razón, su facilidad para alinear elementos con contenido flotantes en prácticamente cualquier posición.
Dentro del mismo contenedor RelativeLayout
definiremos 3 bloques más:
- Otro contenedor padre dentro del
CardView
que será unRelativeLayout
para el manejo del margen superior. - Otro contenedor para la sección destacada del
CardView
(TextView
) que permitirá alinear elTextView
de manera central. - Un
LinearLayout
que contendrá algunos botones flotantes con el propósito del manejo de la sección de opciones permitidas pora el usuario.
Creando la sección de opciones
En este bloque definimos un margen para dar el típico efecto de que la sección destacada sobresale del CardView
(mitad dentro del contenedor y mitad fuera) y el LinearLayout
con la propiedad android:orientation="horizontal"
permite alinear todos los elementos contenidos dentro del mismo de manera horizontal.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/rlContainer"
android:layout_centerHorizontal="true"
android:layout_marginRight="@dimen/fab_margin"
android:layout_marginTop="-15dp"
android:orientation="horizontal">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/fab_margin"
android:src="@drawable/ic_action_info_outline"
app:fabSize="mini" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabEdit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_edit"
app:fabSize="mini" />
</LinearLayout>
Creando la sección destacada
Ahora crearemos la sección destacada que consta de un TextView
centrado; para ello, el contenedor padre RelativeLayout
debe ocupar todo el ancho y en conjunto con la propiedad android:layout_centerHorizontal="true"
permite alinear el TextView
en el medio, de aquí le ponemos un padding de 10dp
para hacerlo el globo un poco más vistoso y un margen que nos permite tener centrado nuestra sección destacada.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="25dp">
<TextView
android:id="@+id/tvMount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="@drawable/layout_bg_corner_mount_1"
android:fontFamily="sans-serif-thin"
android:padding="10dp"
android:text="title"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FFFFFF"
android:textSize="25dp" />
</RelativeLayout>
Diseñando el resto del CardView
Ahora lo último que nos falta es crear la sección central y principal de nuestro listado cuyo código no tiene complicación alguna y no necesita mayor información:
<RelativeLayout
android:id="@+id/rlContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_marginLeft="@dimen/space_component3x"
android:layout_marginRight="@dimen/space_component3x"
android:layout_marginTop="0dp">
<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:id="@+id/cvContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/card_detail_mount_margin"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:id="@+id/llContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"
android:padding="@dimen/pad_10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:fontFamily="sans-serif-light"
android:text="title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:fontFamily="sans-serif-light"
android:gravity="right"
android:text="title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:textStyle="bold" />
</RelativeLayout>
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/pad_5dp"
android:layout_marginTop="@dimen/space_component3x"
android:layout_toLeftOf="@+id/tvDate"
android:fontFamily="sans-serif-condensed"
android:text="title"
android:textColor="#FFFFFF"
android:textSize="20dp" />
<TextView
android:id="@+id/tvDirection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:text="title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:textSize="@dimen/abc_text_size_small_material" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/space_big"
android:orientation="vertical" />
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
Finalmente el código completo:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rlFcontainer"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rlContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_marginLeft="@dimen/space_component3x"
android:layout_marginRight="@dimen/space_component3x"
android:layout_marginTop="0dp">
<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:id="@+id/cvContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/card_detail_mount_margin"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:id="@+id/llContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"
android:padding="@dimen/pad_10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:fontFamily="sans-serif-light"
android:text="title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:fontFamily="sans-serif-light"
android:gravity="right"
android:text="title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:textStyle="bold" />
</RelativeLayout>
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/pad_5dp"
android:layout_marginTop="@dimen/space_component3x"
android:layout_toLeftOf="@+id/tvDate"
android:fontFamily="sans-serif-condensed"
android:text="title"
android:textColor="#FFFFFF"
android:textSize="20dp" />
<TextView
android:id="@+id/tvDirection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:text="title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:textSize="@dimen/abc_text_size_small_material" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/space_big"
android:orientation="vertical" />
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/rlContainer"
android:layout_centerHorizontal="true"
android:layout_marginRight="@dimen/fab_margin"
android:layout_marginTop="@dimen/negative_margin_design_fab_size_mini"
android:orientation="horizontal">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/fab_margin"
android:src="@drawable/ic_action_info_outline"
app:fabSize="mini" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabEdit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_edit"
app:fabSize="mini" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/space_component5x">
<TextView
android:id="@+id/tvMount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="@drawable/layout_bg_corner_mount_1"
android:fontFamily="sans-serif-thin"
android:padding="@dimen/space_component2x"
android:text="title"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FFFFFF"
android:textSize="@dimen/card_detail_mount_text_size" />
</RelativeLayout>
</RelativeLayout>
Valores del dimen.xml
- <dimen name="space_component">5dp</dimen>
- <dimen name="space_component2x">10dp</dimen>
- <dimen name="space_component3x">15dp</dimen>
- <dimen name="space_component5x">25dp</dimen>
- <dimen name="fab_margin">10dp</dimen>
- <dimen name="space_big">20dp</dimen>
- <dimen name="card_detail_mount_margin">45dp</dimen>
- <dimen name="card_detail_mount_text_size">25dp</dimen>
Recursos y colores
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorFive"/>
<stroke android:width="3dp" android:color="@color/colorFive" />
<corners android:radius="30dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
<color name="colorFive">#F7C51E</color>
(Opcional) Tipografías en Android
Para darle un poco de estilo, y como puedes ver el las secciones de código presentado anteriormente, se cambió la tipografía cuando se consideraba hacerlo; las siguientes tipos de tipografía que podemos emplear en Android:
android:fontFamily="sans-serif" // roboto regular
android:fontFamily="sans-serif-light" // roboto light
android:fontFamily="sans-serif-condensed" // roboto condensed
android:fontFamily="sans-serif-black" // roboto black
android:fontFamily="sans-serif-thin" // roboto thin (android 4.2)
android:fontFamily="sans-serif-medium" // roboto medium (android 5.0)
Representados en la siguiente imagen:
Puedes ver la explicación completa en el siguiente enlace: service. How to change fontFamily of TextView in Android.
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter