it-swarm.com.de

Toastäquivalent für Xamarin-Formulare

Gibt es eine Möglichkeit, Xamarin Forms (nicht Android- oder iOS-spezifisch) zu verwenden, um ein Popup zu haben, wie es Android mit Toast macht, das keine Benutzerinteraktion erfordert und nach einer (kurzen) Zeitspanne verschwindet? 

Bei der Suche in der Umgebung sehe ich alle Warnungen, bei denen Klicks der Benutzer erforderlich sind.

43
Jimmy

Dafür gibt es eine einfache Lösung. Mit dem DependencyService können Sie den Toast-Like-Ansatz sowohl in Android als auch in iOS problemlos nutzen.

Erstellen Sie eine Schnittstelle in Ihrem allgemeinen Paket.

public interface iMessage
{
    void LongAlert(string message);
    void ShortAlert(string message);
}

Android-Bereich

[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-Bereich

In iOs gibt es keine native Lösung wie Toast, daher müssen wir unseren eigenen Ansatz implementieren.

[Assembly: Xamarin.Forms.Dependency(typeof(MessageIOS))]
namespace Bahwan.iOS
{
    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();
            }
        }
    }
}

Bitte beachten Sie, dass wir auf jeder Plattform unsere Klassen bei DependencyService registrieren müssen.

Jetzt können Sie überall in unserem Projekt auf den Toast-Service zugreifen.

DependencyService.Get<iMessage>().ShortAlert(string message); 
DependencyService.Get<iMessage>().LongAlert(string message);
92
Alex Chengalan

Hier ist eine Version von Alex Chengalans iOS code , die verhindert, dass die Benutzeroberfläche hängen bleibt, wenn mehrere Nachrichten angezeigt werden ...

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();
            }
        }
    }
5
Ian Warburton

Zu Alex 'Antwort kommt noch die UWP-Variante:

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();
  }
}

Die Farbgebung und das Styling liegt ganz bei Ihnen. Die Variable MaxHeight ist erforderlich, um die Höhe auf einem Minimum zu halten.

4
Gábor

Hier ist ein Codeausschnitt, den ich verwende, um den Toast in Xamarin.iOS zu zeigen

  public void ShowToast(String message, UIView view)
    {
        UIView residualView = view.ViewWithTag(1989);
        if (residualView != null)
            residualView.RemoveFromSuperview();

        var viewBack = new UIView(new CoreGraphics.CGRect(83, 0, 300, 100));
        viewBack.BackgroundColor = UIColor.Black;
        viewBack.Tag = 1989;
        UILabel lblMsg = new UILabel(new CoreGraphics.CGRect(0, 20, 300, 60));
        lblMsg.Lines = 2;
        lblMsg.Text = message;
        lblMsg.TextColor = UIColor.White;
        lblMsg.TextAlignment = UITextAlignment.Center;
        viewBack.Center = view.Center;
        viewBack.AddSubview(lblMsg);
        view.AddSubview(viewBack);
        roundtheCorner(viewBack);
        UIView.BeginAnimations("Toast");
        UIView.SetAnimationDuration(3.0f);
        viewBack.Alpha = 0.0f;
        UIView.CommitAnimations();
    }
3
Durai Amuthan.H

@MengTim, um das Problem des mehrfachen Toasts in der Lösung von @ alex-chengalan zu beheben, habe ich einfach alles in ShowAlert () mit einer Prüfung versehen, um festzustellen, ob alert und alertDelay null sind.

void ShowAlert(string message, double seconds)
    {
        if(alert == null && alertDelay == null) {
            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);
            alert = null;
        }
        if (alertDelay != null)
        {
            alertDelay.Dispose();
            alertDelay = null;
        }
    }

