PopupManager.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using System;
  2. using Syncfusion.XForms.PopupLayout;
  3. using Xamarin.Forms;
  4. namespace InABox.Mobile
  5. {
  6. public interface IPopupManager
  7. {
  8. bool Initialise();
  9. }
  10. public class PopupManagerConfiguration
  11. {
  12. public static double? DefaultHeight => 700;
  13. public static double? DefaultWidth => 350;
  14. public static double? AutoSize => null;
  15. public static RelativePosition? CenterOnScreen => null;
  16. public double? RequestedHeight { get; set; } = DefaultHeight;
  17. public double? RequestedWidth { get; set; } = DefaultWidth;
  18. public AutoSizeMode SizeMode
  19. {
  20. get => (Equals(RequestedHeight,AutoSize) && Equals(RequestedWidth,AutoSize))
  21. ? AutoSizeMode.Both
  22. : Equals(RequestedHeight,AutoSize)
  23. ? AutoSizeMode.Height
  24. : Equals(RequestedWidth,AutoSize)
  25. ? AutoSizeMode.Width
  26. : AutoSizeMode.None;
  27. set
  28. {
  29. RequestedHeight = value is AutoSizeMode.Both or AutoSizeMode.Height ? AutoSize : DefaultHeight;
  30. RequestedWidth = value is AutoSizeMode.Both or AutoSizeMode.Width ? AutoSize : DefaultWidth;
  31. }
  32. }
  33. public bool ShowHeader { get; set; } = false;
  34. public bool ShowFooter { get; set; } = false;
  35. public int Padding { get; set; } = 10;
  36. public int CornerRadius { get; set; } = 5;
  37. public bool Modal { get; set; } = false;
  38. public RelativePosition? Position { get; set; } = CenterOnScreen;
  39. }
  40. public static class PopupManager
  41. {
  42. private static SfPopupLayout _popup = null;
  43. private static ContentPage FindParentPage(Element view)
  44. {
  45. if (view is ContentPage page)
  46. return page;
  47. return FindParentPage(view.Parent);
  48. }
  49. public static void DisplayError(Element view, string message)
  50. {
  51. MobileLogging.Log("Unable to create Popup Layout!");
  52. var page = FindParentPage(view);
  53. Device.BeginInvokeOnMainThread(() =>
  54. {
  55. page.DisplayAlert("Error", message, "OK");
  56. });
  57. }
  58. public static bool Initialise()
  59. {
  60. var service = DependencyService.Get<IPopupManager>();
  61. return service?.Initialise() == true;
  62. }
  63. public static void ShowPopup(VisualElement parent, Func<View> view, PopupManagerConfiguration config = null)
  64. {
  65. if (_popup == null && Initialise())
  66. _popup = new SfPopupLayout();
  67. if (_popup == null)
  68. {
  69. DisplayError(parent, "Unable to create Popup!\nPlease try again or restart the application.");
  70. return;
  71. }
  72. var cfg = config ?? new PopupManagerConfiguration();
  73. _popup.PopupView.AutoSizeMode = cfg.SizeMode;
  74. if (Equals(cfg.RequestedHeight, PopupManagerConfiguration.AutoSize))
  75. _popup.PopupView.ClearValue(VisualElement.HeightRequestProperty);
  76. else
  77. _popup.PopupView.HeightRequest = cfg.RequestedHeight!.Value;
  78. if (Equals(cfg.RequestedWidth, PopupManagerConfiguration.AutoSize))
  79. _popup.PopupView.ClearValue(VisualElement.WidthRequestProperty);
  80. else
  81. _popup.PopupView.WidthRequest = cfg.RequestedWidth!.Value;
  82. _popup.PopupView.ShowHeader = cfg.ShowHeader;
  83. _popup.PopupView.ShowFooter = cfg.ShowFooter;
  84. _popup.PopupView.PopupStyle.CornerRadius = cfg.CornerRadius;
  85. _popup.StaysOpen = cfg.Modal;
  86. _popup.PopupView.ContentTemplate = new DataTemplate(() =>
  87. {
  88. Grid grid = new Grid() { Padding = cfg.Padding };
  89. grid.Children.Add(view());
  90. return grid;
  91. });
  92. if (parent is View pView && cfg.Position != PopupManagerConfiguration.CenterOnScreen)
  93. {
  94. var offset = GetOffset(parent, cfg.Position!.Value);
  95. _popup.ShowRelativeToView(pView, cfg.Position!.Value, offset.X, offset.Y);
  96. }
  97. else
  98. _popup.Show();
  99. }
  100. /// <summary>
  101. /// Calculates the offest of the Menu to position it at the center of the Button
  102. /// Let's not presume that all the calculations are correct - its only been tested
  103. /// against AlignToLeftOf (for top-right-hand side menu options
  104. /// </summary>
  105. /// <param name="x"></param>
  106. /// <param name="y"></param>
  107. private static Point GetOffset(VisualElement parent, RelativePosition Position)
  108. {
  109. return Position switch
  110. {
  111. // Displays the popup at the top of the given view.
  112. RelativePosition.AlignTop => new Point(parent.Width / 2F, parent.Height / 2F),
  113. // Displays the popup to the left of the given view.</summary>
  114. RelativePosition.AlignToLeftOf => new Point(parent.Width / 2F, parent.Height / 2F),
  115. // Displays the popup to the right of the given view.</summary>
  116. RelativePosition.AlignToRightOf => new Point(0F - (parent.Width / 2F), parent.Height / 2F),
  117. // Displays the popup at the bottom of the given view.</summary>
  118. RelativePosition.AlignBottom => new Point(parent.Width / 2F, 0F - (parent.Height / 2F)),
  119. // Displays the popup at the top left position of the given view.
  120. RelativePosition.AlignTopLeft => new Point(parent.Width / 2F, parent.Height / 2F),
  121. // Displays the popup at the top right position of the given view.
  122. RelativePosition.AlignTopRight => new Point(0F - (parent.Width / 2F), parent.Height / 2F),
  123. // Displays the popup at the bottom left position of the given view.
  124. RelativePosition.AlignBottomLeft => new Point(0F - (parent.Width / 2F), parent.Height / 2F),
  125. // Displays the popup at the bottom right position of the given view.
  126. RelativePosition.AlignBottomRight => new Point(0F - (parent.Width / 2F), 0F - (parent.Height / 2F)),
  127. _ => new Point()
  128. };
  129. }
  130. public static void DismissPopup()
  131. {
  132. if (_popup != null)
  133. _popup.Dismiss();
  134. }
  135. }
  136. }