是否有使用Xamarin Forms(而不是Android或iOS特定)创建弹出窗口的方法,就像Android使用Toast一样,不需要用户交互,并且在(短暂的)一段时间后消失?
从搜索中发现,所有我看到的都需要用户点击才能消失的警报。
是否有使用Xamarin Forms(而不是Android或iOS特定)创建弹出窗口的方法,就像Android使用Toast一样,不需要用户交互,并且在(短暂的)一段时间后消失?
从搜索中发现,所有我看到的都需要用户点击才能消失的警报。
这有一个简单的解决方案。通过使用DependencyService,您可以在Android和iOS中轻松地获得类似Toast的方法。
在通用包中创建一个接口。
public interface IMessage
{
void LongAlert(string message);
void ShortAlert(string message);
}
安卓板块
[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 Your.Namespace
{
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注册我们的类。DependencyService.Get<IMessage>().ShortAlert(string message);
DependencyService.Get<IMessage>().LongAlert(string message);
Acr.UserDialogs.UserDialogs.Instance.Toast(Message, new TimeSpan(3));
这是 Alex Chengalan 的 iOS 代码 的一个版本,避免了当显示多个消息时 UI 卡顿的问题...
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();
}
}
}
SnackBar
,在本地支持的平台上使用原生实现,因为Toast
已在API级别30中弃用。没有操作的SnackBar
等效于一个Toast。
该方法已在API级别30中弃用。自定义Toast视图已被弃用。应用程序可以使用makeText(android.content.Context, java.lang.CharSequence, int)方法创建标准文本Toast,或在前台时使用Snackbar。从Android Build.VERSION_CODES#R开始,定位API级别Build.VERSION_CODES#R或更高版本且在后台的应用程序将不会显示自定义Toast视图。(来源)。
using Xamarin.CommunityToolkit.Extensions;
await this.DisplayToastAsync("This is a Toast Message");
await this.DisplayToastAsync("This is a Toast Message for 5 seconds", 5000);
您可以指定SnackBar消失的持续时间(以毫秒为单位),或者保留默认时间,即3秒。
官方代码库 https://github.com/xamarin/XamarinCommunityToolkit
官方文档 https://learn.microsoft.com/en-us/xamarin/community-toolkit/
DisplayToastAsync()
,而不是从页面实例(this
)上调用,将Toast 锚定在某个视图上(如上面的屏幕截图):<Button x:name="floatingButton" .../>
await floatingButton.DisplayToastAsync("This is a Toast Message for 5 seconds", 5000);
您可以像下面的示例一样设置Toast的圆角和填充:
var messageOptions = new MessageOptions
{
Message = "Toast with Padding and round corner",
Foreground = Color.White,
Font = Font.SystemFontOfSize(16),
Padding = new Thickness(20)
};
var options = new ToastOptions
{
MessageOptions = messageOptions,
CornerRadius = new Thickness(40, 40, 0, 0),
BackgroundColor = Color.FromHex("#CC0000")
};
await this.DisplayToastAsync(options);
PS:相同的属性可以应用于SnackBar
视图。
如果xct SnackBar
提供的内容无法满足您的要求,或者您想要显示不仅是文本而是一些复杂的视图,则可能需要使用弹出窗口。
继Alex的回答之后,这里是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
实际上是必需的,以保持高度最小。
我们通常会使用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上似乎运作良好,但如果有人知道这种方法存在风险,请指正。
您可以使用 IUserDialog NuGet 并直接使用其 toastAlert 功能。
var toastConfig = new ToastConfig("Toasting...");
toastConfig.SetDuration(3000);
toastConfig.SetBackgroundColor(System.Drawing.Color.FromArgb(12, 131, 193));
UserDialogs.Instance.Toast(toastConfig);
@MengTim,为了解决@alex-chengalan的解决方案中的多个toast问题,我只需在ShowAlert()
中包含一个检查,以查看alert
和alertDelay
是否为空,然后在DismissMessage
中将alert
和alertDelay
设为null即可。
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;
}
}
如果您正在寻找一个快速解决方案,那看起来至少可以清除UI挂起问题。我试图在导航到新页面时显示toast,并认为设置的PresentViewController
本质上取消了我的导航。很抱歉我没有在帖子中发表评论,我的声望太低了:(
我建议从nuget
下载Plugin.Toast
库。它功能良好。
CrossToastPopUp.Current.ShowToastMessage("my toast message");
或者从ACR.UserDialogs Nuget库中获取
UserDialogs.Instance.ShowLoading("Loading");
这里是我在Xamarin.iOS中使用的代码片段,用于显示toast:
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();
}
MainActivity.cs
中 注册 接口。在LoadApplication(new App())
之前添加这行代码DependencyService.Register<IMessage, MessageAndroid>();
。 - Sadra M.