Das schien zumindest den UI-Hang aufzuklären, wenn Sie nach einer schnellen Lösung suchen. Ich habe versucht, den Toast bei der Navigation auf einer neuen Seite anzuzeigen, und glaube, dass der eingestellte PresentViewController meine Navigation im Wesentlichen aufhob. Sorry, ich habe nicht innerhalb des Threads einen Kommentar abgegeben, mein Ruf ist zu niedrig :(

3
Gunnar

Normalerweise würden wir das Egors Toasts-Plugin verwenden. Da es jedoch Berechtigungen für iOS für ein aktuelles Projekt erfordert, sind wir mit Rg.Plugins.Popup-Nuget ( https://github.com/rotorgames/Rg.Plugins) eine andere Route gegangen .Pop-up ).

Ich habe eine einfache Xaml/cs-Seite vom Typ PopupPage geschrieben,

<?xml version="1.0" encoding="utf-8" ?>
<popup:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.Microsoft.com/winfx/2009/xaml"
         xmlns:popup="clr-namespace:Rg.Plugins.Popup.Pages;Assembly=Rg.Plugins.Popup"
         x:Class="YourApp.Controls.ToastPage">
...

und lassen Sie es von einem Dienst erstellen, dessen Schnittstelle Sie beim Start der App registrieren oder Xamarin.Forms.DependencyService verwenden, um den Dienst abzurufen.

Der Dienst informiert über die abgeleitete PopupPage-Seite

await PopupNavigation.PushAsync(newToastPage);
await Task.Delay(2000);
await PopupNavigation.PopAllAsync();

Die Popup-Seite kann vom Benutzer durch Tippen außerhalb der Seitenanzeige (sofern der Bildschirm nicht ausgefüllt ist) verworfen werden.

Dies scheint auf iOS/Droid gut zu funktionieren, aber ich bin offen für Korrekturen, wenn jemand weiß, was dies eine riskante Methode ist.

3
Allister

Dies ist meine verbesserte ShowAlert-Version von Ian Warburtons Version, um sicherzustellen, dass der Toast auch auf der Popup-Seite angezeigt wird. Außerdem wird der Toast abgewiesen, wenn der Benutzer außerhalb des Toasts klickt Ich habe UIAlertControllerStyle.ActionSheet verwendet, der Toast mag, aber er funktioniert auch mit UIAlertControllerStyle.Alert.

    void ShowAlert(string message, double seconds)
    {
        var alert = UIAlertController.Create(null, message, UIAlertControllerStyle.ActionSheet);

        var alertDelay = NSTimer.CreateScheduledTimer(seconds, obj =>
        {
            DismissMessage(alert, obj);
        });

        var viewController = UIApplication.SharedApplication.KeyWindow.RootViewController;
        while (viewController.PresentedViewController != null)
        {
            viewController = viewController.PresentedViewController;
        }
        viewController.PresentViewController(alert, true, () =>
        {
            UITapGestureRecognizer tapGesture = new UITapGestureRecognizer(_ => DismissMessage(alert, null));
            alert.View.Superview?.Subviews[0].AddGestureRecognizer(tapGesture);
        });
    }

Ich hoffe das hilft jemandem! 

In Forms gibt es keinen integrierten Mechanismus, aber dieses Nuget-Paket liefert etwas Ähnliches

https://github.com/EgorBo/Toasts.Forms.Plugin

Hinweis: Hierbei handelt es sich nicht um Toasts im Android-Stil, wie in der Frage gefordert, sondern um Toasts im UWP-Stil, bei denen es sich um systemweite Benachrichtigungen handelt.

1
Jason

Sie können das Acr.UserDialogs-Paket aus Nuget und Code wie folgt verwenden:

Acr.UserDialogs.UserDialogs.Instance.Toast(Message, new TimeSpan(3));
1
KiShOrE

Sie können DisplayAlert("", "", "", "" ); verwenden

0
O.Ahmadpoor

Sie können IUserDialog Nuget verwenden und einfach toastAlert verwenden

var toastConfig = new ToastConfig("Toasting...");
toastConfig.SetDuration(3000);
toastConfig.SetBackgroundColor(System.Drawing.Color.FromArgb(12, 131, 193));

UserDialogs.Instance.Toast(toastConfig);
0
mohammad kamali

Prüfen Sie, ob plugin.toast v 2.1.2 für Android, iOS und UWP verfügbar ist

Die oben genannten iOS-Antworten funktionierten bei mir jedoch für ein kleines Problem - eine Warnung: Versuch UIAlertController zu präsentieren ... deren Ansicht nicht in der Fensterhierarchie ist!

Nach einiger Suche stieß ich auf diese nicht verwandte Antwort die mir geholfen hat. Das Poster kommentierte "Dies sieht dumm aus, aber es funktioniert", was in beiden Punkten richtig ist.

Also habe ich die ShowAlert () -Funktion oben mit den folgenden Zeilen geändert, die zu funktionieren scheinen:

    var rootVC = UIApplication.SharedApplication.KeyWindow.RootViewController;
    while ( rootVC.PresentedViewController != null) {
        rootVC = rootVC.PresentedViewController;
    }
    rootVC.PresentViewController( alert, true, null);
0
bobwki

Für UWP

public void ShowMessageFast(string message)
    {
        ToastNotifier ToastNotifier = ToastNotificationManager.CreateToastNotifier();
        Windows.Data.Xml.Dom.XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
        Windows.Data.Xml.Dom.XmlNodeList toastNodeList = toastXml.GetElementsByTagName("text");
        toastNodeList.Item(0).AppendChild(toastXml.CreateTextNode("Test"));
        toastNodeList.Item(1).AppendChild(toastXml.CreateTextNode(message));
        Windows.Data.Xml.Dom.IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
        Windows.Data.Xml.Dom.XmlElement audio = toastXml.CreateElement("audio");
        audio.SetAttribute("src", "ms-winsoundevent:Notification.SMS");

        ToastNotification toast = new ToastNotification(toastXml);
        toast.ExpirationTime = DateTime.Now.AddSeconds(4);
        ToastNotifier.Show(toast);
    }
0
Fabien Richard