Xamarin Forms için toast eşdeğeri


90

Android'in Toast ile yaptığı gibi, kullanıcı etkileşimi gerektirmeyen ve (kısa) bir süre sonra kaybolan bir pop-up'a sahip olmak için Xamarin Forms (Android veya iOS'a özgü değil) kullanmanın bir yolu var mı?

Etrafta arama yapmaktan gördüğüm tek şey, kullanıcı tıklamasıyla ortadan kalkması gereken uyarılardır.

Yanıtlar:


171

Bunun için basit bir çözüm var. DependencyService'i kullanarak, Toast-Like yaklaşımını hem Android hem de iOS'ta kolayca edinebilirsiniz.

Ortak paketinizde bir arayüz oluşturun.

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

Android bölümü

[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 bölümü

İO'larda Toast gibi yerel bir çözüm yoktur, bu nedenle kendi yaklaşımımızı uygulamamız gerekir.

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

Her platformda, sınıflarımızı DependencyService ile kaydetmemiz gerektiğini lütfen unutmayın.

Artık projemizin her yerinden Toast hizmetine erişebilirsiniz.

DependencyService.Get<IMessage>().ShortAlert(string message); 
DependencyService.Get<IMessage>().LongAlert(string message);

20
Bu, bu sorunun açık ara en iyi cevabıdır. Üçüncü taraf eklentileri veya kitaplıkları gerekmez.
Bret Faller

4
DependencyService satırında "Nesne başvurusu bir nesnenin örneğine ayarlanmadı."
Joyce de Lanna

5
Evet, bu şimdiye kadarki en iyi cevap, bağımlılık hizmetini seviyorum
Lutaaya Huzaifah Idris

1
Kazanmakla dolu. Bunun bir UWP versiyonuna da sahip olur muydunuz?
Nieminen

1
@MengTim Her seferinde yeni bir uyarı ve zamanlayıcı oluşturarak sıkışan kullanıcı arayüzünü düzelttim. Her ikisine de geçilmesi gerekiyor DismissMessage.
Ian Warburton

14

İşte Alex Chengalan'ın iOS kodunun , birden fazla mesaj gösterildiğinde kullanıcı arayüzünün sıkışmasını önleyen bir sürümü ...

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

11

Acr.UserDialogs Paketini nuget'ten ve aşağıdaki gibi kodu kullanabilirsiniz,

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

9

Normalde Egors Toasts eklentisini kullanırdık, ancak iOS üzerinde mevcut bir proje için izin gerektirdiğinden, Rg.Plugins.Popup nuget ( https://github.com/rotorgames/Rg.Plugins.Popup) kullanarak farklı bir yol izledik. ).

PopupPage türünde temel bir xaml / cs sayfası yazdım,

<?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">
...

ve arayüzünü uygulama başlangıcında kaydettiğiniz bir hizmet tarafından oluşturulmuş veya hizmeti almak için Xamarin.Forms.DependencyService'i kullanmanız da uygulanabilir olacaktır.

Hizmet, PopupPage'in türetilmiş sayfasını bildirir

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

Açılır sayfa, sayfa görüntüsünün dışına dokunarak kullanıcı tarafından kapatılabilir (ekranı doldurmadığı varsayılarak).

Bu, iOS / Droid'de mutlu bir şekilde çalışıyor gibi görünüyor, ancak bunun riskli bir yol olduğunu bilen biri varsa düzeltmeye açığım.


rg pop-up'ları harika. Tam sayfada görüntü veya etkinlik göstergesi yüklemek için benzer bir çözüm yapıyorum. diğer eklentilerle ilgili sorun, asenkron işlevlere ve ana iş parçacığına bağımlı olmalarıdır, ancak rg popup, onu çok kullanışlı kılan 2. iş parçacığında çalışabilir. gerçekten iyi bir fikir, ancak android tostlarda yerel görünüme sahip olmak istiyorum.
Emil

Şimdiye kadar bu, platformlar arası tost yapmak için en iyi yöntemdir. Rg.Popup süper esnek ve neredeyse her projede kullanıyorum. Tostları görüntülemek için başka eklentileri veya platform kodunu kullanmaya gerek yok,
GiampaoloGabba

8

Alex'in cevabına ek olarak, işte UWP varyantı:

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

Boyama ve şekillendirme size kalmış, MaxHeightaslında yüksekliği minimumda tutmak gerekiyor.


Yani onu bir Bağımlılık Hizmeti olarak kaydettirmek UWP'ye ihtiyaç duymaz mı?
Olorunfemi Ajibulu

Diğer iki varyantla aynı şekilde çalışır. Evet, bağımlılık hizmeti.
Gabor

7

Sen IUserDialog kullanabilirsiniz Nuget ve basitçe 's toastAlert kullanmak

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

UserDialogs.Instance.Toast(toastConfig);

4

İşte Xamarin.iOS'ta tostu göstermek için kullandığım bir kod parçacığı

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

4

Dan Plugin.Toastkitaplık tavsiye ederim nuget. İyi çalışıyor.

CrossToastPopUp.Current.ShowToastMessage("my toast message");

veya ACR.UserDialogs Nuget kitaplığından

UserDialogs.Instance.ShowLoading("Loading");

Zirveye taşımanın bir yolu var mı? Katları özelleştirmek ve göstermek?
G_Money

Hayır. bu kitaplık yalnızca temel tost mesajlarını destekler. sadece bg ve metin rengini ve mesajın süresini değiştirebilirsiniz.
Fk Bey

4

@MengTim, Alex-chengalan çözümüyle @ birden tost sorunu gidermek için, ben sadece içinde her şeyi sarılı ShowAlert()olup olmadığını görmek için bir çek ile alertve alertDelaydaha sonra içinde boş olan DismissMessage, nulled alertve alertDelay.

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

Hızlı bir düzeltme arıyorsanız, en azından kullanıcı arayüzünün askıda kalmasını temizliyor gibiydi. Tostu yeni bir sayfada gezinirken görüntülemeye çalışıyordum ve PresentViewControllerayarlamanın esasen navigasyonumu iptal ettiğini düşünüyorum . Üzgünüm konu başlığı içinde yorum yapmadım, itibarım çok düşük :(


2

Bu, ShowAlertkadeh kaldırmanın açılır sayfada bile görüntülenmesini sağlamak için Ian Warburton'ın geliştirilmiş versiyonudur. Ayrıca, kullanıcı tostun dışına tıklarsa tost iptal edilir. UIAlertControllerStyle.ActionSheetBu görünümü tost gibi kullandım ama aynı zamanda işe yarıyorUIAlertControllerStyle.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);
        });
    }

Umarım bu birine yardımcı olur!


1

Forms'da yerleşik bir mekanizma yoktur, ancak bu nuget paketi benzer bir şey sağlar

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

Not: Bunlar soruda talep edilen Android tarzı tostlar değil, sistem çapında bildirimler olan UWP tarzı tostlardır.


5
Android Toast tamamen farklı bir şey ifade ediyor - bu bir açılır mesaj. Bu kitaplık, sistem çapında bildirimler içindir.
Vojtěch Sázel

Kitaplığı kurmadan önce yorumu okumalıydım, o zaman bunların android tarzı tost olmadığını fark etmek için .. Lütfen cevabınızda bunu netleştirin.
findusl


1

Rg.Plugins.Popup NuGet ile özel bir açılır pencere özelleştirdim, bu bir örnektir:

 <pages:PopupPage.Animation>
    <animations:ScaleAnimation 
        PositionIn="Center"
        PositionOut="Center"
        ScaleIn="1.2"
        ScaleOut="0.8"
        DurationIn="600"
        DurationOut="600"
        EasingIn="Linear"
       EasingOut="Linear"/>
</pages:PopupPage.Animation>

<Frame CornerRadius="10"  
    HeightRequest="30"
       VerticalOptions="End"
       HorizontalOptions="Fill"
       HasShadow="False"
        Padding="0" Margin="40,50"
       OutlineColor="LightGray">
    <StackLayout 
    Opacity="0.4"
       BackgroundColor="White">
    <Label
        x:Name="lbl"
        LineBreakMode="WordWrap"
        HorizontalTextAlignment="Center"
                    VerticalTextAlignment="Center"

        VerticalOptions="CenterAndExpand"
        HorizontalOptions="Center" TextColor="Black" FontSize="12">
                <Label.FontFamily>
                    <OnPlatform x:TypeArguments="x:String">
                        <On Platform="iOS" Value="NewJuneMedium" />
                    </OnPlatform>
                </Label.FontFamily>
            </Label>
</StackLayout>
    </Frame>

daha sonra temel içerik sayfanıza, bir süre sonra "tost" u göstermek ve gizlemek için aşağıdaki kodu ekleyebilirsiniz:

public async void showpopup(string msg)
    {
        await Navigation.PushPopupAsync(new Toast(msg));
        await Task.Delay(3000);
        await Navigation.PopPopupAsync(true);   
    }

0

Yukarıdaki iOS cevapları benim için işe yaradı ama küçük bir sorun için - bir uyarı: UIAlertController'ı sunmaya çalışın ... görünümü pencere hiyerarşisinde olmayan!

Biraz araştırdıktan sonra, yardımcı olan bu ilgisiz cevapla karşılaştım . Poster "Bu aptalca görünüyor ama işe yarıyor" yorumunu yaptı, bu her iki açıdan da haklı.

Dolayısıyla, yukarıdaki ShowAlert () işlevini işe yarıyor gibi görünen şu satırlarla değiştirdim:

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

Dang - Aşağıda @ Pierre-Alexandre Flèche'den bunun daha iyi bir versiyonunu görüyorum. Daha önce nasıl özledim?
bobwki

0

UWP için

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

-5

Kullanabilirsiniz DisplayAlert("", "", "", "" );


1
Bu hiç de kadeh kaldırıcı gibi tepki vermiyor, devam etmesi için bir eyleme ihtiyacı var.
CennoxX
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.