首页 文章

Xamarin Forms的Toast等效物

提问于
浏览
37

是否有任何方法使用Xamarin Forms(不是Android或iOS特定的)来弹出,就像Android与Toast一样,不需要用户交互,并在(短)时间后消失?

从搜索所有我看到的是需要用户点击消失的警报 .

7 回答

  • 3

    这是我用来在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();
        }
    
  • 3

    我们'd normally use Egors Toasts plugin, but as it requires permissions on iOS for a current project we'使用Rg.Plugins.Popup nuget(https://github.com/rotorgames/Rg.Plugins.Popup)走了一条不同的路线 .

    我写了一个类型为PopupPage的基本xaml / cs页面,

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

    并让它由服务创建,您在app开始注册的接口或使用Xamarin.Forms.DependencyService来获取服务也是可行的 .

    PopupPage派生页面上的服务新闻,并且确实如此

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

    用户可以通过点击页面显示外部来取消弹出页面(假设它没有填满屏幕) .

    这似乎在iOS / Droid上工作愉快,但如果有人知道这是一种冒险的方法,我愿意纠正 .

  • 1

    @MengTim,为了修复@ alex-chengalan解决方案中的多个Toast问题,我只是在ShowAlert()中包装所有内容,检查alert和alertDelay是否为null,然后在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;
            }
        }
    

    如果您正在寻找快速解决方案,那似乎至少可以清除UI挂起 . 我试图在导航到新页面时显示吐司,并且相信正在设置的PresentViewController基本上取消了我的导航 . 对不起,我没有在帖子内发表评论,我的名声太低了:(

  • 78

    Forms中没有内置机制,但是这个nuget包提供了类似的东西

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

    注意:这些不是问题中所要求的Android风格的祝酒词,而是UWP样式的祝酒词,它们是系统范围的通知 .

  • 2

    这里's a version of Alex Chengalan'的iOS code避免了在显示多条消息时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();
                }
            }
        }
    
  • 3

    除了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 实际上需要将高度保持在最低限度 .

  • 2

    有一个简单的解决方案 . 通过使用DependencyService,您可以轻松地在Android和iOS中获得Toast-Like方法 .

    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

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

相关问题