Toast equivalent for Xamarin Forms
Solution 1
There is a simple solution for this. By using the DependencyService you can easily get the Toast-Like approach in both Android and iOS.
Create an interface in your common package.
public interface IMessage
{
void LongAlert(string message);
void ShortAlert(string message);
}
Android section
[assembly: Xamarin.Forms.Dependency(typeof(MessageAndroid))]
namespace Your.Namespace
{
public class MessageAndroid : IMessage
{
public void LongAlert(string message)
{
Toast.MakeText(Application.Context, message, ToastLength.Long).Show();
}
public void ShortAlert(string message)
{
Toast.MakeText(Application.Context, message, ToastLength.Short).Show();
}
}
}
iOS section
In iOs there is no native solution like Toast, so we need to implement our own approach.
[assembly: Xamarin.Forms.Dependency(typeof(MessageIOS))]
namespace Your.Namespace
{
public class MessageIOS : IMessage
{
const double LONG_DELAY = 3.5;
const double SHORT_DELAY = 2.0;
NSTimer alertDelay;
UIAlertController alert;
public void LongAlert(string message)
{
ShowAlert(message, LONG_DELAY);
}
public void ShortAlert(string message)
{
ShowAlert(message, SHORT_DELAY);
}
void ShowAlert(string message, double seconds)
{
alertDelay = NSTimer.CreateScheduledTimer(seconds, (obj) =>
{
dismissMessage();
});
alert = UIAlertController.Create(null, message, UIAlertControllerStyle.Alert);
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null);
}
void dismissMessage()
{
if (alert != null)
{
alert.DismissViewController(true, null);
}
if (alertDelay != null)
{
alertDelay.Dispose();
}
}
}
}
Please note that in each platform, we have to register our classes with DependencyService.
Now you can access out Toast service in anywhere in our project.
DependencyService.Get<IMessage>().ShortAlert(string message);
DependencyService.Get<IMessage>().LongAlert(string message);
Solution 2
You can use Acr.UserDialogs Package from nuget and code like below,
Acr.UserDialogs.UserDialogs.Instance.Toast(Message, new TimeSpan(3));
Solution 3
Here's a version of Alex Chengalan's iOS code that avoids the UI sticking when multiple messages are shown...
public class MessageIOS : IMessage
{
const double LONG_DELAY = 3.5;
const double SHORT_DELAY = 0.75;
public void LongAlert(string message)
{
ShowAlert(message, LONG_DELAY);
}
public void ShortAlert(string message)
{
ShowAlert(message, SHORT_DELAY);
}
void ShowAlert(string message, double seconds)
{
var alert = UIAlertController.Create(null, message, UIAlertControllerStyle.Alert);
var alertDelay = NSTimer.CreateScheduledTimer(seconds, obj =>
{
DismissMessage(alert, obj);
});
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null);
}
void DismissMessage(UIAlertController alert, NSTimer alertDelay)
{
if (alert != null)
{
alert.DismissViewController(true, null);
}
if (alertDelay != null)
{
alertDelay.Dispose();
}
}
}
Solution 4
You can use SnackBar
from Xamarin Community toolkit package, which uses native implementation in platforms where natively supported, because Toast
is deprecated in API level 30, a SnackBar
without an Action is equivalent to a Toast.
This method was deprecated in API level 30. Custom toast views are deprecated. Apps can create a standard text toast with the makeText(android.content.Context, java.lang.CharSequence, int) method, or use a Snackbar when in the foreground. Starting from Android Build.VERSION_CODES#R, apps targeting API level Build.VERSION_CODES#R or higher that are in the background will not have custom toast views displayed. (source).
Starting with Xamarin Community toolkit
- Install the Package on all your projects
- include the namespace
using Xamarin.CommunityToolkit.Extensions;
- In your page code-behind show a SnackBar upon an event
await this.DisplayToastAsync("This is a Toast Message");
await this.DisplayToastAsync("This is a Toast Message for 5 seconds", 5000);
You may specify a duration for the SnackBar to disappear (in milliseconds) or leave the default one which equals 3 seconds.
Resources
SnackBar Sample
Official Repo https://github.com/xamarin/XamarinCommunityToolkit
Official Docs https://docs.microsoft.com/en-us/xamarin/community-toolkit/
EDIT
-
Anchored Toast: You may anchor the toast above a view (like screenshot above) by simply calling the extension method
DisplayToastAsync()
from that view (anchor) object instead from the page instance (this
):
<Button x:name="floatingButton" .../>
await floatingButton.DisplayToastAsync("This is a Toast Message for 5 seconds", 5000);
- Padding and corner radius: (starting from xct version 1.3.0 preview-1)
You can set the corner radius and the padding for your Toast like the following example:
var messageOptions = new MessageOptions
{
Message = "Toast with Padding and round corner",
Foreground = Color.White,
Font = Font.SystemFontOfSize(16),
Padding = new Thickness(20)
};
var options = new ToastOptions
{
MessageOptions = messageOptions,
CornerRadius = new Thickness(40, 40, 0, 0),
BackgroundColor = Color.FromHex("#CC0000")
};
await this.DisplayToastAsync(options);
PS: The same properties could be applied for the SnackBar
view.
EDIT2
If what xct SnackBar
offers doesn't fulfil your requirements or you want to display not only text but some complexe view, you might have to use a popup instead.
Solution 5
Adding to Alex's answer, here's the UWP variant:
public class Message : IMessage {
private const double LONG_DELAY = 3.5;
private const double SHORT_DELAY = 2.0;
public void LongAlert(string message) =>
ShowMessage(message, LONG_DELAY);
public void ShortAlert(string message) =>
ShowMessage(message, SHORT_DELAY);
private void ShowMessage(string message, double duration) {
var label = new TextBlock {
Text = message,
Foreground = new SolidColorBrush(Windows.UI.Colors.White),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
};
var style = new Style { TargetType = typeof(FlyoutPresenter) };
style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Windows.UI.Colors.Black)));
style.Setters.Add(new Setter(FrameworkElement.MaxHeightProperty, 1));
var flyout = new Flyout {
Content = label,
Placement = FlyoutPlacementMode.Full,
FlyoutPresenterStyle = style,
};
flyout.ShowAt(Window.Current.Content as FrameworkElement);
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(duration) };
timer.Tick += (sender, e) => {
timer.Stop();
flyout.Hide();
};
timer.Start();
}
}
Coloring and styling is up to you, the MaxHeight
is actually required to keep the height at the minimum.
Related videos on Youtube
Jimmy
Updated on July 08, 2022Comments
-
Jimmy almost 2 years
Is there any way using Xamarin Forms (not Android or iOS specific) to have a pop-up, like Android does with Toast, that needs no user interaction and goes away after a (short) period of time?
From searching around all I'm seeing are alerts that need user clicks to go away.
-
Bret Faller about 7 yearsThis is by far the best answer to this question. No third party plugins or libraries needed.
-
Joyce de Lanna almost 7 yearsin DependencyService line I am getting "Object reference not set to an instance of an object."
-
Lutaaya Huzaifah Idris over 6 yearsYeah this is the best answer so far , i like dependency service
-
Nieminen over 6 yearsFull of win. Would you happen to have a UWP version of this as well?
-
Meng Tim over 6 yearsDid you try the code? If you toast the second message before first one dismiss, the UI will stuck. The second message will never disappear.
-
Alex Chengalan over 6 years@MengTim I have tried this code and working well, but didn't check with simultaneous toasts. Will check and update here.
-
Vojtěch Sázel about 6 yearsAndroid Toast means completely different thing - it's a popup message. This library is for system-wide notifications.
-
Ian Warburton about 6 years@MengTim I seem to have fixed the stuck UI by creating a new alert and timer every time. Both need to be passed to
DismissMessage
. -
Meng Tim about 6 years@Ian Warburton Do you have a code sample for this? Thanks so much. I still need this function.
-
Emil almost 6 yearsrg popups are great. I do similar workaround for loading display or activity indicator on full page. problem with other plugins are they are dependent on async functions and main thread but rg popup can run on 2nd thread which makes it very useful. good idea indeed but I wish to have native look like on android toasts.
-
R15 almost 6 years@AlexChengalan-Could you tell me why interface needed here. However without interface also we can do it.
-
Alex Chengalan almost 6 years@Arvindraja Its because I followed something like this: xamarinhelp.com/xamarin-forms-dependency-injection and I think which is better for dependency injection.
-
Joachim Løvf almost 6 yearsThanks for this! I have only one issue with it: How could you NOT call the interface IToaster? :)
-
Alex Chengalan almost 6 years@JoachimLøvf What if somebody wants to show snack bar instead of toast? ;)
-
Olorunfemi Davis over 5 yearsSo registering it as a Dependency Service does not need for the UWP?
-
Gábor over 5 yearsIt works exactly as the other two variants. Yes, a dependency service.
-
findusl over 5 yearsShould have read the comment before I installed the library just to notice then that these are not android style toasts.. Please make that clear in the answer.
-
bobwki over 5 yearsDang -- I see an even better version of this below from @Pierre-Alexandre Flèche. How did I miss it before?
-
Jamshaid K. over 5 yearsGives an exception
System.TypeLoadException: <Timeout exceeded getting exception details>
on IOS and doesn't show on Android. -
GiampaoloGabba about 5 yearsSo far this is the best method to do cross platform toast. Rg.Popup is super flexibile, and i use it in almost every project. No need to use other plugins or platform code to display toasts,
-
CennoxX over 4 yearsThis doesn't at all react like a toast, it needs an action to continue.
-
G_Money over 4 yearsIs there a way to move it to the top? Customize and show multiples?
-
Fk Bey over 4 yearsno. this library supports only basic toast messages. you just can change bg and text color and the duration of message.
-
Razzzz over 4 yearsin DependencyService line I am getting "Object reference not set to an instance of an object." ? Any solution i have instance
-
Razzzz over 4 yearspublic IMessage Message => DependencyService.Get<IMessage>();
-
actopozipc about 4 years@Razzzz if this exception appears you are missing the assembly class above the namespace
-
Sadra M. over 3 years@JoycedeLanna Don't forget to register the interface in
MainActivity.cs
. Add this line of code beforeLoadApplication(new App())
DependencyService.Register<IMessage, MessageAndroid>();
-
Emil almost 3 yearsthis is not working. not sure if that is something to do with the latest Ios version but no longer working
-
Emil almost 3 yearsthats awesome and working. especially with the popup page solution. thanks.
-
Priyanka almost 3 yearsHow to display the text at the center and how to provide the margin to the snackbar
-
Krausladen over 2 yearsI wish I had seen this before trying the top voted answer. Good lord.
-
Cfun over 2 years@Priyanka not sure about that if you think it could be a new feature you can request it in GitHub repo, or check the Popup control (altought it might be an overkill in this case). Krausladen good to know it's helpful