Тост эквивалент для форм Xamarin
Есть ли способ использовать Xamarin Forms (не для Android или iOS), чтобы всплывающее окно, как Android делает с Toast, которое не требует взаимодействия с пользователем и исчезает через (короткий) промежуток времени?
Из всех поисков я вижу предупреждения, которые требуют кликов пользователей, чтобы уйти.
Ответы
Ответ 1
Для этого есть простое решение. Используя DependencyService, вы можете легко получить подход Toast-Like в Android и iOS.
Создайте интерфейс в вашем общем пакете.
public interface IMessage
{
void LongAlert(string message);
void ShortAlert(string message);
}
Раздел 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();
}
}
}
раздел iOS
В iOs нет собственного решения, такого как Toast, поэтому нам нужно реализовать наш собственный подход.
[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();
}
}
}
}
Обратите внимание, что на каждой платформе мы должны регистрировать наши классы в DependencyService.
Теперь вы можете получить доступ к сервису Toast в любом месте нашего проекта.
DependencyService.Get<IMessage>().ShortAlert(string message);
DependencyService.Get<IMessage>().LongAlert(string message);
Ответ 2
Вот версия кода Алекса Ченгалана для iOS, которая предотвращает зависание пользовательского интерфейса при отображении нескольких сообщений...
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();
}
}
}
Ответ 3
Добавив Алексу ответ, вот вариант 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();
}
}
Окраска и стилизация зависит от вас, на самом деле MaxHeight
требуется, чтобы высота была минимальной.
Ответ 4
Проверьте эти пакеты также для диалогов и тостов оповещения:
Ответ 5
Вот фрагмент кода, который я использую, чтобы показать тост в 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();
}
Ответ 6
Обычно мы используем плагин Egors Toasts, но поскольку для текущего проекта требуются разрешения для iOS, мы пошли другим путем, используя Rg.Plugins.Popup nuget (https://github.com/rotorgames/Rg.Plugins.Popup).
Я написал основную страницу xaml/cs типа 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">
...
и создать его службой, интерфейс которой вы регистрируетесь при запуске приложения или используете Xamarin.Forms.DependencyService для извлечения сервиса, также будет жизнеспособным.
Служебные новости на странице, созданной PopupPage, и
await PopupNavigation.PushAsync(newToastPage);
await Task.Delay(2000);
await PopupNavigation.PopAllAsync();
Всплывающая страница может быть уволена пользователем, нажав вне экрана страницы (при условии, что она не заполнила экран).
Это похоже на работу с iOS/Droid, но я открыт для исправления, если кто-то знает, что это рискованный способ сделать это.
Ответ 7
@MengTim, чтобы исправить проблему с несколькими тостами в решении @alex-chengalan, я просто обернул все в ShowAlert() с проверкой, чтобы видеть, являются ли alert и alertDelay нулевыми, затем в DismissMessage обнулены alert и 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;
}
}
Это, по крайней мере, прояснило зависание пользовательского интерфейса, если вы ищете быстрое решение. Я пытался отобразить тост при переходе на новую страницу и считаю, что установленный PresentViewController по сути отменял мою навигацию. Извините, я не прокомментировал в теме, моя репутация слишком низкая :(
Ответ 8
Вы можете использовать пакет Acr.UserDialogs из nuget и кода, как показано ниже,
Acr.UserDialogs.UserDialogs.Instance.Toast(Message, new TimeSpan(3));
Ответ 9
В Forms нет встроенного механизма, но этот пакет nuget предоставляет нечто подобное
https://github.com/EgorBo/Toasts.Forms.Plugin
Примечание. Это не тосты в стиле Android, как указано в вопросе, а тосты в стиле UWP, которые являются общесистемными уведомлениями.
Ответ 10
Это моя улучшенная версия ShowAlert
версии Ian Warburton, чтобы тост отображался даже на всплывающей странице. Кроме того, тост отклоняется, если пользователь щелкает снаружи тоста. Я использовал UIAlertControllerStyle.ActionSheet
который выглядит как тост, но он также работает с 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);
});
}
Я надеюсь, что это поможет кому-то!
Ответ 11
Вы можете использовать IUserDialog NuGet и просто использовать его toastAlert
var toastConfig = new ToastConfig("Toasting...");
toastConfig.SetDuration(3000);
toastConfig.SetBackgroundColor(System.Drawing.Color.FromArgb(12, 131, 193));
UserDialogs.Instance.Toast(toastConfig);
Ответ 12
Ответы iOS выше помогли мне, но для одной маленькой проблемы - предупреждение: Попытайтесь представить UIAlertController..., чье представление не находится в иерархии окон!
После некоторых поисков я наткнулся на этот несвязанный ответ, который помог. Постер прокомментировал: "Это выглядит глупо, но работает", что верно по обоим пунктам.
Итак, я изменил функцию ShowAlert() выше с этими строками, которые, кажется, работают:
var rootVC = UIApplication.SharedApplication.KeyWindow.RootViewController;
while ( rootVC.PresentedViewController != null) {
rootVC = rootVC.PresentedViewController;
}
rootVC.PresentViewController( alert, true, null);
Ответ 13
Для 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);
}
Ответ 14
Проверьте plugin.toast v 2.1.2 для Android, iOS и UWP
Ответ 15
Вы можете использовать DisplayAlert("", "", "", "" );