Existe uma solução simples para isso. Ao usar o DependencyService, você pode obter facilmente a abordagem Toast-Like no Android e no iOS.
Crie uma interface em seu pacote comum.
public interface IMessage
{
void LongAlert(string message);
void ShortAlert(string message);
}
Seção Android
[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();
}
}
}
seção iOS
Em iOs não há solução nativa como o Toast, então precisamos implementar nossa própria abordagem.
[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();
}
}
}
}
Observe que em cada plataforma, temos que registrar nossas classes com DependencyService.
Agora você pode acessar o serviço Toast em qualquer lugar do nosso projeto.
DependencyService.Get<IMessage>().ShortAlert(string message);
DependencyService.Get<IMessage>().LongAlert(string message);
DismissMessage
.Esta é uma versão do código iOS de Alex Chengalan que evita que a IU grude quando várias mensagens são mostradas ...
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(); } } }
fonte
Você pode usar o pacote Acr.UserDialogs do nuget e o código abaixo,
Acr.UserDialogs.UserDialogs.Instance.Toast(Message, new TimeSpan(3));
fonte
Normalmente usaríamos o plugin Egors Toasts, mas como ele requer permissões no iOS para um projeto atual, seguimos um caminho diferente usando o nuget Rg.Plugins.Popup ( https://github.com/rotorgames/Rg.Plugins.Popup )
Eu escrevi uma página xaml / cs básica do tipo PopupPage,
<?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"> ...
e tê-lo criado por um serviço, cuja interface você registra no início do aplicativo ou usa o Xamarin.Forms.DependencyService para buscar o serviço também seria viável.
O serviço atualiza a página derivada do PopupPage e
await PopupNavigation.PushAsync(newToastPage); await Task.Delay(2000); await PopupNavigation.PopAllAsync();
A página Popup pode ser descartada pelo usuário tocando fora da exibição da página (assumindo que não preencheu a tela).
Isso parece funcionar bem no iOS / Droid, mas estou aberto a correções se alguém souber o que é uma maneira arriscada de fazer isso.
fonte
Somando-se à resposta de Alex, aqui está a variante UWP:
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(); } }
Colorir e estilizar é com você,
MaxHeight
é realmente necessário para manter a altura no mínimo.fonte
Você pode usar IUserDialog NuGet e simplesmente usar seu toastAlert
var toastConfig = new ToastConfig("Toasting..."); toastConfig.SetDuration(3000); toastConfig.SetBackgroundColor(System.Drawing.Color.FromArgb(12, 131, 193)); UserDialogs.Instance.Toast(toastConfig);
fonte
Aqui está um trecho de código que estou usando para mostrar a torrada no Xamarin.iOS
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(); }
fonte
Eu recomendaria a
Plugin.Toast
biblioteca denuget
. Isso funciona bem.CrossToastPopUp.Current.ShowToastMessage("my toast message");
ou da biblioteca ACR.UserDialogs Nuget
UserDialogs.Instance.ShowLoading("Loading");
fonte
@MengTim, para corrigir o problema de vários toast na solução de @ alex-chengalan, simplesmente envolvi tudo dentro de
ShowAlert()
uma verificação para ver sealert
ealertDelay
são nulos, então dentroDismissMessage
, anuladosalert
ealertDelay
.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; } }
Isso pareceu pelo menos esclarecer o travamento da IU, se você está procurando uma solução rápida. Eu estava tentando exibir o brinde na navegação para uma nova página e acredito que a
PresentViewController
configuração estava basicamente cancelando minha navegação. Desculpe, não comentei no tópico, minha reputação é muito baixa :(fonte
Esta é minha
ShowAlert
versão melhorada da versão de Ian Warburton para garantir que o brinde seja exibido mesmo na página pop-up. Além disso, a torrada é dispensada se o usuário clicar fora dela. Eu useiUIAlertControllerStyle.ActionSheet
aquele visual como torradas, mas também funciona comUIAlertControllerStyle.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); }); }
Espero que isso ajude alguém!
fonte
Não há nenhum mecanismo embutido no Formulários, mas este pacote nuget fornece algo semelhante
https://github.com/EgorBo/Toasts.Forms.Plugin
Nota: Estes não são toasts no estilo Android, conforme solicitado na pergunta, mas no estilo UWP, que são notificações de todo o sistema.
fonte
Eu uso https://github.com/ishrakland/Toast/ Em https://www.nuget.org/packages/Plugin.Toast/
Exemplo CrossToastPopUp.Current.ShowToastMessage ("Carregando", Plugin.Toast.Abstractions.ToastLength.Short);
Experimente, é ótimo
fonte
Personalizei um pop-up personalizado com Rg.Plugins.Popup NuGet, este é um exemplo:
<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>
em seguida, em sua página de conteúdo base, você pode adicionar o seguinte código, para mostrar e ocultar o "brinde" depois de um tempo:
public async void showpopup(string msg) { await Navigation.PushPopupAsync(new Toast(msg)); await Task.Delay(3000); await Navigation.PopPopupAsync(true); }
fonte
As respostas do iOS acima funcionaram para mim, mas para um pequeno problema - um aviso: Tente apresentar UIAlertController ... cuja visualização não está na hierarquia da janela!
Depois de alguma pesquisa, encontrei esta resposta não relacionada que ajudou. O autor da postagem comentou "Isso parece estúpido, mas funciona", o que está certo em ambos os casos.
Portanto, modifiquei a função ShowAlert () acima com estas linhas, que parecem funcionar:
var rootVC = UIApplication.SharedApplication.KeyWindow.RootViewController; while ( rootVC.PresentedViewController != null) { rootVC = rootVC.PresentedViewController; } rootVC.PresentViewController( alert, true, null);
fonte
Para 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); }
fonte
Você pode usar
DisplayAlert("", "", "", "" );
fonte