Toast equivalent for Xamarin Forms

75,736

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

  1. Install the Package on all your projects
  2. include the namespace using Xamarin.CommunityToolkit.Extensions;
  3. 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.

enter image description here


Resources

SnackBar Sample

Official Repo https://github.com/xamarin/XamarinCommunityToolkit

Official Docs https://docs.microsoft.com/en-us/xamarin/community-toolkit/


EDIT

  1. 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);
  1. 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);

enter image description here

enter image description here

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 MaxHeightis actually required to keep the height at the minimum.

Share:
75,736

Related videos on Youtube

Jimmy
Author by

Jimmy

Updated on July 08, 2022

Comments

  • Jimmy
    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
    Bret Faller about 7 years
    This is by far the best answer to this question. No third party plugins or libraries needed.
  • Joyce de Lanna
    Joyce de Lanna almost 7 years
    in DependencyService line I am getting "Object reference not set to an instance of an object."
  • Lutaaya Huzaifah Idris
    Lutaaya Huzaifah Idris over 6 years
    Yeah this is the best answer so far , i like dependency service
  • Nieminen
    Nieminen over 6 years
    Full of win. Would you happen to have a UWP version of this as well?
  • Meng Tim
    Meng Tim over 6 years
    Did 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
    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
    Vojtěch Sázel about 6 years
    Android Toast means completely different thing - it's a popup message. This library is for system-wide notifications.
  • Ian Warburton
    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
    Meng Tim about 6 years
    @Ian Warburton Do you have a code sample for this? Thanks so much. I still need this function.
  • Emil
    Emil almost 6 years
    rg 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
    R15 almost 6 years
    @AlexChengalan-Could you tell me why interface needed here. However without interface also we can do it.
  • Alex Chengalan
    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
    Joachim Løvf almost 6 years
    Thanks for this! I have only one issue with it: How could you NOT call the interface IToaster? :)
  • Alex Chengalan
    Alex Chengalan almost 6 years
    @JoachimLøvf What if somebody wants to show snack bar instead of toast? ;)
  • Olorunfemi Davis
    Olorunfemi Davis over 5 years
    So registering it as a Dependency Service does not need for the UWP?
  • Gábor
    Gábor over 5 years
    It works exactly as the other two variants. Yes, a dependency service.
  • findusl
    findusl over 5 years
    Should 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
    bobwki over 5 years
    Dang -- I see an even better version of this below from @Pierre-Alexandre Flèche. How did I miss it before?
  • Jamshaid K.
    Jamshaid K. over 5 years
    Gives an exception System.TypeLoadException: <Timeout exceeded getting exception details> on IOS and doesn't show on Android.
  • GiampaoloGabba
    GiampaoloGabba about 5 years
    So 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
    CennoxX over 4 years
    This doesn't at all react like a toast, it needs an action to continue.
  • G_Money
    G_Money over 4 years
    Is there a way to move it to the top? Customize and show multiples?
  • Fk Bey
    Fk Bey over 4 years
    no. this library supports only basic toast messages. you just can change bg and text color and the duration of message.
  • Razzzz
    Razzzz over 4 years
    in DependencyService line I am getting "Object reference not set to an instance of an object." ? Any solution i have instance
  • Razzzz
    Razzzz over 4 years
    public IMessage Message => DependencyService.Get<IMessage>();
  • actopozipc
    actopozipc about 4 years
    @Razzzz if this exception appears you are missing the assembly class above the namespace
  • Sadra M.
    Sadra M. over 3 years
    @JoycedeLanna Don't forget to register the interface in MainActivity.cs. Add this line of code before LoadApplication(new App()) DependencyService.Register<IMessage, MessageAndroid>();
  • Emil
    Emil almost 3 years
    this is not working. not sure if that is something to do with the latest Ios version but no longer working
  • Emil
    Emil almost 3 years
    thats awesome and working. especially with the popup page solution. thanks.
  • Priyanka
    Priyanka almost 3 years
    How to display the text at the center and how to provide the margin to the snackbar
  • Krausladen
    Krausladen over 2 years
    I wish I had seen this before trying the top voted answer. Good lord.
  • Cfun
    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