如何在Xamarin中创建跨平台弹出对话框?

时间:2017-08-09 20:17:38

标签: xamarin

在我们的Xamarin移动应用程序中,我需要显示一个基于计时器的弹出对话框。基本上,如果用户没有单击“确定”按钮,则对话框仍应在十秒钟内消失。

在网上,有人提到为Android和iOS创建自定义对话框。但是,我没有找到任何关于创建跨平台对话框的参考。

似乎有第三方nuget包创建弹出对话框 -  http://www.sparkhound.com/learn/blog/creating-a-modal-popup-dialog-in-xamarin-forms,但是,我不想使用第三方软件包。另外,我不知道该库是否支持基于计时器的对话框。

有没有办法创建一个简单的跨平台对话框?从使用角度来看,这是我想的原型:

 static void DisplayAlert(string title, string body, int msec);

2 个答案:

答案 0 :(得分:2)

答案

这是我在Xamarin.Forms中创建的自定义弹出窗口。它包括一些奇特的动画,甚至模糊背景。我已经在我构建的几个应用程序中成功使用了它。

您可以通过调用ShowView来触发此自定义弹出窗口。它有一个计时器,将在10秒内解散,或者你可以通过拨打HideView来解雇它。

代码

自定义弹出基类

using System;
using System.Threading.Tasks;

using Xamarin.Forms;

namespace MyNamespace
{
    public abstract class OverlayContentView : ContentView
    {
        #region Constant Fields
        readonly BoxView _backgroundOverlayBoxView;
        readonly Frame _overlayFrame;
        readonly RelativeLayout _relativeLayout;
        #endregion

        #region Fields
        View _overlayContent;
        #endregion

        #region Constructors
        protected OverlayContentView(bool isChildOfNavigationPage)
        {
            _backgroundOverlayBoxView = new BoxView
            {
                BackgroundColor = ColorConstants.WhiteWith75Opacity
            };
            _backgroundOverlayBoxView.Opacity = 0;

            _overlayFrame = new Frame
            {
                HasShadow = true,
                BackgroundColor = Color.White
            };
            _overlayFrame.Scale = 0;

            _relativeLayout = new RelativeLayout();
            Func<RelativeLayout, double> getOverlayContentHeight = (p) => OverlayContent.Measure(p.Width, p.Height).Request.Height;
            Func<RelativeLayout, double> getOverlayContentWidth = (p) => OverlayContent.Measure(p.Width, p.Height).Request.Width;

            _relativeLayout.Children.Add(_backgroundOverlayBoxView,
                   Constraint.Constant(-10),
                   Constraint.Constant(0),
                  Constraint.RelativeToParent(parent => parent.Width + 20),
                Constraint.RelativeToParent(parent => parent.Height)
               );
            _relativeLayout.Children.Add(_overlayFrame,
                Constraint.RelativeToParent(parent => parent.Width / 2 - getOverlayContentWidth(parent) / 2 - 25),
                Constraint.RelativeToParent(parent =>
                    {
                        switch (isChildOfNavigationPage)
                        {
                            case true:
                                return parent.Height / 4 - getOverlayContentHeight(parent) / 2;

                            default:
                                return parent.Height / 2 - getOverlayContentHeight(parent) / 2 - 10;
                        }
                    }),

                Constraint.RelativeToParent(parent => getOverlayContentWidth(parent) + 50),
                Constraint.RelativeToParent(parent => getOverlayContentHeight(parent) + 40)
              );
        }
        #endregion

        #region Properties
        public View OverlayContent
        {
            get => _overlayContent;
            set
            {
                _overlayContent = value;
                _overlayContent.Scale = 0;

                _overlayFrame.Content = _overlayContent;

                Content = _relativeLayout;
            }
        }
        #endregion

        #region Methods
        public void ShowView(bool shouldDisappearAfterTimeoutExpires = false, int timeoutInSeconds = 10)
        {
            const uint overlayContentViewAnimationTime = 300;
            const double overlayContentViewMaxSize = 1.05;
            const double overlayContentViewNormalSize = 1;

            Device.BeginInvokeOnMainThread(async () =>
            {
                IsVisible = true;
                _backgroundOverlayBoxView.Opacity = 1;

                await Task.WhenAll(OverlayContent?.ScaleTo(overlayContentViewMaxSize, overlayContentViewAnimationTime, Easing.CubicOut),
                                    _overlayFrame?.ScaleTo(overlayContentViewMaxSize, overlayContentViewAnimationTime, Easing.CubicOut));

                await Task.WhenAll(OverlayContent?.ScaleTo(overlayContentViewNormalSize, overlayContentViewAnimationTime, Easing.CubicOut),
                                    _overlayFrame?.ScaleTo(overlayContentViewNormalSize, overlayContentViewAnimationTime, Easing.CubicOut));

                if (!shouldDisappearAfterTimeoutExpires)
                    return;

                await Task.Delay(TimeSpan.FromSeconds(timeoutInSeconds));

                HideView();
            });
        }

        public void HideView()
        {
            Device.BeginInvokeOnMainThread(async () =>
            {
                await this.FadeTo(0);

                IsVisible = false;
                InputTransparent = true;
                Opacity = 1;

                _backgroundOverlayBoxView.Opacity = 0;
                OverlayContent.Scale = 0;
                _overlayFrame.Scale = 0;
            });
        }
        #endregion
    }
}

自定义弹出窗口的实现

using Xamarin.Forms;

namespace MyNamespace
{
    public class WelcomeView : OverlayContentView
    {
        public WelcomeView() : base(true)
        {
            const string titleText = "Welcome";
            const string bodyText = "Enjoy InvestmentDataSampleApp";
            const string okButtonText = "Ok, thanks!";

            var titleLabel = new Label
            {
                FontAttributes = FontAttributes.Bold,
                Text = titleText,
                HorizontalTextAlignment = TextAlignment.Center
            };

            var bodyLabel = new Label
            {
                Text = bodyText,
                HorizontalTextAlignment = TextAlignment.Center
            };

            var okButton = new Button
            {
                TextColor = Color.White,
                FontAttributes = FontAttributes.Bold,
                Margin = new Thickness(5),
                Text = okButtonText,
                BackgroundColor = new Color(0, 0, 0, 0.75),
                TextColor = Color.White,
                BorderWidthProperty = 1,
                BorderColor = new Color(0, 0, 0, 0.75),
            };
            okButton.Clicked += (sender, e) => this.HideView();

            var textAndButtonStack = new StackLayout
            {
                HorizontalOptions = LayoutOptions.CenterAndExpand,
                Spacing = 20,
                Children = {
                    titleLabel,
                    bodyLabel,
                    okButton
                }
            };

            OverlayContent = textAndButtonStack;
        }
    }
}

示例应用

作为参考,这是一个已实现自定义弹出窗口的示例应用程序: https://github.com/brminnick/InvestmentDataSampleApp

enter image description here

答案 1 :(得分:0)

我建议您看一下这篇文章,我在一段时间前回答:Display a popup with xamarin forms

即使这样的系统需要花费一些时间来实现,它也使您可以从应用程序中的任何位置调用任何对话框,而无需将对话框嵌入内容页面中。

如果您想让对话框计时,可以简单地用

进行调用
Dialogs.ShowLoading();
Xamarin.Forms.Device.StartTimer(TimeSpan.FromSeconds(5), () => { Dialogs.Hide();
    return false;
});