可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is there any way using Xamarin Forms (not android or ios specific) to have a popup, like Android does with toast, that needs no user interaction and goes away after a period of time?
From searching around all I'm seeing are alerts that need user clicks to go away.
回答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 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(); } } } }
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);
回答2:
Check these packages too for Alert Dialogues and Toasts:
回答3:
There is no built-in mechanism in Forms, but this nuget package supplies something similar
https://github.com/EgorBo/Toasts.Forms.Plugin
回答4:
Here is a code snippet that I am using to show the toast in 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(); }
回答5:
We'd normally use Egors Toasts plugin, but as it requires permissions on iOS for a current project we've gone a different route using Rg.Plugins.Popup nuget (https://github.com/rotorgames/Rg.Plugins.Popup).
I wrote a basic xaml/cs page of type 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"> ...
and have it created by a service, whose interface you register at app start or use Xamarin.Forms.DependencyService to fetch the service would be viable too.
The service news up the PopupPage derived page, and does
await PopupNavigation.PushAsync(newToastPage); await Task.Delay(2000); await PopupNavigation.PopAllAsync();
The Popup page can be dismissed by the user by tapping outside the page display (assuming it hasn't filled the screen).
This seems to work happily on iOS/Droid, but I'm open to correction if anyone knows what this is a risky way of doing it.
回答6:
@MengTim, to fix the multiple toast issue in @alex-chengalan's solution, I simply wrapped everything within ShowAlert() with a check to see if alert and alertDelay are null, then within DismissMessage, nulled out alert and 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; } }
That seemed to at least clear up the UI hang, if you are looking for a quick fix. I was trying to display the toast on navigation to a new page, and believe that the PresentViewController being set was essentially cancelling out my navigation. Sorry I did not comment within the thread, my reputation is too low :(