Bánh mì nướng tương đương với Xamarin Forms


89

Có cách nào sử dụng Xamarin Forms (không dành riêng cho Android hoặc iOS) để có cửa sổ bật lên, giống như Android làm với Toast, không cần người dùng tương tác và biến mất sau một khoảng thời gian (ngắn) không?

Từ việc tìm kiếm xung quanh, tất cả những gì tôi thấy là các cảnh báo cần người dùng nhấp chuột để biến mất.

Câu trả lời:


170

Có một giải pháp đơn giản cho điều này. Bằng cách sử dụng DependencyService, bạn có thể dễ dàng có được cách tiếp cận Toast-Like trong cả Android và iOS.

Tạo một giao diện trong gói chung của bạn.

public interface IMessage
{
    void LongAlert(string message);
    void ShortAlert(string message);
}

Phần 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();
        }
    }
}

phần iOS

Trong iOs không có giải pháp gốc nào như Toast, vì vậy chúng tôi cần triển khai cách tiếp cận của riêng mình.

[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();
            }
        }
    }
}

Xin lưu ý rằng trong mỗi nền tảng, chúng tôi phải đăng ký các lớp học của mình với DependencyService.

Bây giờ bạn có thể truy cập dịch vụ Toast ở bất kỳ đâu trong dự án của chúng tôi.

DependencyService.Get<IMessage>().ShortAlert(string message); 
DependencyService.Get<IMessage>().LongAlert(string message);

20
Đây là câu trả lời tốt nhất cho câu hỏi này. Không cần plugin hoặc thư viện của bên thứ ba.
Bret Faller

4
trong dòng DependencyService, tôi nhận được "Tham chiếu đối tượng không được đặt thành một thể hiện của đối tượng."
Joyce de Lanna

5
Vâng, đây là câu trả lời tốt nhất cho đến nay, tôi thích dịch vụ phụ thuộc
Lutaaya Huzaifah Idris

1
Toàn thắng. Bạn có tình cờ có một phiên bản UWP của cái này không?
Nieminen

1
@MengTim Tôi dường như đã sửa giao diện người dùng bị kẹt bằng cách tạo cảnh báo và bộ hẹn giờ mới mọi lúc. Cả hai đều cần được chuyển đến DismissMessage.
Ian Warburton

13

Đây là phiên bản iOS của Alex Chengalan để tránh giao diện người dùng bị dính khi nhiều thông báo được hiển thị ...

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();
            }
        }
    }

10

Bạn có thể sử dụng Gói Acr.UserDialogs từ nuget và mã như bên dưới,

Acr.UserDialogs.UserDialogs.Instance.Toast(Message, new TimeSpan(3));

9

Chúng tôi thường sử dụng plugin Egors Toasts, nhưng vì nó yêu cầu quyền trên iOS cho một dự án hiện tại, chúng tôi đã đi một con đường khác bằng cách sử dụng Rg.Plugins.Popup nuget ( https://github.com/rotorgames/Rg.Plugins.Popup ).

Tôi đã viết một trang xaml / cs cơ bản thuộc loại 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">
...

và có nó được tạo bởi một dịch vụ, có giao diện mà bạn đăng ký khi khởi động ứng dụng hoặc sử dụng Xamarin.Forms.DependencyService để tìm nạp dịch vụ cũng sẽ khả thi.

Dịch vụ đưa tin lên trang dẫn xuất PopupPage và

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

Người dùng có thể loại bỏ trang Cửa sổ bật lên bằng cách chạm vào bên ngoài màn hình trang (giả sử trang này chưa lấp đầy màn hình).

Điều này có vẻ hoạt động tốt trên iOS / Droid, nhưng tôi sẵn sàng sửa chữa nếu ai đó biết đây là một cách làm rủi ro.


cửa sổ bật lên rg rất tuyệt. Tôi thực hiện cách giải quyết tương tự để tải hiển thị hoặc chỉ báo hoạt động trên toàn trang. vấn đề với các plugin khác là chúng phụ thuộc vào các chức năng không đồng bộ và luồng chính nhưng rg popup có thể chạy trên luồng thứ 2 nên rất hữu ích. thực sự là ý tưởng hay nhưng tôi muốn có giao diện gốc giống như trên bánh mì nướng android.
Emil,

Cho đến nay đây là phương pháp tốt nhất để nâng cốc chúc mừng đa nền tảng. Rg.Popup là siêu linh hoạt và tôi sử dụng nó trong hầu hết các dự án. Không cần sử dụng các plugin hoặc mã nền tảng khác để hiển thị chúc mừng,
GiampaoloGabba

8

Thêm vào câu trả lời của Alex, đây là biến thể 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();
  }
}

Màu sắc và kiểu dáng là tùy thuộc vào bạn, MaxHeightthực sự bắt buộc phải giữ chiều cao ở mức tối thiểu.


Vì vậy, đăng ký nó như một Dịch vụ phụ thuộc không cần cho UWP?
Olorunfemi Ajibulu

Nó hoạt động chính xác như hai biến thể còn lại. Có, một dịch vụ phụ thuộc.
Gábor

7

