package de.blau.android.util;
import java.util.LinkedList;
import android.app.Activity;
import android.content.Context;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import de.blau.android.R;
/**
* Helper methods to display Snackbars in a consistent way and queuing on one of three priority queues
* @author simon
*
*/
public class Snack {
private static final int SHOW_DURATION_ACTION = 5000;
protected static final int QUEUE_CAPACITY = 3;
private static Object queueLock = new Object();
// google has declared Snackbar as final, making life difficult for everybody ....
protected static LinkedList<Snackbar> infoQueue = new LinkedList<Snackbar>();
protected static LinkedList<Snackbar> warningQueue = new LinkedList<Snackbar>();
protected static LinkedList<Snackbar> errorQueue = new LinkedList<Snackbar>();
static boolean isShowing(LinkedList<Snackbar> queue) {
Snackbar first = queue.peekFirst();
if (first != null) {
return first.isShown();
}
return false;
}
/**
* Enqueue a snackbar on a queue removing items if space is exhausted
*
* Note: caller needs to provide synchronization
* @param queue
* @param s
*/
static void enqueue(LinkedList<Snackbar> queue, Snackbar s) {
if (queue.size() >= QUEUE_CAPACITY) {
Snackbar first = queue.peekFirst();
if (first != null) {
queue.removeFirst();
if (first.isShown()) {
first.dismiss(); // will try to remove itself but that is OK
}
}
}
queue.offer(s);
}
/**
* Show the first snackbar on the queue if any and not already being shown
*
* Note: caller needs to provide synchronization
* @param queue to check
* @return true if a snackbar was found and shown
*/
static boolean showFirst(LinkedList<Snackbar> queue) {
Snackbar first = queue.peekFirst();
if (first != null && !first.isShown()) {
first.show();
return true;
}
return false;
}
/**
* Dismiss the first entry on the queue if it is being shown
*
* Note: caller needs to provide synchronization
* @param queue the queue to check
*/
static void dismiss(LinkedList<Snackbar> queue) {
Snackbar first = queue.peekFirst();
if (first != null && !first.isShown()) {
first.dismiss();
}
}
/**
* Enqueue a snackbar on the info queue
*
* @param s the snackbar to queue
*/
static void enqueueInfo(Snackbar s) {
synchronized (queueLock) {
enqueue(infoQueue, s);
if (!isShowing(warningQueue) && !isShowing(errorQueue)) {
showFirst(infoQueue);
}
}
}
/**
* Enqueue a snackbar on the warning queue
*
* @param s the snackbar to queue
*/
static void enqueueWarning(Snackbar s) {
synchronized (queueLock) {
enqueue(warningQueue, s);
if (isShowing(errorQueue)) {
return;
}
dismiss(warningQueue);
showFirst(warningQueue);
}
}
/**
* Enqueue a snackbar on the error queue
*
* @param s the snackbar to queue
*/
static void enqueueError(Snackbar s) {
synchronized (queueLock) {
enqueue(errorQueue, s);
dismiss(infoQueue);
dismiss(warningQueue);
showFirst(errorQueue);
}
}
/**
* called when a snackbar has been dismissed, removes itself from the queue
* and shows the next eligible snackbar if any.
*/
static Snackbar.Callback callback = new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar s, int event) {
synchronized(queueLock) {
if (!infoQueue.remove(s)) {
if (!warningQueue.remove(s)) {
errorQueue.remove(s);
}
}
if (!showFirst(errorQueue)) {
if (!showFirst(warningQueue)) {
showFirst(infoQueue);
}
}
}
}
};
/**
* Display a snackbar with an error message
*
* @param activity activity calling us
* @param res resource id of the message to display
*/
public static void barError(Activity activity, int res) {
if (activity != null) {
barError(activity.findViewById(android.R.id.content), res);
}
}
/**
* Display a snackbar with an error message
*
* @param v view to display the snackbar on
* @param res resource id of the message to display
*/
public static void barError(View v, int res) {
Snackbar snackbar = Snackbar.make(v, res, Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_error, R.color.material_red));
snackbar.setCallback(callback);
enqueueError(snackbar);
}
/**
* * Display a snackbar with an error message
*
* @param activity activity calling us
* @param msg message to display
*/
public static void barError(Activity activity, String msg) {
if (activity != null) {
barError(activity.findViewById(android.R.id.content), msg);
}
}
/**
* Display a snackbar with an error message
*
* @param v view to display the snackbar on
* @param msg message to display
*/
public static void barError(View v, String msg) {
Snackbar snackbar = Snackbar.make(v, msg, Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_error, R.color.material_red));
snackbar.setCallback(callback);
enqueueError(snackbar);
}
/**
* Display a snackbar with an informational message
*
* @param activity activity calling us
* @param res resource id of the message to display
*/
public static void barInfo(Activity activity, int res) {
if (activity != null) {
barInfo(activity.findViewById(android.R.id.content), res);
}
}
/**
* Display a snackbar with an informational message
*
* @param v view to display the snackbar on
* @param res resource id of the message to display
*/
public static void barInfo(View v, int res) {
barInfo(v, res, Snackbar.LENGTH_LONG);
}
/**
* Display a snackbar with an informational message for a short duration
*
* @param v view to display the snackbar on
* @param res resource id of the message to display
*/
public static void barInfoShort(View v, int res) {
barInfo(v, res, Snackbar.LENGTH_SHORT);
}
/**
* Display a snackbar with an informational message for a short duration
*
* @param activity activity calling us
* @param res resource id of the message to display
*/
public static void barInfoShort(Activity activity, int res) {
if (activity != null) {
barInfo(activity.findViewById(android.R.id.content), res, Snackbar.LENGTH_SHORT);
}
}
/**
* Display a snackbar with an informational message
*
* @param v view to display the snackbar on
* @param res resource id of the message to display
* @param duration hw long to display the message in ms
*/
public static void barInfo(View v, int res, int duration) {
Snackbar snackbar = Snackbar.make(v, res, duration);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_info, R.color.material_teal));
snackbar.setCallback(callback);
enqueueInfo(snackbar);
}
/**
* Display a snackbar with an informational message
*
* @param activity activity calling us
* @param msg message to display
*/
public static void barInfo(Activity activity, String msg) {
if (activity != null) {
barInfo(activity.findViewById(android.R.id.content), msg);
}
}
/**
* Display a snackbar with an informational message for a short duration
*
* @param v view to display the snackbar on
* @param msg message to display
*/
public static void barInfoShort(View v, String msg) {
barInfo(v, msg, Snackbar.LENGTH_SHORT);
}
/**
* Display a snackbar with an informational message for a short duration
*
* @param activity activity calling us
* @param msg message to display
*/
public static void barInfoShort(Activity activity, String msg) {
if (activity != null) {
barInfo(activity.findViewById(android.R.id.content), msg, Snackbar.LENGTH_SHORT);
}
}
/**
* Display a snackbar with an informational message
*
* @param v view to display the snackbar on
* @param msg message to display
* @param duration hw long to display the message in ms
*/
public static void barInfo(View v, String msg, int duration) {
Snackbar snackbar = Snackbar.make(v, msg, duration);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_info, R.color.material_teal));
snackbar.setCallback(callback);
enqueueInfo(snackbar);
}
/**
* Display a snackbar with an informational message
*
* @param v view to display the snackbar on
* @param msg message to display
*/
public static void barInfo(View v, String msg) {
Snackbar snackbar = Snackbar.make(v, msg, Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_info, R.color.material_teal));
snackbar.setCallback(callback);
enqueueInfo(snackbar);
}
/**
* Display a snackbar with an informational message with a possible action
*
* @param activity activity calling us
* @param msg message to display
* @param action action textRes resource for the text of an action
* @param listener called when action is selected
*/
public static void barInfo(Activity activity, String msg, int actionRes, View.OnClickListener listener) {
if (activity != null) {
barInfo(activity.findViewById(android.R.id.content), msg, actionRes, listener);
}
}
/**
* Display a snackbar with an informational message with a possible action
*
* @param v view to display the snackbar on
* @param msg message to display
* @param action action textRes resource for the text of an action
* @param listener called when action is selected
*/
public static void barInfo(View v, String msg, int actionRes, View.OnClickListener listener) {
Snackbar snackbar = Snackbar.make(v, msg, Snackbar.LENGTH_LONG);
snackbar.setDuration(5000);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_info, R.color.material_teal));
snackbar.setActionTextColor(ContextCompat.getColor(v.getContext(), R.color.ccc_white));
snackbar.setAction (actionRes, listener);
snackbar.setCallback(callback);
enqueueInfo(snackbar);
}
/**
* Display a snackbar with an informational message with a possible action
*
* @param activity activity calling us
* @param msg message to display
* @param action action text
* @param listener called when action is selected
*/
public static void barInfo(Activity activity, String msg, String action, View.OnClickListener listener) {
if (activity != null) {
barInfo(activity.findViewById(android.R.id.content), msg, action, listener);
}
}
/**
* Display a snackbar with an informational message with a possible action
*
* @param v view to display the snackbar on
* @param msg message to display
* @param action action text
* @param listener called when action is selected
*/
public static void barInfo(View v, String msg, String action, View.OnClickListener listener) {
Snackbar snackbar = Snackbar.make(v, msg, Snackbar.LENGTH_LONG);
snackbar.setDuration(SHOW_DURATION_ACTION);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_info, R.color.material_teal));
snackbar.setActionTextColor(ContextCompat.getColor(v.getContext(), R.color.ccc_white));
snackbar.setAction(action, listener);
snackbar.setCallback(callback);
enqueueInfo(snackbar);
}
/**
* Display a snackbar with a warning
*
* @param activity activity calling us
* @param res resource id of the message to display
*/
public static void barWarning(Activity activity, int res) {
if (activity != null) {
barWarning(activity.findViewById(android.R.id.content), res, Snackbar.LENGTH_LONG);
}
}
/**
* Display a snackbar with a warning for a short duration
*
* @param activity activity calling us
* @param res resource id of the message to display
*/
public static void barWarningShort(Activity activity, int res) {
if (activity != null) {
barWarning(activity.findViewById(android.R.id.content), res, Snackbar.LENGTH_SHORT);
}
}
/**
* Display a snackbar with a warning
*
* @param v view to display the snackbar on
* @param res resource id of the message to display
* @param duration hw long to display the message in ms
*/
public static void barWarning(View v, int res, int duration) {
Snackbar snackbar = Snackbar.make(v, res, duration);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_warning, R.color.material_yellow));
snackbar.setCallback(callback);
enqueueWarning(snackbar);
}
/**
* Display a snackbar with an warning message with a possible action
*
* @param activity activity calling us
* @param msg message to display
* @param action action textRes resource for the text of an action
* @param listener called when action is selected
*/
public static void barWarning(Activity activity, String msg, int actionRes, View.OnClickListener listener) {
if (activity != null) {
barWarning(activity.findViewById(android.R.id.content), msg, actionRes, listener);
}
}
/**
* Display a snackbar with an warning message with a possible action
*
* @param v view to display the snackbar on
* @param msg message to display
* @param action action text resrouce id
* @param listener called when action is selected
*/
public static void barWarning(View v, String msg, int actionRes, View.OnClickListener listener) {
Snackbar snackbar = Snackbar.make(v, msg, Snackbar.LENGTH_LONG);
snackbar.setDuration(5000);
snackbar.getView().setBackgroundColor(ThemeUtils.getStyleAttribColorValue(v.getContext(), R.attr.snack_warning, R.color.material_yellow));
snackbar.setActionTextColor(ContextCompat.getColor(v.getContext(), R.color.ccc_white));
snackbar.setAction (actionRes, listener);
snackbar.setCallback(callback);
enqueueWarning(snackbar);
}
/**
* Display an info toast underneath the top action bar
* @param activity activity that called this
* @param msg the message to display
*/
public static void toastTopInfo(Context context, String msg) {
toastTop(context, msg, ThemeUtils.getStyleAttribColorValue(context, R.attr.snack_info, R.color.material_teal),Toast.LENGTH_SHORT);
}
/**
* Display a warning toast underneath the top action bar
* @param activity activity that called this
* @param msg the message to display
*/
public static void toastTopWarning(Context context, String msg) {
toastTop(context, msg, ThemeUtils.getStyleAttribColorValue(context, R.attr.snack_warning, R.color.material_yellow),Toast.LENGTH_LONG);
}
/**
* Display an error toast underneath the top action bar
* @param activity activity that called this
* @param msgRes the message resource to display
*/
public static void toastTopError(Context context, int msgRes) {
toastTop(context, msgRes, ThemeUtils.getStyleAttribColorValue(context, R.attr.snack_error, R.color.material_red),Toast.LENGTH_LONG);
}
/**
* Display an error toast underneath the top action bar
* @param activity activity that called this
* @param msg the message to display
*/
public static void toastTopError(Context context, String msg) {
toastTop(context, msg, ThemeUtils.getStyleAttribColorValue(context, R.attr.snack_error, R.color.material_red),Toast.LENGTH_LONG);
}
/**
* Display a toast underneath the top action bar
* @param activity activity that called this
* @param msgRes the message resource to display
* @param color background color of the message
* @param duration how long to display the message
*/
private static void toastTop(Context context, int msgRes, int color, int duration) {
toastTop(context, context.getResources().getString(msgRes), color, duration);
}
/**
* Display a toast underneath the top action bar
* @param activity activity that called this
* @param msg the message to display
* @param color background color of the message
* @param duration how long to display the message
*/
private static void toastTop(Context context, String msg, int color, int duration) {
LayoutInflater inflater = LayoutInflater.from(context);
View layout = inflater.inflate(R.layout.toast, null);
layout.setBackgroundColor(color);
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText(msg);
Toast toast = new Toast(context);
int yOffset = ThemeUtils.getActionBarHeight(context) + 5;
toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, yOffset);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
toast.show();
}
}