ayer publique la primera versión de como hacer mensajes Toast personalizados. En esa publicación indicaba que había varias cosas que no sabia como solucionar, pues nada, hoy pongo la solución a estos problemas, espero que os guste.
Para realizar los mensajes toast personalizados que yo estaba buscando, debemos realizar los siguientes pasos:
1- Crear el layout (vista) que luego asignaremos al Toast.
2- Crear el xml (borde) donde indicaremos como tienen que ser los bordes para e mensaje.
3- Introduciremos el código Java necesario para cargar la vista y poder poner el mensaje que queramos en cada momento.
4- Llevaremos todo esto a una clase static, para compartir el mensaje en todo momento, y así tener un control sobre él para hacer que desaparezca el mensaje cuando creamos oportuno.
Este ultimo paso lo considero indispensable, ya que sino nos pasara que pulsaremos multiples veces sobre un botón, y estaremos viendo dicho Toast durante un rato hasta que se muestren todos. Para evitar que pueda pasar esto, y para evitar que el Toast se siga mostrando incluso después de abandonar la pantalla donde se mostró vamos ha realizar el paso 4.
Este ultimo paso es opcional, ya que aunque yo lo considero útil no tiene por que servir o gustar a todo el mundo.
PASO 1:
Crearemos el layout que sera la vista tal y como queremos que se muestre en los mensajes.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/toast_layout_root" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:layout_marginLeft="20px" android:layout_marginRight="20px" android:background="#0FFF" android:orientation="horizontal" android:padding="20dp" android:gravity="center"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@drawable/borde" android:orientation="horizontal" > <ImageView android:id="@+id/toastImagen" android:layout_width="58dp" android:layout_height="58dp" android:src="@drawable/icon" android:layout_gravity="center"/> <TextView android:id="@+id/toastText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000" android:gravity="center" android:layout_marginRight="10px" android:layout_marginLeft="10px" android:layout_gravity="center"/> </LinearLayout> </LinearLayout>
Como se puede observar a diferencia de la entrada anterior en este caso la vista esta compuesta por un LinearLayout dentro de otro, esto es necesario si queremos que nuestro mensaje tenga un margen o separación entre los laterales del terminal y él.
El LinearLayout mas externo sera el que cargaremos en la clase java, de ahí que tenga un id. También se puede observar que hemos puesto un background a dicho layout, esto es necesario si queremos que el fondo sea transparente. Y mediante el padding indicamos la distancia que habrá entre el borde del terminal y el mensaje que mostramos.
El LinearLayout mas interior sera el que contendrá el background encargado de hacer el borde y el color del fondo del mensaje.
El resto de componentes es adaptable, ya que en nuestro caso hemos puesto una imagen y un texto, pero se podría modificar y añadir otra clase de objetos.
Ahora seguimos con el paso 2, que es el encargado de crear el borde y el fondo del mensaje.
PASO 2:
En este paso creamos el xml que contendrá el borde y el fondo del mensaje. Para ello crearemos un xml en el directorio res/drawable, el cual tendrá el siguiente código.
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="4dp" android:color="#FAAA" /> <padding android:left="7dp" android:top="7dp" android:right="7dp" android:bottom="7dp" /> <corners android:radius="4dp" /> <solid android:color="#DAAA" /> </shape>
PASO 3:
Ahora pondremos el código necesario para hacer uso de la vista que hemos creado y poder montar nuestros Toast personalizados.
Para ello necesitaremos obtener la vista mediante el siguiente codigo:
LayoutInflater inflater = getLayoutInflater(); View layout = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root));
Mediante este codigo obtenemos la vista, que posteriormente pasaremos al toast con esto:
Toast toast = new Toast(ctx); toast.setView(layout); text = (TextView) vista.findViewById(R.id.toastText); text.setText("texto a mostar"); toast.show();
Ya con esto es suficiente para poder personalizar los mensajes, pero claro para mis desarrollos necesito una vuelta de tuerca mas, ya que con lo que hemos hecho hasta ahora lo que conseguimos es personalizar los mensajes, pero no evitamos que si pulsamos repetidamente un elemento que muestre el toast este se tenga que mostrar tantas veces como pulsaciones hubo, ni evita que si se cambia de ventana mientras se muestra el mensaje, este se siga viendo en la siguiente ventana a la que vayamos.
Para poder solucionar esto yo he realizado el paso 4, a ver que os parece.
PASO 4:
Para realizar este paso crearemos una clase static, la cual tendrá el toast que generaremos al iniciar la aplicación, la vista, la cual cargaremos nada mas empezar, y algunos objetos mas.
El código de la clase static será:
package es.atndroider.qui.util; import android.content.Context; import android.graphics.Paint.Join; import android.view.Gravity; import android.view.View; import android.widget.TextView; import android.widget.Toast; import es.atndroider.qui.R; public class MensajeToast { private static Toast toast = null; private static Context ctx = null; private static View vista = null; private static TextView text = null; public static void prepararVista(Context c, View view){ if (ctx==null) ctx = c; if (vista==null) vista=view; text = (TextView) vista.findViewById(R.id.toastText); toast = Toast.makeText(ctx, "", Toast.LENGTH_LONG); toast.setView(vista); } public static void mostrarMensajeLargo(int mensaje){ mostrarMensaje(mensaje, Toast.LENGTH_LONG); } public static void mostrarMensajeCorto(int mensaje){ mostrarMensaje(mensaje, Toast.LENGTH_SHORT); } private static void mostrarMensaje(int mensaje, int duration) { ctx = ctx.getApplicationContext(); Thread th = null; if (toast!=null){ th = new Thread(new Runnable() { @Override public void run() { toast.cancel(); } }); th.start(); } try { if (th!=null) th.join(); } catch (InterruptedException e) {} text.setText(mensaje); toast.setDuration(duration); toast.show(); } }
Como se puede observar, la clase necesita una inicialización que vamos a realizar llamando al método prepararVista() al cual le pasaremos el contexto global de la aplicación y la vista obtenida a partir del layout que creamos al principio.
LayoutInflater inflater = getLayoutInflater(); View layout = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root)); MensajeToast.prepararVista(getApplicationContext(),layout);A partir de este momento cada vez que queramos escribir un mensaje Toast llamaremos a MensajeToast.mostrarMensaje(R.string.mensaje) el cual cancelara el toast anterior (si es que se esta mostrando), y cambiara el texto por el nuevo mensaje.
Se pueden hacer variantes, como cambiar la imagen que se muestre y otras cosas, pero eso ya queda a la imaginación de cada uno.
Espero que os haya gustado todo lo que he puesto, y si veis algo raro, no dudéis en corregidme.
Nos vemos, espero que pronto.