web-dev-qa-db-ja.com

Xamarin Formsのトースト版

Xamarin Forms(AndroidまたはiOS固有ではない)を使用して、AndroidがToastで行うように、ユーザーの操作を必要とせずに終了するポップアップを使用する方法はありますか(短い)期間?

私が見ているすべてのものを検索すると、ユーザーのクリックが消える必要があるアラートが表示されます。

54
Jimmy

これには簡単な解決策があります。 DependencyService を使用すると、AndroidとiOSの両方でToastのようなアプローチを簡単に取得できます。

共通パッケージにインターフェースを作成します。

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セクション

IOには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);
118
Alex Chengalan

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

アレックスの答えに加えて、ここに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は実際に高さを最小に保つために必要です。

7
Gábor

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
Durai Amuthan.H

通常はEgors Toastsプラグインを使用しますが、現在のプロジェクトではiOSで権限が必要なので、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">
...

サービスによって作成されたもので、そのインターフェイスはアプリの起動時に登録するか、Xamarin.Forms.DependencyServiceを使用してサービスを取得します。

サービスはPopupPage派生ページをニュースアップし、

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

ユーザーは、ページ表示の外側をタップすることでポップアップ画面を閉じることができます(画面がいっぱいになっていない場合)。

これはiOS/Droidでうまく機能しているように見えますが、これがリスクを伴う方法であると誰かが知っていれば、修正を受け入れます。

4
Allister

@ MengTim、@ alex-chengalanのソリューションの複数のトーストの問題を修正するために、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が本質的にナビゲーションをキャンセルしていると信じていました。申し訳ありませんが、スレッド内でコメントしませんでした。評判が低すぎます:(

3
Gunnar

IUserDialog Nuget を使用して、単純にtoastAlertを使用できます。

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

UserDialogs.Instance.Toast(toastConfig);
1
mohammad kamali

これは、Ian Warburtonのバージョンの私の改良されたShowAlertバージョンで、ポップアップページでもトーストが表示されるようにします。さらに、ユーザーがトーストの外側をクリックすると、トーストは破棄されます。トーストのように見える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);
        });
    }

これが誰かを助けることを願っています!

Formsには組み込みのメカニズムはありませんが、このnugetパッケージは類似したものを提供します

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

注:これらは、質問で要求されているAndroidスタイルのトーストではなく、システム全体の通知であるUWPスタイルのトーストです。

1
Jason

NugetのAcr.UserDialogsパッケージと次のようなコードを使用できます。

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

DisplayAlert("", "", "", "" );を使用できます

0
O.Ahmadpoor

Plugin.toast v 2.1.2がAndroid、iOS、およびUWPで利用可能であることを確認してください

上記のiOSの答えは私のために働いたが、1つの小さな問題-警告:UIAlertControllerを提示しようとしています...そのビューはウィンドウ階層にありません!

いくつかの検索の後、私はこれに遭遇しました 無関係な答え これは助けました。ポスターは「これは馬鹿げているように見えるが機能している」とコメントしており、これは両方の点で正しい。

そこで、上記のShowAlert()関数を次の行で変更しました。

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

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);
    }
0
Fabien Richard