I'm maintaining an "enterprise" Android app that runs on wrist-mounted computers in an industrial environment. When we need to let the user know something of middling importance, we have the device make a noise and produce haptic feedback, and pop up a short text message in a bubble on the middle of the screen. The popup goes away on its own after a few seconds.
The design intent here is that the user can see what's up, but doesn't have to reach over with the dominant hand (which might be full of Tool or Product) and mess with the device buttons or screen to carry on working.
Originally, this was implemented using a Toast
and life was good. Then Toast
was Googléd into deprecation, and a new implementation (indistinguishable to the user) based on Snackbar
was born. (Code in C# for Xamarin.Android for "historical reasons", but that should not matter for the purposes of the question.)
public static Snackbar ShowErrorOverlay(Activity activity,
int duration, int resID, params object[] args)
{
var coordinatorLayout = activity.Window.DecorView.RootView;
var snackbar = Snackbar.Make(coordinatorLayout, string.Empty, Snackbar.LengthLong);
var layout = activity.LayoutInflater.Inflate(Resource.Layout.ErrorToast,
activity.FindViewById<ViewGroup>(Resource.Id.errortoast_layout_main), false);
var txt = layout.FindViewById<TextView>(Resource.Id.errortoast_textview_message);
txt.Text = string.Format(activity.Resources.GetString(resID), args);
var snackbarLayout = (Snackbar.SnackbarLayout)snackbar.View;
snackbarLayout.SetBackgroundColor(Color.Transparent);
var opts = (FrameLayout.LayoutParams)snackbarLayout.LayoutParameters;
opts.Gravity = GravityFlags.Center;
snackbarLayout.LayoutParameters = opts;
snackbarLayout.AddView(layout);
snackbar.SetDuration(duration);
snackbar.Show();
return snackbar;
}
where Resource.Layout.ErrorToast
comes from:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/errortoast_layout_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="8dp"
android:background="@drawable/ErrorToast">
<TextView
android:id="@+id/errortoast_textview_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal|center_vertical"
android:text="(error message)"
android:paddingLeft="12dp"
android:paddingRight="12dp"
style="@style/TextAppearance"
android:layout_centerInParent="true" />
</RelativeLayout>
and drawable/ErrorToast
looks like:
<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/errorBackground" />
<stroke
android:width="4dp"
android:color="@color/errorBorder" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="35dp" />
</shape>
End result: Text in the middle of the screen, in a bright cheerful yellow bubble, thus:
Alas, no useful Android API is ever long for this troubled world. Thus it is with Snackbar.SnackbarLayout
:
Warning XAOBS001 'Snackbar.SnackbarLayout' is obsolete: 'While this type is 'public', Google considers it internal API and reserves the right to modify or delete it in the future. Use at your own risk.'
Take as read the usual Kübler-Ross stages of grief over gratuitous API changes.
With what am I supposed to replace this going forward? What is the "best practices" toast/snackbar-like popup thing with a custom layout? (Maybe subclass AndroidX.Fragment.App.DialogFragment
?)
I want to keep the current appearance (see above screenshot) and behavior: pops up for a limited time over the top of whatever is on the screen, goes away after a specific time limit (but can be dismissed early).
I do not need to show anything on the screen when my application is not in the foreground.
Ideally, I'd also avoid having to touch every one of the (many, many) screen layouts in my app to achieve this.