Bạn có thể sử dụng IUserDialog NuGet và chỉ cần sử dụng toastAlert

var toastConfig = new ToastConfig("Toasting...");
toastConfig.SetDuration(3000);
toastConfig.SetBackgroundColor(System.Drawing.Color.FromArgb(12, 131, 193));

UserDialogs.Instance.Toast(toastConfig);

4

Đây là đoạn mã mà tôi đang sử dụng để hiển thị bánh mì nướng trong 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();
    }

4

Tôi muốn giới thiệu Plugin.Toastthư viện từ nuget. Nó hoạt động tốt.

CrossToastPopUp.Current.ShowToastMessage("my toast message");

hoặc từ ACR.UserDialogs Nuget libriary

UserDialogs.Instance.ShowLoading("Loading");

Có cách nào để di chuyển nó lên đầu không? Tùy chỉnh và hiển thị bội số?
G_Money

Không. thư viện này chỉ hỗ trợ các tin nhắn bánh mì nướng cơ bản. bạn chỉ có thể thay đổi bg và màu văn bản và thời lượng của tin nhắn.
Fk Bey

4

@MengTim, để khắc phục sự cố nhiều bánh mì nướng trong giải pháp của @ alex-chengalan, tôi chỉ cần gói mọi thứ bên trong ShowAlert()bằng một kiểm tra để xem nếu alertalertDelaycó rỗng không, sau đó bên trong DismissMessage, vô hiệu hóa alertalertDelay.

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;
        }
    }

Điều đó dường như ít nhất cũng giải quyết được tình trạng treo giao diện người dùng, nếu bạn đang tìm cách khắc phục nhanh chóng. Tôi đang cố gắng hiển thị bánh mì nướng trên điều hướng đến một trang mới và tin rằng việc PresentViewControllerthiết lập về cơ bản đang hủy bỏ điều hướng của tôi. Xin lỗi, tôi đã không bình luận trong chủ đề, danh tiếng của tôi quá thấp :(


1

Không có cơ chế tích hợp trong Biểu mẫu, nhưng gói nuget này cung cấp một thứ tương tự

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

Lưu ý: Đây không phải là chúc mừng kiểu Android như được yêu cầu trong câu hỏi mà là chúc mừng kiểu UWP là thông báo trên toàn hệ thống.


5
Android Toast có nghĩa là một điều hoàn toàn khác - đó là một thông báo bật lên. Thư viện này dành cho các thông báo trên toàn hệ thống.
Vojtěch Sázel

Đáng lẽ phải đọc bình luận trước khi tôi cài đặt thư viện chỉ để nhận thấy rằng đây không phải là những lời chúc mừng phong cách android .. Hãy làm rõ điều đó trong câu trả lời.
findusl

1

Đây là ShowAlertphiên bản cải tiến của tôi từ phiên bản của Ian Warburton để đảm bảo rằng bánh mì nướng được hiển thị ngay cả trên trang bật lên. Hơn nữa, bánh mì nướng sẽ bị loại bỏ nếu người dùng nhấp vào bên ngoài bánh mì nướng. Tôi đã sử dụng UIAlertControllerStyle.ActionSheetcái nhìn thích bánh mì nướng nhưng nó cũng hoạt động vớiUIAlertControllerStyle.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);
        });
    }

Tôi hy vọng điều này sẽ giúp một ai đó!



1

Tôi đã tùy chỉnh một cửa sổ bật lên tùy chỉnh với Rg.Plugins.Popup NuGet đây là một ví dụ:

 <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>

thì trong trang cơ sở của bạn, bạn có thể thêm mã sau để hiển thị và ẩn "bánh mì nướng" sau một thời gian:

public async void showpopup(string msg)
    {
        await Navigation.PushPopupAsync(new Toast(msg));
        await Task.Delay(3000);
        await Navigation.PopPopupAsync(true);   
    }

0

Các câu trả lời iOS ở trên phù hợp với tôi nhưng đối với một vấn đề nhỏ - cảnh báo: Cố gắng trình bày UIAlertController ... có chế độ xem không nằm trong hệ thống phân cấp cửa sổ!

Sau một số tìm kiếm, tôi đã tìm thấy câu trả lời không liên quan này này đã giúp ích. Người đăng bình luận "Điều này trông ngu ngốc nhưng hiệu quả", điều này đúng về cả hai tính.

Vì vậy, tôi đã sửa đổi hàm ShowAlert () ở trên với các dòng này, có vẻ như hoạt động:

    var rootVC = UIApplication.SharedApplication.KeyWindow.RootViewController;
    while ( rootVC.PresentedViewController != null) {
        rootVC = rootVC.PresentedViewController;
    }
    rootVC.PresentViewController( alert, true, null);

Dang - Tôi thấy một phiên bản thậm chí còn tốt hơn của điều này bên dưới từ @ Pierre-Alexandre Flèche. Làm thế nào mà tôi đã bỏ lỡ nó trước đây?
bobwki

0

Đối với 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);
    }

-5

Bạn có thể dùng DisplayAlert("", "", "", "" );


1
Điều này hoàn toàn không phản ứng giống như nâng cốc, nó cần một hành động để tiếp tục.
CennoxX
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.