diff --git a/src/Compatibility/Core/src/Android/VisualElementTracker.cs b/src/Compatibility/Core/src/Android/VisualElementTracker.cs index 4ba17c7a9761..1dc281f38f8b 100644 --- a/src/Compatibility/Core/src/Android/VisualElementTracker.cs +++ b/src/Compatibility/Core/src/Android/VisualElementTracker.cs @@ -332,6 +332,7 @@ void UpdateClip() aView?.Invalidate(); } + [PortHandler] void UpdateIsVisible() { VisualElement view = _renderer.Element; diff --git a/src/Compatibility/Core/src/WinUI/CollectionView/FormsGridView.cs b/src/Compatibility/Core/src/WinUI/CollectionView/FormsGridView.cs index 46cc6fb20844..c376c45c7659 100644 --- a/src/Compatibility/Core/src/WinUI/CollectionView/FormsGridView.cs +++ b/src/Compatibility/Core/src/WinUI/CollectionView/FormsGridView.cs @@ -4,6 +4,7 @@ using UWPApp = Microsoft.UI.Xaml.Application; using UWPControls = Microsoft.UI.Xaml.Controls; using WScrollMode = Microsoft.UI.Xaml.Controls.ScrollMode; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -41,11 +42,11 @@ public int Span public static readonly DependencyProperty EmptyViewVisibilityProperty = DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility), - typeof(FormsGridView), new PropertyMetadata(Visibility.Collapsed)); + typeof(FormsGridView), new PropertyMetadata(WVisibility.Collapsed)); - public Visibility EmptyViewVisibility + public WVisibility EmptyViewVisibility { - get { return (Visibility)GetValue(EmptyViewVisibilityProperty); } + get { return (WVisibility)GetValue(EmptyViewVisibilityProperty); } set { SetValue(EmptyViewVisibilityProperty, value); } } diff --git a/src/Compatibility/Core/src/WinUI/CollectionView/FormsListView.cs b/src/Compatibility/Core/src/WinUI/CollectionView/FormsListView.cs index b5890f0787c4..c15ef7f2d0ed 100644 --- a/src/Compatibility/Core/src/WinUI/CollectionView/FormsListView.cs +++ b/src/Compatibility/Core/src/WinUI/CollectionView/FormsListView.cs @@ -4,6 +4,7 @@ using UwpApp = Microsoft.UI.Xaml.Application; using UwpControlTemplate = Microsoft.UI.Xaml.Controls.ControlTemplate; using UwpScrollBarVisibility = Microsoft.UI.Xaml.Controls.ScrollBarVisibility; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -25,11 +26,11 @@ public FormsListView() public static readonly DependencyProperty EmptyViewVisibilityProperty = DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility), - typeof(FormsListView), new PropertyMetadata(Visibility.Collapsed)); + typeof(FormsListView), new PropertyMetadata(WVisibility.Collapsed)); - public Visibility EmptyViewVisibility + public WVisibility EmptyViewVisibility { - get { return (Visibility)GetValue(EmptyViewVisibilityProperty); } + get { return (WVisibility)GetValue(EmptyViewVisibilityProperty); } set { SetValue(EmptyViewVisibilityProperty, value); } } diff --git a/src/Compatibility/Core/src/WinUI/CollectionView/IEmptyView.cs b/src/Compatibility/Core/src/WinUI/CollectionView/IEmptyView.cs index aa0c21535395..ffe237e83e61 100644 --- a/src/Compatibility/Core/src/WinUI/CollectionView/IEmptyView.cs +++ b/src/Compatibility/Core/src/WinUI/CollectionView/IEmptyView.cs @@ -1,10 +1,11 @@ using Microsoft.UI.Xaml; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { internal interface IEmptyView { - Visibility EmptyViewVisibility { get; set; } + WVisibility EmptyViewVisibility { get; set; } void SetEmptyView(FrameworkElement emptyView, View formsEmptyView); } } \ No newline at end of file diff --git a/src/Compatibility/Core/src/WinUI/CollectionView/ItemsViewRenderer.cs b/src/Compatibility/Core/src/WinUI/CollectionView/ItemsViewRenderer.cs index ddf1b1b16704..17b6a0038254 100644 --- a/src/Compatibility/Core/src/WinUI/CollectionView/ItemsViewRenderer.cs +++ b/src/Compatibility/Core/src/WinUI/CollectionView/ItemsViewRenderer.cs @@ -13,6 +13,7 @@ using WRect = Windows.Foundation.Rect; using Microsoft.Maui.Graphics; using Microsoft.Maui.Controls.Platform; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -472,7 +473,7 @@ protected virtual void UpdateEmptyViewVisibility() if (_emptyView != null && ListViewBase is IEmptyView emptyView) { - emptyView.EmptyViewVisibility = Visibility.Visible; + emptyView.EmptyViewVisibility = WVisibility.Visible; if (ActualWidth >= 0 && ActualHeight >= 0) _formsEmptyView?.Layout(new Rectangle(0, 0, ActualWidth, ActualHeight)); @@ -485,7 +486,7 @@ protected virtual void UpdateEmptyViewVisibility() if (_emptyViewDisplayed) { if (_emptyView != null && ListViewBase is IEmptyView emptyView) - emptyView.EmptyViewVisibility = Visibility.Collapsed; + emptyView.EmptyViewVisibility = WVisibility.Collapsed; ItemsView.RemoveLogicalChild(_formsEmptyView); } @@ -582,7 +583,7 @@ bool IsElementVisibleInContainer(FrameworkElement element, FrameworkElement cont if (element == null || container == null) return false; - if (element.Visibility != Visibility.Visible) + if (element.Visibility != WVisibility.Visible) return false; var elementBounds = element.TransformToVisual(container).TransformBounds(new WRect(0, 0, element.ActualWidth, element.ActualHeight)); diff --git a/src/Compatibility/Core/src/WinUI/FlyoutPageControl.cs b/src/Compatibility/Core/src/WinUI/FlyoutPageControl.cs index f82c84fda98d..51ec23442755 100644 --- a/src/Compatibility/Core/src/WinUI/FlyoutPageControl.cs +++ b/src/Compatibility/Core/src/WinUI/FlyoutPageControl.cs @@ -5,6 +5,7 @@ using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; using WBrush = Microsoft.UI.Xaml.Media.Brush; using WImageSource = Microsoft.UI.Xaml.Media.ImageSource; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -82,7 +83,7 @@ public FlyoutPageControl() { DefaultStyleKey = typeof(FlyoutPageControl); - DetailTitleVisibility = Visibility.Collapsed; + DetailTitleVisibility = WVisibility.Collapsed; CollapseStyle = CollapseStyle.Full; } @@ -133,9 +134,9 @@ public View DetailTitleView set { SetValue(DetailTitleViewProperty, value); } } - public Visibility DetailTitleVisibility + public WVisibility DetailTitleVisibility { - get { return (Visibility)GetValue(DetailTitleVisibilityProperty); } + get { return (WVisibility)GetValue(DetailTitleVisibilityProperty); } set { SetValue(DetailTitleVisibilityProperty, value); } } @@ -187,15 +188,15 @@ public string FlyoutTitle set { SetValue(FlyoutTitleProperty, value); } } - public Visibility FlyoutTitleVisibility + public WVisibility FlyoutTitleVisibility { - get { return (Visibility)GetValue(FlyoutTitleVisibilityProperty); } + get { return (WVisibility)GetValue(FlyoutTitleVisibilityProperty); } set { SetValue(FlyoutTitleVisibilityProperty, value); } } - public Visibility FlyoutToolbarVisibility + public WVisibility FlyoutToolbarVisibility { - get { return (Visibility)GetValue(FlyoutToolbarVisibilityProperty); } + get { return (WVisibility)GetValue(FlyoutToolbarVisibilityProperty); } set { SetValue(FlyoutToolbarVisibilityProperty, value); } } @@ -231,9 +232,9 @@ public bool ToolbarDynamicOverflowEnabled } } - public Visibility ContentTogglePaneButtonVisibility + public WVisibility ContentTogglePaneButtonVisibility { - get { return (Visibility)GetValue(ContentTogglePaneButtonVisibilityProperty); } + get { return (WVisibility)GetValue(ContentTogglePaneButtonVisibilityProperty); } set { SetValue(ContentTogglePaneButtonVisibilityProperty, value); } } @@ -349,20 +350,20 @@ void UpdateMode() { // If we've determined that the pane will always be open, then there's no // reason to display the show/hide pane button in the master - FlyoutToolbarVisibility = Visibility.Collapsed; + FlyoutToolbarVisibility = WVisibility.Collapsed; } // If we're in compact mode or the pane is always open, // we don't need to display the content pane's toggle button ContentTogglePaneButtonVisibility = _split.DisplayMode == SplitViewDisplayMode.Overlay - ? Visibility.Visible - : Visibility.Collapsed; + ? WVisibility.Visible + : WVisibility.Collapsed; - if (ContentTogglePaneButtonVisibility == Visibility.Visible) - DetailTitleVisibility = Visibility.Visible; + if (ContentTogglePaneButtonVisibility == WVisibility.Visible) + DetailTitleVisibility = WVisibility.Visible; - if (DetailTitleVisibility == Visibility.Visible && !ShouldShowNavigationBar) - DetailTitleVisibility = Visibility.Collapsed; + if (DetailTitleVisibility == WVisibility.Visible && !ShouldShowNavigationBar) + DetailTitleVisibility = WVisibility.Collapsed; _firstLoad = true; } @@ -401,13 +402,13 @@ public string MasterTitle set => FlyoutTitle = value; } - public Visibility MasterTitleVisibility + public WVisibility MasterTitleVisibility { get => FlyoutTitleVisibility; set => FlyoutTitleVisibility = value; } - public Visibility MasterToolbarVisibility + public WVisibility MasterToolbarVisibility { get => FlyoutToolbarVisibility; set => FlyoutToolbarVisibility = value; diff --git a/src/Compatibility/Core/src/WinUI/FlyoutPageRenderer.cs b/src/Compatibility/Core/src/WinUI/FlyoutPageRenderer.cs index 81a2e0641cf5..351723c3bc8d 100644 --- a/src/Compatibility/Core/src/WinUI/FlyoutPageRenderer.cs +++ b/src/Compatibility/Core/src/WinUI/FlyoutPageRenderer.cs @@ -11,6 +11,7 @@ using WImageSource = Microsoft.UI.Xaml.Media.ImageSource; using Microsoft.Maui.Graphics; using Microsoft.Maui.Controls.Platform; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -76,7 +77,7 @@ bool ITitleProvider.ShowTitle return; _showTitle = value; - Control.DetailTitleVisibility = _showTitle ? Visibility.Visible : Visibility.Collapsed; + Control.DetailTitleVisibility = _showTitle ? WVisibility.Visible : WVisibility.Collapsed; } } diff --git a/src/Compatibility/Core/src/WinUI/FormsCommandBar.cs b/src/Compatibility/Core/src/WinUI/FormsCommandBar.cs index 474c232cd4de..01534427cf95 100644 --- a/src/Compatibility/Core/src/WinUI/FormsCommandBar.cs +++ b/src/Compatibility/Core/src/WinUI/FormsCommandBar.cs @@ -4,6 +4,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Data; using Microsoft.UI.Xaml.Media; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -60,26 +61,26 @@ void UpdateVisibility() { // If there's no title to display (e.g., toolbarplacement is set to bottom) // or the title is collapsed (e.g., because it's empty) - if (frameworkElement == null || frameworkElement.Visibility != Visibility.Visible) + if (frameworkElement == null || frameworkElement.Visibility != WVisibility.Visible) { // Just collapse the whole thing - Visibility = Visibility.Collapsed; + Visibility = WVisibility.Collapsed; return; } // The title needs to be visible, but we're not allowed to show a toolbar // So we need to hide the toolbar items - Visibility = Visibility.Visible; + Visibility = WVisibility.Visible; if (_moreButton != null) { - _moreButton.Visibility = Visibility.Collapsed; + _moreButton.Visibility = WVisibility.Collapsed; } if (_primaryItemsControl != null) { - _primaryItemsControl.Visibility = Visibility.Collapsed; + _primaryItemsControl.Visibility = WVisibility.Collapsed; } return; @@ -90,11 +91,11 @@ void UpdateVisibility() if (_primaryItemsControl != null) { // This is normally visible by default, but it might have been collapsed by the toolbar consistency rules above - _primaryItemsControl.Visibility = Visibility.Visible; + _primaryItemsControl.Visibility = WVisibility.Visible; } // Are there any commands to display? - var visibility = PrimaryCommands.Count + SecondaryCommands.Count > 0 ? Visibility.Visible : Visibility.Collapsed; + var visibility = PrimaryCommands.Count + SecondaryCommands.Count > 0 ? WVisibility.Visible : WVisibility.Collapsed; if (_moreButton != null) { @@ -105,10 +106,10 @@ void UpdateVisibility() // but it became available in 10.0.14393.0 and we have to support 10.0.10240 } - if (frameworkElement != null && frameworkElement.Visibility != Visibility.Collapsed) + if (frameworkElement != null && frameworkElement.Visibility != WVisibility.Collapsed) { // If there's a title to display, we have to be visible whether or not we have commands - Visibility = Visibility.Visible; + Visibility = WVisibility.Visible; } else { diff --git a/src/Compatibility/Core/src/WinUI/FormsFlyout.xaml.cs b/src/Compatibility/Core/src/WinUI/FormsFlyout.xaml.cs index 5bfa46a558ff..351c8178a263 100644 --- a/src/Compatibility/Core/src/WinUI/FormsFlyout.xaml.cs +++ b/src/Compatibility/Core/src/WinUI/FormsFlyout.xaml.cs @@ -3,6 +3,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.Maui.Controls.Internals; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -54,8 +55,8 @@ public FormsFlyout(ActionSheetArguments sheetOptions) RightBtn.Content = options.Destruction; } - LeftBtn.Visibility = LeftBtn.Content == null ? Visibility.Collapsed : Visibility.Visible; - RightBtn.Visibility = RightBtn.Content == null ? Visibility.Collapsed : Visibility.Visible; + LeftBtn.Visibility = LeftBtn.Content == null ? WVisibility.Collapsed : WVisibility.Visible; + RightBtn.Visibility = RightBtn.Content == null ? WVisibility.Collapsed : WVisibility.Visible; } void ListItemSelected (object sender, ItemClickEventArgs e) diff --git a/src/Compatibility/Core/src/WinUI/FormsSlider.cs b/src/Compatibility/Core/src/WinUI/FormsSlider.cs index 7b4a7dec3f35..74d7c5463ed2 100644 --- a/src/Compatibility/Core/src/WinUI/FormsSlider.cs +++ b/src/Compatibility/Core/src/WinUI/FormsSlider.cs @@ -4,6 +4,7 @@ using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Media.Imaging; using WImageSource = Microsoft.UI.Xaml.Media.ImageSource; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -32,13 +33,13 @@ static void SwapThumbs(FormsSlider slider) if (slider.ThumbImageSource != null) { - slider.Thumb.Visibility = Visibility.Collapsed; - slider.ImageThumb.Visibility = Visibility.Visible; + slider.Thumb.Visibility = WVisibility.Collapsed; + slider.ImageThumb.Visibility = WVisibility.Visible; } else { - slider.Thumb.Visibility = Visibility.Visible; - slider.ImageThumb.Visibility = Visibility.Collapsed; + slider.Thumb.Visibility = WVisibility.Visible; + slider.ImageThumb.Visibility = WVisibility.Collapsed; } } diff --git a/src/Compatibility/Core/src/WinUI/PageControl.cs b/src/Compatibility/Core/src/WinUI/PageControl.cs index 444efc6548f9..71e925179b14 100644 --- a/src/Compatibility/Core/src/WinUI/PageControl.cs +++ b/src/Compatibility/Core/src/WinUI/PageControl.cs @@ -4,12 +4,13 @@ using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; using WBrush = Microsoft.UI.Xaml.Media.Brush; using WImageSource = Microsoft.UI.Xaml.Media.ImageSource; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { public sealed class PageControl : ContentControl, IToolbarProvider, ITitleViewRendererController { - public static readonly DependencyProperty TitleVisibilityProperty = DependencyProperty.Register(nameof(TitleVisibility), typeof(Visibility), typeof(PageControl), new PropertyMetadata(Visibility.Visible)); + public static readonly DependencyProperty TitleVisibilityProperty = DependencyProperty.Register(nameof(TitleVisibility), typeof(WVisibility), typeof(PageControl), new PropertyMetadata(WVisibility.Visible)); public static readonly DependencyProperty ToolbarBackgroundProperty = DependencyProperty.Register(nameof(ToolbarBackground), typeof(WBrush), typeof(PageControl), new PropertyMetadata(default(WBrush))); @@ -23,7 +24,7 @@ public sealed class PageControl : ContentControl, IToolbarProvider, ITitleViewRe public static readonly DependencyProperty TitleViewProperty = DependencyProperty.Register(nameof(TitleView), typeof(View), typeof(PageControl), new PropertyMetadata(default(View), OnTitleViewPropertyChanged)); - public static readonly DependencyProperty TitleViewVisibilityProperty = DependencyProperty.Register(nameof(TitleViewVisibility), typeof(Visibility), typeof(PageControl), new PropertyMetadata(Visibility.Collapsed)); + public static readonly DependencyProperty TitleViewVisibilityProperty = DependencyProperty.Register(nameof(TitleViewVisibility), typeof(WVisibility), typeof(PageControl), new PropertyMetadata(WVisibility.Collapsed)); public static readonly DependencyProperty TitleInsetProperty = DependencyProperty.Register("TitleInset", typeof(double), typeof(PageControl), new PropertyMetadata(default(double))); diff --git a/src/Compatibility/Core/src/WinUI/Platform.cs b/src/Compatibility/Core/src/WinUI/Platform.cs index 04a2022fd2c5..86ae6310fee2 100644 --- a/src/Compatibility/Core/src/WinUI/Platform.cs +++ b/src/Compatibility/Core/src/WinUI/Platform.cs @@ -12,6 +12,7 @@ using WImage = Microsoft.UI.Xaml.Controls.Image; using Microsoft.Maui.Graphics; using Microsoft.Maui.Controls.Platform; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -139,7 +140,7 @@ internal Platform(Microsoft.UI.Xaml.Window page) MessagingCenter.Subscribe(this, Page.BusySetSignalName, (Page sender, bool enabled) => { Microsoft.UI.Xaml.Controls.ProgressBar indicator = GetBusyIndicator(); - indicator.Visibility = enabled ? Visibility.Visible : Visibility.Collapsed; + indicator.Visibility = enabled ? WVisibility.Visible : WVisibility.Collapsed; }); _toolbarTracker.CollectionChanged += OnToolbarItemsChanged; @@ -317,7 +318,7 @@ Microsoft.UI.Xaml.Controls.ProgressBar GetBusyIndicator() _busyIndicator = new Microsoft.UI.Xaml.Controls.ProgressBar { IsIndeterminate = true, - Visibility = Visibility.Collapsed, + Visibility = WVisibility.Collapsed, VerticalAlignment = UI.Xaml.VerticalAlignment.Top }; diff --git a/src/Compatibility/Core/src/WinUI/Shell/ShellFlyoutItemRenderer.cs b/src/Compatibility/Core/src/WinUI/Shell/ShellFlyoutItemRenderer.cs index d19a85fcbe8a..203d8df33163 100644 --- a/src/Compatibility/Core/src/WinUI/Shell/ShellFlyoutItemRenderer.cs +++ b/src/Compatibility/Core/src/WinUI/Shell/ShellFlyoutItemRenderer.cs @@ -9,6 +9,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; using WRect = Windows.Foundation.Rect; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -123,11 +124,11 @@ void OnMeasureInvalidated() { if (!_content.IsVisible) { - fe.Visibility = Visibility.Collapsed; + fe.Visibility = WVisibility.Collapsed; } else { - fe.Visibility = Visibility.Visible; + fe.Visibility = WVisibility.Visible; } } diff --git a/src/Compatibility/Core/src/WinUI/Shell/ShellItemRenderer.cs b/src/Compatibility/Core/src/WinUI/Shell/ShellItemRenderer.cs index 1303de7cb14e..6ba970c8014d 100644 --- a/src/Compatibility/Core/src/WinUI/Shell/ShellItemRenderer.cs +++ b/src/Compatibility/Core/src/WinUI/Shell/ShellItemRenderer.cs @@ -18,6 +18,7 @@ using UwpApplication = Microsoft.UI.Xaml.Application; using UwpSolidColorBrush = Microsoft.UI.Xaml.Media.SolidColorBrush; using Microsoft.Maui.Controls.Platform; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -361,12 +362,12 @@ void UpdateNavBarVisibility() { if (DisplayedPage == null || Shell.GetNavBarIsVisible(DisplayedPage)) { - _HeaderArea.Visibility = Visibility.Visible; + _HeaderArea.Visibility = WVisibility.Visible; Shell.SetFlyoutBehavior(Shell.Current, Microsoft.Maui.Controls.FlyoutBehavior.Flyout); } else { - _HeaderArea.Visibility = Visibility.Collapsed; + _HeaderArea.Visibility = WVisibility.Collapsed; Shell.SetFlyoutBehavior(Shell.Current, Microsoft.Maui.Controls.FlyoutBehavior.Disabled); } } @@ -379,7 +380,7 @@ void UpdatePageTitle() void UpdateBottomBarVisibility() { bool isVisible = ShellItemController?.ShowTabs ?? false; - _BottomBar.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + _BottomBar.Visibility = isVisible ? WVisibility.Visible : WVisibility.Collapsed; } void UpdateToolbar() diff --git a/src/Compatibility/Core/src/WinUI/TitleViewManager.cs b/src/Compatibility/Core/src/WinUI/TitleViewManager.cs index 2b435bd3567a..499ea053e49c 100644 --- a/src/Compatibility/Core/src/WinUI/TitleViewManager.cs +++ b/src/Compatibility/Core/src/WinUI/TitleViewManager.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -70,7 +71,7 @@ void UpdateTitleViewWidth() double buttonWidth = 0; foreach (var item in CommandBar.GetDescendantsByName("MoreButton")) - if (item.Visibility == Visibility.Visible) + if (item.Visibility == WVisibility.Visible) buttonWidth += item.ActualWidth; if (!CommandBar.IsDynamicOverflowEnabled) diff --git a/src/Compatibility/Core/src/WinUI/VisualElementTracker.cs b/src/Compatibility/Core/src/WinUI/VisualElementTracker.cs index ea1c54e9b847..f6c98ec40202 100644 --- a/src/Compatibility/Core/src/WinUI/VisualElementTracker.cs +++ b/src/Compatibility/Core/src/WinUI/VisualElementTracker.cs @@ -18,6 +18,7 @@ using WCompositeTransform = Microsoft.UI.Xaml.Media.CompositeTransform; using WScaleTransform = Microsoft.UI.Xaml.Media.ScaleTransform; using Microsoft.Maui.Graphics; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { @@ -778,9 +779,10 @@ static void UpdateScaleAndRotation(VisualElement view, FrameworkElement framewor UpdateRotation(view, frameworkElement); } + [PortHandler] static void UpdateVisibility(VisualElement view, FrameworkElement frameworkElement) { - frameworkElement.Visibility = view.IsVisible ? Visibility.Visible : Visibility.Collapsed; + frameworkElement.Visibility = view.IsVisible ? WVisibility.Visible : WVisibility.Collapsed; } void UpdateDragAndDropGestureRecognizers() diff --git a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs index 68cd1983f260..4d40f884aa77 100644 --- a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs +++ b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs @@ -37,6 +37,26 @@ public MainPage(IServiceProvider services, MainPageViewModel viewModel) NavigationPage.SetHasNavigationBar(this, false); //SetupCompatibilityLayout(); + //SetupVisibilityTest(); + } + + public class VisibilityLabel : Label, IFrameworkElement + { + private Visibility _visibility; + + public void SetVisibility(Visibility visibility) + { + _visibility = visibility; + Handler?.UpdateValue(nameof(Visibility)); + } + + Visibility IFrameworkElement.Visibility + { + get + { + return _visibility; + } + } } const string LoremIpsum = @@ -53,7 +73,7 @@ void SetupMauiLayout() var verticalStack = new VerticalStackLayout() { Spacing = 5, BackgroundColor = Colors.AntiqueWhite }; var horizontalStack = new HorizontalStackLayout() { Spacing = 2, BackgroundColor = Colors.CornflowerBlue }; - verticalStack.Add(CreateSampleGrid()); + //verticalStack.Add(CreateSampleGrid()); verticalStack.Add(CreateResizingButton()); AddTextResizeDemo(verticalStack); @@ -490,5 +510,49 @@ void AddTextResizeDemo(Microsoft.Maui.ILayout layout) layout.Add(widthAndHeightTestLabel); layout.Add(explicitWidthTestLabel); } + + void SetupVisibilityTest() + { + var layout = new VerticalStackLayout() { BackgroundColor = Colors.BurlyWood }; + + var button1 = new Button { Text = "Controls", Margin = new Thickness(0, 40) }; + + var button2 = new Button { Text = "MAUI" }; + + var controlsLabel = new Label { Text = "Controls Label" }; + controlsLabel.IsVisible = true; + + var alwaysVisible = new Label { Text = "Always visible" }; + + var mauiLabel = new VisibilityLabel() { Text = "Core Label" }; + + button1.Clicked += (sender, args) => { + controlsLabel.IsVisible = !controlsLabel.IsVisible; + }; + + button2.Clicked += (sender, args) => + { + switch ((mauiLabel as IFrameworkElement).Visibility) + { + case Visibility.Visible: + mauiLabel.SetVisibility(Visibility.Hidden); + break; + case Visibility.Hidden: + mauiLabel.SetVisibility(Visibility.Collapsed); + break; + case Visibility.Collapsed: + mauiLabel.SetVisibility(Visibility.Visible); + break; + } + }; + + layout.Add(button1); + layout.Add(button2); + layout.Add(controlsLabel); + layout.Add(mauiLabel); + layout.Add(alwaysVisible); + + Content = layout; + } } } diff --git a/src/Controls/src/Core/HandlerImpl/VisualElement.Impl.cs b/src/Controls/src/Core/HandlerImpl/VisualElement.Impl.cs index 978a070afbb0..07d411e3974d 100644 --- a/src/Controls/src/Core/HandlerImpl/VisualElement.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/VisualElement.Impl.cs @@ -7,7 +7,8 @@ namespace Microsoft.Maui.Controls { public partial class VisualElement : IFrameworkElement { - private IViewHandler _handler; + Semantics _semantics; + IViewHandler _handler; public Rectangle Frame => Bounds; @@ -139,8 +140,9 @@ protected virtual Size MeasureOverride(double widthConstraint, double heightCons Primitives.LayoutAlignment IFrameworkElement.HorizontalLayoutAlignment => default; Primitives.LayoutAlignment IFrameworkElement.VerticalLayoutAlignment => default; - Maui.Semantics _semantics; - Maui.Semantics IFrameworkElement.Semantics + Visibility IFrameworkElement.Visibility => IsVisible.ToVisibility(); + + Semantics IFrameworkElement.Semantics { get => _semantics; } @@ -148,7 +150,7 @@ Maui.Semantics IFrameworkElement.Semantics // We don't want to initialize Semantics until someone explicitly // wants to modify some aspect of the semantics class internal Semantics SetupSemantics() => - _semantics ??= new Maui.Semantics(); + _semantics ??= new Semantics(); double IFrameworkElement.Width => WidthRequest; double IFrameworkElement.Height => HeightRequest; diff --git a/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs b/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs index ac02f3e56442..2bd05764de7f 100644 --- a/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs +++ b/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs @@ -4,6 +4,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Data; using Microsoft.UI.Xaml.Media; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Platform { @@ -60,26 +61,26 @@ void UpdateVisibility() { // If there's no title to display (e.g., toolbarplacement is set to bottom) // or the title is collapsed (e.g., because it's empty) - if (frameworkElement == null || frameworkElement.Visibility != Visibility.Visible) + if (frameworkElement == null || frameworkElement.Visibility != WVisibility.Visible) { // Just collapse the whole thing - Visibility = Visibility.Collapsed; + Visibility = WVisibility.Collapsed; return; } // The title needs to be visible, but we're not allowed to show a toolbar // So we need to hide the toolbar items - Visibility = Visibility.Visible; + Visibility = WVisibility.Visible; if (_moreButton != null) { - _moreButton.Visibility = Visibility.Collapsed; + _moreButton.Visibility = WVisibility.Collapsed; } if (_primaryItemsControl != null) { - _primaryItemsControl.Visibility = Visibility.Collapsed; + _primaryItemsControl.Visibility = WVisibility.Collapsed; } return; @@ -90,11 +91,11 @@ void UpdateVisibility() if (_primaryItemsControl != null) { // This is normally visible by default, but it might have been collapsed by the toolbar consistency rules above - _primaryItemsControl.Visibility = Visibility.Visible; + _primaryItemsControl.Visibility = WVisibility.Visible; } // Are there any commands to display? - var visibility = PrimaryCommands.Count + SecondaryCommands.Count > 0 ? Visibility.Visible : Visibility.Collapsed; + var visibility = PrimaryCommands.Count + SecondaryCommands.Count > 0 ? WVisibility.Visible : WVisibility.Collapsed; if (_moreButton != null) { @@ -105,10 +106,10 @@ void UpdateVisibility() // but it became available in 10.0.14393.0 and we have to support 10.0.10240 } - if (frameworkElement != null && frameworkElement.Visibility != Visibility.Collapsed) + if (frameworkElement != null && frameworkElement.Visibility != WVisibility.Collapsed) { // If there's a title to display, we have to be visible whether or not we have commands - Visibility = Visibility.Visible; + Visibility = WVisibility.Visible; } else { diff --git a/src/Controls/src/Core/Platform/Windows/PageControl.cs b/src/Controls/src/Core/Platform/Windows/PageControl.cs index 2697b2f7114e..de90d10fc1d5 100644 --- a/src/Controls/src/Core/Platform/Windows/PageControl.cs +++ b/src/Controls/src/Core/Platform/Windows/PageControl.cs @@ -4,12 +4,13 @@ using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; using WBrush = Microsoft.UI.Xaml.Media.Brush; using WImageSource = Microsoft.UI.Xaml.Media.ImageSource; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Platform { public sealed class PageControl : ContentControl, IToolbarProvider, ITitleViewRendererController { - public static readonly DependencyProperty TitleVisibilityProperty = DependencyProperty.Register(nameof(TitleVisibility), typeof(Visibility), typeof(PageControl), new PropertyMetadata(Visibility.Visible)); + public static readonly DependencyProperty TitleVisibilityProperty = DependencyProperty.Register(nameof(TitleVisibility), typeof(WVisibility), typeof(PageControl), new PropertyMetadata(WVisibility.Visible)); public static readonly DependencyProperty ToolbarBackgroundProperty = DependencyProperty.Register(nameof(ToolbarBackground), typeof(WBrush), typeof(PageControl), new PropertyMetadata(default(WBrush))); @@ -23,7 +24,7 @@ public sealed class PageControl : ContentControl, IToolbarProvider, ITitleViewRe public static readonly DependencyProperty TitleViewProperty = DependencyProperty.Register(nameof(TitleView), typeof(View), typeof(PageControl), new PropertyMetadata(default(View), OnTitleViewPropertyChanged)); - public static readonly DependencyProperty TitleViewVisibilityProperty = DependencyProperty.Register(nameof(TitleViewVisibility), typeof(Visibility), typeof(PageControl), new PropertyMetadata(Visibility.Collapsed)); + public static readonly DependencyProperty TitleViewVisibilityProperty = DependencyProperty.Register(nameof(TitleViewVisibility), typeof(WVisibility), typeof(PageControl), new PropertyMetadata(WVisibility.Collapsed)); public static readonly DependencyProperty TitleInsetProperty = DependencyProperty.Register("TitleInset", typeof(double), typeof(PageControl), new PropertyMetadata(default(double))); diff --git a/src/Controls/src/Core/Platform/Windows/TitleViewManager.cs b/src/Controls/src/Core/Platform/Windows/TitleViewManager.cs index 472f3904e950..280a44363996 100644 --- a/src/Controls/src/Core/Platform/Windows/TitleViewManager.cs +++ b/src/Controls/src/Core/Platform/Windows/TitleViewManager.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Platform { @@ -69,8 +70,9 @@ void UpdateTitleViewWidth() return; double buttonWidth = 0; + foreach (var item in CommandBar.GetDescendantsByName("MoreButton")) - if (item.Visibility == Visibility.Visible) + if (item.Visibility == WVisibility.Visible) buttonWidth += item.ActualWidth; if (!CommandBar.IsDynamicOverflowEnabled) diff --git a/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs b/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs index e307a550e3ea..4bae91ec9bc0 100644 --- a/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs +++ b/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs @@ -20,6 +20,7 @@ using WCompositeTransform = Microsoft.UI.Xaml.Media.CompositeTransform; using WScaleTransform = Microsoft.UI.Xaml.Media.ScaleTransform; using Microsoft.Maui.Graphics; +using WVisibility = Microsoft.UI.Xaml.Visibility; namespace Microsoft.Maui.Controls.Platform { @@ -790,7 +791,7 @@ static void UpdateScaleAndRotation(VisualElement view, FrameworkElement framewor static void UpdateVisibility(VisualElement view, FrameworkElement frameworkElement) { - frameworkElement.Visibility = view.IsVisible ? Visibility.Visible : Visibility.Collapsed; + frameworkElement.Visibility = view.IsVisible ? WVisibility.Visible : WVisibility.Collapsed; } void UpdateDragAndDropGestureRecognizers() diff --git a/src/Controls/src/Core/VisibilityExtensions.cs b/src/Controls/src/Core/VisibilityExtensions.cs new file mode 100644 index 000000000000..2b315a986094 --- /dev/null +++ b/src/Controls/src/Core/VisibilityExtensions.cs @@ -0,0 +1,13 @@ +namespace Microsoft.Maui.Controls +{ + public static class VisibilityExtensions + { + public static Visibility ToVisibility(this bool isVisible) + { + if (isVisible) + return Visibility.Visible; + + return Visibility.Collapsed; + } + } +} diff --git a/src/Controls/src/Core/VisualElement.cs b/src/Controls/src/Core/VisualElement.cs index 35a82c902122..e57b1ccc1731 100644 --- a/src/Controls/src/Core/VisualElement.cs +++ b/src/Controls/src/Core/VisualElement.cs @@ -939,7 +939,15 @@ internal virtual void OnIsPlatformEnabledChanged() { } - internal virtual void OnIsVisibleChanged(bool oldValue, bool newValue) => InvalidateMeasureInternal(InvalidationTrigger.Undefined); + internal virtual void OnIsVisibleChanged(bool oldValue, bool newValue) + { + if (this is IFrameworkElement fe) + { + fe.Handler?.UpdateValue(nameof(IFrameworkElement.Visibility)); + } + + InvalidateMeasureInternal(InvalidationTrigger.Undefined); + } internal override void OnParentResourcesChanged(IEnumerable> values) { diff --git a/src/Core/src/Core/IFrameworkElement.cs b/src/Core/src/Core/IFrameworkElement.cs index f70656ff90bb..d76e7b6c63f2 100644 --- a/src/Core/src/Core/IFrameworkElement.cs +++ b/src/Core/src/Core/IFrameworkElement.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using Microsoft.Maui.Graphics; using Microsoft.Maui.Primitives; @@ -14,6 +14,16 @@ public interface IFrameworkElement /// bool IsEnabled { get; } + /// + /// Gets a value that determines whether this FrameworkElement should be part of the visual tree or not. + /// + Visibility Visibility { get; } + + /// + /// Gets the opacity value applied to the view when it is rendered. + /// + double Opacity { get; } + /// /// Gets the paint which will fill the background of a FrameworkElement. /// diff --git a/src/Core/src/Handlers/View/ViewHandler.cs b/src/Core/src/Handlers/View/ViewHandler.cs index 765f8197c40e..98a598126eff 100644 --- a/src/Core/src/Handlers/View/ViewHandler.cs +++ b/src/Core/src/Handlers/View/ViewHandler.cs @@ -18,6 +18,7 @@ public abstract partial class ViewHandler : IViewHandler public static PropertyMapper ViewMapper = new PropertyMapper { [nameof(IView.AutomationId)] = MapAutomationId, + [nameof(IView.Visibility)] = MapVisibility, [nameof(IView.Background)] = MapBackground, [nameof(IView.Width)] = MapWidth, [nameof(IView.Height)] = MapHeight, @@ -106,6 +107,11 @@ public static void MapIsEnabled(IViewHandler handler, IView view) ((NativeView?)handler.NativeView)?.UpdateIsEnabled(view); } + public static void MapVisibility(IViewHandler handler, IView view) + { + ((NativeView?)handler.NativeView)?.UpdateVisibility(view); + } + public static void MapBackground(IViewHandler handler, IView view) { ((NativeView?)handler.NativeView)?.UpdateBackground(view); diff --git a/src/Core/src/Layouts/GridLayoutManager.cs b/src/Core/src/Layouts/GridLayoutManager.cs index 17ab5dac4b45..d9241a827018 100644 --- a/src/Core/src/Layouts/GridLayoutManager.cs +++ b/src/Core/src/Layouts/GridLayoutManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Microsoft.Maui.Graphics; +using System.Linq; namespace Microsoft.Maui.Layouts { @@ -29,6 +30,11 @@ public override void ArrangeChildren(Rectangle childBounds) foreach (var view in Grid.Children) { + if (view.Visibility == Visibility.Collapsed) + { + continue; + } + var cell = structure.ComputeFrameFor(view); view.Arrange(cell); } @@ -42,6 +48,7 @@ class GridStructure Row[] _rows { get; } Column[] _columns { get; } + IView[] _children; Cell[] _cells { get; } readonly Dictionary _spans = new Dictionary(); @@ -65,7 +72,10 @@ public GridStructure(IGridLayout grid, double widthConstraint, double heightCons _columns[n] = new Column(_grid.ColumnDefinitions[n]); } - _cells = new Cell[_grid.Children.Count]; + _children = _grid.Children.Where(child => child.Visibility != Visibility.Collapsed).ToArray(); + + // We'll ignore any collapsed child views during layout + _cells = new Cell[_children.Length]; InitializeCells(); @@ -74,9 +84,15 @@ public GridStructure(IGridLayout grid, double widthConstraint, double heightCons void InitializeCells() { - for (int n = 0; n < _grid.Children.Count; n++) + for (int n = 0; n < _children.Length; n++) { - var view = _grid.Children[n]; + var view = _children[n]; + + if (view.Visibility == Visibility.Collapsed) + { + continue; + } + var column = _grid.GetColumn(view); var columnSpan = _grid.GetColumnSpan(view); @@ -181,7 +197,7 @@ void MeasureCells() var availableWidth = _gridWidthConstraint - GridWidth(); var availableHeight = _gridHeightConstraint - GridHeight(); - var measure = _grid.Children[cell.ViewIndex].Measure(availableWidth, availableHeight); + var measure = _children[cell.ViewIndex].Measure(availableWidth, availableHeight); if (cell.IsColumnSpanAuto) { diff --git a/src/Core/src/Layouts/HorizontalStackLayoutManager.cs b/src/Core/src/Layouts/HorizontalStackLayoutManager.cs index b0d09d977bd3..0ad992ea9873 100644 --- a/src/Core/src/Layouts/HorizontalStackLayoutManager.cs +++ b/src/Core/src/Layouts/HorizontalStackLayoutManager.cs @@ -41,6 +41,12 @@ static Size Measure(double heightConstraint, int spacing, IReadOnlyList v for (int n = 0; n < views.Count; n++) { var child = views[n]; + + if (child.Visibility == Visibility.Collapsed) + { + continue; + } + var measure = child.Measure(double.PositiveInfinity, heightConstraint); totalRequestedWidth += measure.Width; requestedHeight = Math.Max(requestedHeight, measure.Height); @@ -59,6 +65,12 @@ static void ArrangeLeftToRight(double height, int spacing, IReadOnlyList for (int n = 0; n < views.Count; n++) { var child = views[n]; + + if (child.Visibility == Visibility.Collapsed) + { + continue; + } + xPosition += ArrangeChild(child, height, spacing, xPosition); } } @@ -70,6 +82,12 @@ static void ArrangeRightToLeft(double height, int spacing, IReadOnlyList for (int n = views.Count - 1; n >= 0; n--) { var child = views[n]; + + if (child.Visibility == Visibility.Collapsed) + { + continue; + } + xPostition += ArrangeChild(child, height, spacing, xPostition); } } diff --git a/src/Core/src/Layouts/VerticalStackLayoutManager.cs b/src/Core/src/Layouts/VerticalStackLayoutManager.cs index 7c859744197a..79d6ac3850fb 100644 --- a/src/Core/src/Layouts/VerticalStackLayoutManager.cs +++ b/src/Core/src/Layouts/VerticalStackLayoutManager.cs @@ -28,6 +28,11 @@ static Size Measure(double widthConstraint, int spacing, IReadOnlyList vi foreach (var child in views) { + if (child.Visibility == Visibility.Collapsed) + { + continue; + } + var measure = child.Measure(widthConstraint, double.PositiveInfinity); totalRequestedHeight += measure.Height; requestedWidth = Math.Max(requestedWidth, measure.Width); @@ -45,6 +50,11 @@ static void Arrange(double width, int spacing, IEnumerable views) foreach (var child in views) { + if (child.Visibility == Visibility.Collapsed) + { + continue; + } + var destination = new Rectangle(0, stackHeight, width, child.DesiredSize.Height); child.Arrange(destination); stackHeight += destination.Height + spacing; diff --git a/src/Core/src/Platform/Android/ActivityIndicatorExtensions.cs b/src/Core/src/Platform/Android/ActivityIndicatorExtensions.cs index 24e910a84f16..b86928d01a24 100644 --- a/src/Core/src/Platform/Android/ActivityIndicatorExtensions.cs +++ b/src/Core/src/Platform/Android/ActivityIndicatorExtensions.cs @@ -5,8 +5,17 @@ namespace Microsoft.Maui { public static class ActivityIndicatorExtensions { - public static void UpdateIsRunning(this ProgressBar progressBar, IActivityIndicator activityIndicator) => - progressBar.Visibility = activityIndicator.IsRunning ? ViewStates.Visible : ViewStates.Invisible; + public static void UpdateIsRunning(this ProgressBar progressBar, IActivityIndicator activityIndicator) + { + if (activityIndicator.Visibility == Visibility.Visible) + { + progressBar.Visibility = activityIndicator.IsRunning ? ViewStates.Visible : ViewStates.Invisible; + } + else + { + progressBar.Visibility = activityIndicator.Visibility.ToNativeVisibility(); + } + } public static void UpdateColor(this ProgressBar progressBar, IActivityIndicator activityIndicator) { diff --git a/src/Core/src/Platform/Android/ViewExtensions.cs b/src/Core/src/Platform/Android/ViewExtensions.cs index 6c98aaac692d..a0dd992c3c50 100644 --- a/src/Core/src/Platform/Android/ViewExtensions.cs +++ b/src/Core/src/Platform/Android/ViewExtensions.cs @@ -1,3 +1,4 @@ +using Android.Views; using AndroidX.Core.View; using Microsoft.Maui.Graphics; using AView = Android.Views.View; @@ -15,6 +16,21 @@ public static void UpdateIsEnabled(this AView nativeView, IView view) nativeView.Enabled = view.IsEnabled; } + public static void UpdateVisibility(this AView nativeView, IView view) + { + nativeView.Visibility = view.Visibility.ToNativeVisibility(); + } + + public static ViewStates ToNativeVisibility(this Visibility visibility) + { + return visibility switch + { + Visibility.Hidden => ViewStates.Invisible, + Visibility.Collapsed => ViewStates.Gone, + _ => ViewStates.Visible, + }; + } + public static void UpdateBackground(this AView nativeView, IView view) { if (view == null) diff --git a/src/Core/src/Platform/Standard/ViewExtensions.cs b/src/Core/src/Platform/Standard/ViewExtensions.cs index 815d018c910a..3caf5a909b97 100644 --- a/src/Core/src/Platform/Standard/ViewExtensions.cs +++ b/src/Core/src/Platform/Standard/ViewExtensions.cs @@ -4,6 +4,8 @@ static class ViewExtensions { public static void UpdateIsEnabled(this object nativeView, IView view) { } + public static void UpdateVisibility(this object nativeView, IView view) { } + public static void UpdateBackground(this object nativeView, IView view) { } public static void UpdateAutomationId(this object nativeView, IView view) { } diff --git a/src/Core/src/Platform/Windows/ViewExtensions.cs b/src/Core/src/Platform/Windows/ViewExtensions.cs index b4b599a49395..c640d3215b99 100644 --- a/src/Core/src/Platform/Windows/ViewExtensions.cs +++ b/src/Core/src/Platform/Windows/ViewExtensions.cs @@ -10,6 +10,27 @@ public static class ViewExtensions { public static void UpdateIsEnabled(this FrameworkElement nativeView, IView view) => (nativeView as Control)?.UpdateIsEnabled(view.IsEnabled); + + public static void UpdateVisibility(this FrameworkElement nativeView, IView view) + { + double opacity = view.Opacity; + + switch (view.Visibility) + { + case Visibility.Visible: + nativeView.Opacity = opacity; + nativeView.Visibility = UI.Xaml.Visibility.Visible; + break; + case Visibility.Hidden: + nativeView.Opacity = 0; + nativeView.Visibility = UI.Xaml.Visibility.Visible; + break; + case Visibility.Collapsed: + nativeView.Opacity = opacity; + nativeView.Visibility = UI.Xaml.Visibility.Collapsed; + break; + } + } public static void UpdateBackground(this FrameworkElement nativeView, IView view) { diff --git a/src/Core/src/Platform/iOS/CollapseConstraint.cs b/src/Core/src/Platform/iOS/CollapseConstraint.cs new file mode 100644 index 000000000000..d91c8f3dbb41 --- /dev/null +++ b/src/Core/src/Platform/iOS/CollapseConstraint.cs @@ -0,0 +1,15 @@ +using System; +using UIKit; + +namespace Microsoft.Maui +{ + /// + /// Constraint which forces a UIView's height to zero + /// + internal class CollapseConstraint : NSLayoutConstraint + { + public override NSLayoutRelation Relation => NSLayoutRelation.Equal; + public override NSLayoutAttribute FirstAttribute => NSLayoutAttribute.Height; + public override nfloat Multiplier => 0; + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/ViewExtensions.cs b/src/Core/src/Platform/iOS/ViewExtensions.cs index d7079e261ea5..692d17d036ad 100644 --- a/src/Core/src/Platform/iOS/ViewExtensions.cs +++ b/src/Core/src/Platform/iOS/ViewExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using CoreAnimation; using Microsoft.Maui.Graphics; @@ -21,6 +20,37 @@ public static void UpdateIsEnabled(this UIView nativeView, IView view) uiControl.Enabled = view.IsEnabled; } + public static void UpdateVisibility(this UIView nativeView, IView view) + { + var shouldLayout = false; + + switch (view.Visibility) + { + case Visibility.Visible: + shouldLayout = nativeView.Inflate(); + nativeView.Hidden = false; + break; + case Visibility.Hidden: + shouldLayout = nativeView.Inflate(); + nativeView.Hidden = true; + break; + case Visibility.Collapsed: + nativeView.Hidden = true; + nativeView.Collapse(); + shouldLayout = true; + break; + } + + // If the view is just switching between Visible and Hidden, then a re-layout isn't necessary. The return value + // from Inflate will tell us if the view was previously collapsed. If the view is switching to or from a collapsed + // state, then we'll have to ask for a re-layout. + + if (shouldLayout) + { + nativeView.Superview?.SetNeedsLayout(); + } + } + public static void UpdateBackground(this UIView nativeView, IView view) { if (nativeView == null) @@ -137,6 +167,40 @@ public static void UpdateFrame(UIView nativeView, IView view) nativeView.Frame = new CoreGraphics.CGRect(currentFrame.X, currentFrame.Y, view.Width, view.Height); } + internal static void Collapse(this UIView view) + { + // See if this view already has a collapse constraint we can use + foreach (var constraint in view.Constraints) + { + if (constraint is CollapseConstraint collapseConstraint) + { + // Active the collapse constraint; that will squish the view down to zero height + collapseConstraint.Active = true; + return; + } + } + + // Set up a collapse constraint and turn it on + var collapse = new CollapseConstraint(); + view.AddConstraint(collapse); + collapse.Active = true; + } + + internal static bool Inflate(this UIView view) + { + // Find and deactivate the collapse constraint, if any; the view will go back to its normal height + foreach (var constraint in view.Constraints) + { + if (constraint is CollapseConstraint collapseConstraint) + { + collapseConstraint.Active = false; + return true; + } + } + + return false; + } + static void InsertBackgroundLayer(this UIView control, CALayer backgroundLayer, int index = -1) { control.RemoveBackgroundLayer(); diff --git a/src/Core/src/Primitives/Visibility.cs b/src/Core/src/Primitives/Visibility.cs new file mode 100644 index 000000000000..64cb6a11c125 --- /dev/null +++ b/src/Core/src/Primitives/Visibility.cs @@ -0,0 +1,9 @@ +namespace Microsoft.Maui +{ + public enum Visibility + { + Visible = 0, + Hidden = 1, + Collapsed = 2 + } +} \ No newline at end of file diff --git a/src/Core/tests/Benchmarks/Stubs/StubBase.cs b/src/Core/tests/Benchmarks/Stubs/StubBase.cs index 7310f5a5399e..d1beccbe648c 100644 --- a/src/Core/tests/Benchmarks/Stubs/StubBase.cs +++ b/src/Core/tests/Benchmarks/Stubs/StubBase.cs @@ -10,6 +10,10 @@ public class StubBase : IFrameworkElement { public bool IsEnabled { get; set; } = true; + public Visibility Visibility { get; set; } = Visibility.Visible; + + public double Opacity { get; set; } = 1.0d; + public Paint Background { get; set; } public Rectangle Frame { get; set; } = new Rectangle(0, 0, 20, 20); diff --git a/src/Core/tests/DeviceTests/Handlers/ActivityIndicator/ActivityIndicatorHandlerTests.Android.cs b/src/Core/tests/DeviceTests/Handlers/ActivityIndicator/ActivityIndicatorHandlerTests.Android.cs index 77acf699f938..655753d930dd 100644 --- a/src/Core/tests/DeviceTests/Handlers/ActivityIndicator/ActivityIndicatorHandlerTests.Android.cs +++ b/src/Core/tests/DeviceTests/Handlers/ActivityIndicator/ActivityIndicatorHandlerTests.Android.cs @@ -2,8 +2,10 @@ using System.Threading.Tasks; using Android.Views; using Android.Widget; +using Microsoft.Maui.DeviceTests.Stubs; using Microsoft.Maui.Graphics; using Microsoft.Maui.Handlers; +using Xunit; namespace Microsoft.Maui.DeviceTests { @@ -24,5 +26,20 @@ Task ValidateHasColor(IActivityIndicator activityIndicator, Color color, Action nativeActivityIndicator.AssertContainsColor(color); }); } + + [Theory(DisplayName = "Visibility is set correctly")] + [InlineData(Visibility.Collapsed)] + [InlineData(Visibility.Hidden)] + public override async Task SetVisibility(Visibility visibility) + { + var view = new ActivityIndicatorStub + { + Visibility = visibility, + IsRunning = true + }; + + var id = await GetValueAsync(view, handler => GetVisibility(handler)); + Assert.Equal(view.Visibility, id); + } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Android.cs b/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Android.cs index 666f1e6b5f93..9a044e5a1923 100644 --- a/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Android.cs +++ b/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Android.cs @@ -21,5 +21,17 @@ protected SemanticHeadingLevel GetSemanticHeading(IViewHandler viewHandler) return viewHandler.VirtualView.Semantics.HeadingLevel; } + + protected Visibility GetVisibility(IViewHandler viewHandler) + { + var nativeView = (View)viewHandler.NativeView; + + if (nativeView.Visibility == ViewStates.Visible) + return Visibility.Visible; + else if (nativeView.Visibility == ViewStates.Gone) + return Visibility.Collapsed; + else + return Visibility.Hidden; + } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Tests.cs b/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Tests.cs index 8e3017932f4b..a3a5412d0f21 100644 --- a/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Tests.cs +++ b/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.Tests.cs @@ -1,6 +1,4 @@ -using System; using System.Threading.Tasks; -using Microsoft.Maui.DeviceTests.Stubs; using Xunit; namespace Microsoft.Maui.DeviceTests @@ -11,19 +9,35 @@ public abstract partial class HandlerTestBase [InlineData()] public async Task SetAutomationId() { - var view = new TStub(); - view.AutomationId = "TestId"; - var id = await GetValueAsync((IView)view, handler => GetAutomationId(handler)); + var view = new TStub + { + AutomationId = "TestId" + }; + var id = await GetValueAsync(view, handler => GetAutomationId(handler)); Assert.Equal(view.AutomationId, id); } + [Theory(DisplayName = "Visibility is set correctly")] + [InlineData(Visibility.Collapsed)] + [InlineData(Visibility.Hidden)] + public virtual async Task SetVisibility(Visibility visibility) + { + var view = new TStub + { + Visibility = visibility + }; + + var id = await GetValueAsync(view, handler => GetVisibility(handler)); + Assert.Equal(view.Visibility, id); + } + [Fact(DisplayName = "Semantic Description is set correctly")] [InlineData()] public async Task SetSemanticDescription() { var view = new TStub(); view.Semantics.Description = "Test"; - var id = await GetValueAsync((IView)view, handler => GetSemanticDescription(handler)); + var id = await GetValueAsync(view, handler => GetSemanticDescription(handler)); Assert.Equal(view.Semantics.Description, id); } @@ -37,7 +51,7 @@ public async Task SetSemanticHint() { var view = new TStub(); view.Semantics.Description = "Test"; - var id = await GetValueAsync((IView)view, handler => GetSemanticDescription(handler)); + var id = await GetValueAsync(view, handler => GetSemanticDescription(handler)); Assert.Equal(view.Semantics.Description, id); } @@ -47,7 +61,7 @@ public async Task SetSemanticHeading() { var view = new TStub(); view.Semantics.HeadingLevel = SemanticHeadingLevel.Level1; - var id = await GetValueAsync((IView)view, handler => GetSemanticHeading(handler)); + var id = await GetValueAsync(view, handler => GetSemanticHeading(handler)); Assert.Equal(view.Semantics.HeadingLevel, id); } @@ -55,10 +69,12 @@ public async Task SetSemanticHeading() [InlineData()] public async Task NullSemanticsClass() { - var view = new TStub(); - view.Semantics = null; - view.AutomationId = "CreationFailed"; - var id = await GetValueAsync((IView)view, handler => GetAutomationId(handler)); + var view = new TStub + { + Semantics = null, + AutomationId = "CreationFailed" + }; + var id = await GetValueAsync(view, handler => GetAutomationId(handler)); Assert.Equal(view.AutomationId, id); } } diff --git a/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.iOS.cs b/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.iOS.cs index 0fe13146f934..4c87123973f2 100644 --- a/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.iOS.cs +++ b/src/Core/tests/DeviceTests/Handlers/HandlerTestBase.iOS.cs @@ -16,5 +16,29 @@ protected string GetSemanticHint(IViewHandler viewHandler) => protected SemanticHeadingLevel GetSemanticHeading(IViewHandler viewHandler) => ((UIView)viewHandler.NativeView).AccessibilityTraits.HasFlag(UIAccessibilityTrait.Header) ? SemanticHeadingLevel.Level1 : SemanticHeadingLevel.None; + + protected Visibility GetVisibility(IViewHandler viewHandler) + { + var nativeView = (UIView)viewHandler.NativeView; + + foreach (var constraint in nativeView.Constraints) + { + if (constraint is CollapseConstraint collapseConstraint) + { + // Active the collapse constraint; that will squish the view down to zero height + if (collapseConstraint.Active) + { + return Visibility.Collapsed; + } + } + } + + if (nativeView.Hidden) + { + return Visibility.Hidden; + } + + return Visibility.Visible; + } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Stubs/StubBase.cs b/src/Core/tests/DeviceTests/Stubs/StubBase.cs index ef26a2b573c4..14ba8b32bd6c 100644 --- a/src/Core/tests/DeviceTests/Stubs/StubBase.cs +++ b/src/Core/tests/DeviceTests/Stubs/StubBase.cs @@ -10,6 +10,10 @@ public class StubBase : IFrameworkElement { public bool IsEnabled { get; set; } = true; + public Visibility Visibility { get; set; } = Visibility.Visible; + + public double Opacity { get; set; } = 1.0d; + public Paint Background { get; set; } public Rectangle Frame { get; set; } diff --git a/src/Core/tests/UnitTests/TestClasses/ViewStub.cs b/src/Core/tests/UnitTests/TestClasses/ViewStub.cs index 7fdc199e4ee4..036e137cccc4 100644 --- a/src/Core/tests/UnitTests/TestClasses/ViewStub.cs +++ b/src/Core/tests/UnitTests/TestClasses/ViewStub.cs @@ -1,4 +1,3 @@ -using System; using Microsoft.Maui.Graphics; using Microsoft.Maui.Primitives; @@ -6,17 +5,13 @@ namespace Microsoft.Maui.UnitTests { class ViewStub : IViewStub { - public Thickness Margin { get; set; } - public bool IsEnabled { get; set; } - public Paint Background { get; set; } + public Visibility Visibility { get; set; } - public Rectangle Frame { get; set; } + public double Opacity { get; set; } - public double Width { get; set; } - - public double Height { get; set; } + public Rectangle Frame { get; set; } public IViewHandler Handler { get; set; } @@ -24,6 +19,14 @@ class ViewStub : IViewStub public Size DesiredSize { get; set; } + public bool IsMeasureValid { get; set; } + + public bool IsArrangeValid { get; set; } + + public double Width { get; set; } + + public double Height { get; set; } + public Thickness Margin { get; set; } public string AutomationId { get; set; } public FlowDirection FlowDirection { get; set; } @@ -34,8 +37,9 @@ class ViewStub : IViewStub public Semantics Semantics { get; set; } - public Size Arrange(Rectangle bounds) => - Size.Zero; + public Paint Background { get; set; } + + public Size Arrange(Rectangle bounds) => Size.Zero; public void InvalidateArrange() { }