diff options
Diffstat (limited to 'Xamarin.Forms.Platform.UAP')
-rw-r--r-- | Xamarin.Forms.Platform.UAP/NavigationPageRendererUWP.cs | 97 | ||||
-rw-r--r-- | Xamarin.Forms.Platform.UAP/PlatformUWP.cs | 257 | ||||
-rw-r--r-- | Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj | 2 |
3 files changed, 356 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.UAP/NavigationPageRendererUWP.cs b/Xamarin.Forms.Platform.UAP/NavigationPageRendererUWP.cs new file mode 100644 index 00000000..a56ce903 --- /dev/null +++ b/Xamarin.Forms.Platform.UAP/NavigationPageRendererUWP.cs @@ -0,0 +1,97 @@ +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using Xamarin.Forms.PlatformConfiguration.WindowsSpecific; + +namespace Xamarin.Forms.Platform.UWP +{ + public partial class NavigationPageRenderer : IToolBarForegroundBinder + { + SystemNavigationManager _navManager; + + public void BindForegroundColor(AppBar appBar) + { + SetAppBarForegroundBinding(appBar); + } + + public void BindForegroundColor(AppBarButton button) + { + SetAppBarForegroundBinding(button); + } + + void SetAppBarForegroundBinding(FrameworkElement element) + { + element.SetBinding(Control.ForegroundProperty, + new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath("TitleBrush"), Source = _container, RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent } }); + } + + void UpdateToolbarPlacement() + { + if (_container == null) + { + return; + } + + _container.ToolbarPlacement = Element.OnThisPlatform().GetToolbarPlacement(); + } + + void UpdateShowTitle() + { + ((ITitleProvider)this).ShowTitle = _parentTabbedPage == null && _parentMasterDetailPage == null; + } + + static object GetDefaultColor() + { + return Windows.UI.Xaml.Application.Current.Resources["SystemControlBackgroundChromeMediumLowBrush"]; + } + + void UpdateBackButton() + { + bool showBackButton = PageController.InternalChildren.Count > 1 && NavigationPage.GetHasBackButton(_currentPage); + _container.ShowBackButton = showBackButton; + + if (_navManager != null) + { + _navManager.AppViewBackButtonVisibility = showBackButton ? AppViewBackButtonVisibility.Visible : AppViewBackButtonVisibility.Collapsed; + } + } + + async void UpdateTitleOnParents() + { + if (Element == null) + return; + + ITitleProvider render = null; + if (_parentTabbedPage != null) + { + render = Platform.GetRenderer(_parentTabbedPage) as ITitleProvider; + if (render != null) + render.ShowTitle = (_parentTabbedPage.CurrentPage == Element) && NavigationPage.GetHasNavigationBar(_currentPage); + } + + if (_parentMasterDetailPage != null) + { + render = Platform.GetRenderer(_parentMasterDetailPage) as ITitleProvider; + if (render != null) + render.ShowTitle = (_parentMasterDetailPage.Detail == Element) && NavigationPage.GetHasNavigationBar(_currentPage); + } + + if (render != null && render.ShowTitle) + { + render.Title = _currentPage.Title; + render.BarBackgroundBrush = GetBarBackgroundBrush(); + render.BarForegroundBrush = GetBarForegroundBrush(); + } + + if (_showTitle || (render != null && render.ShowTitle)) + { + var platform = Element.Platform as Platform; + if (platform != null) + { + await platform.UpdateToolbarItems(); + } + } + } + } +} diff --git a/Xamarin.Forms.Platform.UAP/PlatformUWP.cs b/Xamarin.Forms.Platform.UAP/PlatformUWP.cs new file mode 100644 index 00000000..83cb9129 --- /dev/null +++ b/Xamarin.Forms.Platform.UAP/PlatformUWP.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Windows.ApplicationModel.Core; +using Windows.Foundation; +using Windows.Foundation.Metadata; +using Windows.UI; +using Windows.UI.Core; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace Xamarin.Forms.Platform.UWP +{ + public abstract partial class Platform + { + internal static StatusBar MobileStatusBar => ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar") ? StatusBar.GetForCurrentView() : null; + + IToolbarProvider _toolbarProvider; + + void InitializeStatusBar() + { + StatusBar statusBar = MobileStatusBar; + if (statusBar != null) + { + statusBar.Showing += (sender, args) => UpdateBounds(); + statusBar.Hiding += (sender, args) => UpdateBounds(); + + // UWP 14393 Bug: If RequestedTheme is Light (which it is by default), then the + // status bar uses White Foreground with White Background. + // UWP 10586 Bug: If RequestedTheme is Light (which it is by default), then the + // status bar uses Black Foreground with Black Background. + // Since the Light theme should have a Black on White status bar, we will set it explicitly. + // This can be overriden by setting the status bar colors in App.xaml.cs OnLaunched. + + if (statusBar.BackgroundColor == null && statusBar.ForegroundColor == null && Windows.UI.Xaml.Application.Current.RequestedTheme == ApplicationTheme.Light) + { + statusBar.BackgroundColor = Colors.White; + statusBar.ForegroundColor = Colors.Black; + statusBar.BackgroundOpacity = 1; + } + } + } + + void UpdateToolbarTitle(Page page) + { + if (_toolbarProvider == null) + return; + + ((ToolbarProvider)_toolbarProvider).CommandBar.Content = page.Title; + } + + async void OnPageActionSheet(Page sender, ActionSheetArguments options) + { + List<string> buttons = options.Buttons.ToList(); + + var list = new Windows.UI.Xaml.Controls.ListView + { + Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["ActionSheetList"], + ItemsSource = buttons, + IsItemClickEnabled = true + }; + + var dialog = new ContentDialog + { + Template = (Windows.UI.Xaml.Controls.ControlTemplate)Windows.UI.Xaml.Application.Current.Resources["MyContentDialogControlTemplate"], + Content = list, + Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["ActionSheetStyle"] + }; + + if (options.Title != null) + dialog.Title = options.Title; + + list.ItemClick += (s, e) => + { + dialog.Hide(); + options.SetResult((string)e.ClickedItem); + }; + + TypedEventHandler<CoreWindow, CharacterReceivedEventArgs> onEscapeButtonPressed = delegate (CoreWindow window, CharacterReceivedEventArgs args) + { + if (args.KeyCode == 27) + { + dialog.Hide(); + options.SetResult(ContentDialogResult.None.ToString()); + } + }; + + Window.Current.CoreWindow.CharacterReceived += onEscapeButtonPressed; + + _actionSheetOptions = options; + + if (options.Cancel != null) + dialog.SecondaryButtonText = options.Cancel; + + if (options.Destruction != null) + dialog.PrimaryButtonText = options.Destruction; + + ContentDialogResult result = await dialog.ShowAsync(); + if (result == ContentDialogResult.Secondary) + options.SetResult(options.Cancel); + else if (result == ContentDialogResult.Primary) + options.SetResult(options.Destruction); + + Window.Current.CoreWindow.CharacterReceived -= onEscapeButtonPressed; + } + + void ClearCommandBar() + { + if (_toolbarProvider != null) + { + _toolbarProvider = null; + if (Device.Idiom == TargetIdiom.Phone) + _page.BottomAppBar = null; + else + _page.TopAppBar = null; + } + } + + CommandBar CreateCommandBar() + { + var bar = new FormsCommandBar(); + if (Device.Idiom != TargetIdiom.Phone) + bar.Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["TitleToolbar"]; + + _toolbarProvider = new ToolbarProvider(bar); + + if (Device.Idiom == TargetIdiom.Phone) + _page.BottomAppBar = bar; + else + _page.TopAppBar = bar; + + return bar; + } + + async Task<CommandBar> GetCommandBarAsync() + { + IToolbarProvider provider = GetToolbarProvider(); + if (provider == null) + { + return null; + } + + return await provider.GetCommandBarAsync(); + } + + void UpdateBounds() + { + _bounds = new Rectangle(0, 0, _page.ActualWidth, _page.ActualHeight); + + StatusBar statusBar = MobileStatusBar; + if (statusBar != null) + { + bool landscape = Device.Info.CurrentOrientation.IsLandscape(); + bool titleBar = CoreApplication.GetCurrentView().TitleBar.IsVisible; + double offset = landscape ? statusBar.OccludedRect.Width : statusBar.OccludedRect.Height; + + _bounds = new Rectangle(0, 0, _page.ActualWidth - (landscape ? offset : 0), _page.ActualHeight - (landscape ? 0 : offset)); + + // Even if the MainPage is a ContentPage not inside of a NavigationPage, the calculated bounds + // assume the TitleBar is there even if it isn't visible. When UpdatePageSizes is called, + // _container.ActualWidth is correct because it's aware that the TitleBar isn't there, but the + // bounds aren't, and things can subsequently run under the StatusBar. + if (!titleBar) + { + _bounds.Width -= (_bounds.Width - _container.ActualWidth); + } + } + } + + internal async Task UpdateToolbarItems() + { + CommandBar commandBar = await GetCommandBarAsync(); + if (commandBar != null) + { + commandBar.PrimaryCommands.Clear(); + commandBar.SecondaryCommands.Clear(); + + if (_page.BottomAppBar != null || _page.TopAppBar != null) + { + _page.BottomAppBar = null; + _page.TopAppBar = null; + _page.InvalidateMeasure(); + } + } + + var toolBarProvider = GetToolbarProvider() as IToolBarForegroundBinder; + + foreach (ToolbarItem item in _toolbarTracker.ToolbarItems.OrderBy(ti => ti.Priority)) + { + if (commandBar == null) + commandBar = CreateCommandBar(); + + toolBarProvider?.BindForegroundColor(commandBar); + + var button = new AppBarButton(); + button.SetBinding(AppBarButton.LabelProperty, "Text"); + button.SetBinding(AppBarButton.IconProperty, "Icon", _fileImageSourcePathConverter); + button.Command = new MenuItemCommand(item); + button.DataContext = item; + + ToolbarItemOrder order = item.Order == ToolbarItemOrder.Default ? ToolbarItemOrder.Primary : item.Order; + if (order == ToolbarItemOrder.Primary) + { + toolBarProvider?.BindForegroundColor(button); + commandBar.PrimaryCommands.Add(button); + } + else + { + commandBar.SecondaryCommands.Add(button); + } + } + + if (commandBar?.PrimaryCommands.Count + commandBar?.SecondaryCommands.Count == 0) + ClearCommandBar(); + } + + internal IToolbarProvider GetToolbarProvider() + { + IToolbarProvider provider = null; + + Page element = _currentPage; + while (element != null) + { + provider = GetRenderer(element) as IToolbarProvider; + if (provider != null) + break; + + var pageContainer = element as IPageContainer<Page>; + element = pageContainer?.CurrentPage; + } + + if (provider != null && _toolbarProvider == null) + ClearCommandBar(); + + return provider; + } + + class ToolbarProvider : IToolbarProvider + { + readonly Task<CommandBar> _commandBar; + + public ToolbarProvider(CommandBar commandBar) + { + _commandBar = Task.FromResult(commandBar); + } + + public CommandBar CommandBar => _commandBar.Result; + + public Task<CommandBar> GetCommandBarAsync() + { + return _commandBar; + } + } + } +} diff --git a/Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj b/Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj index 66ab6023..ec7bca5a 100644 --- a/Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj +++ b/Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj @@ -192,6 +192,8 @@ <Compile Include="IToolBarForegroundBinder.cs" /> <Compile Include="NativeBindingService.cs" /> <Compile Include="NativeValueConverterService.cs" /> + <Compile Include="NavigationPageRendererUWP.cs" /> + <Compile Include="PlatformUWP.cs" /> <Compile Include="SearchBarRenderer.cs" /> <Compile Include="..\Xamarin.Forms.Platform.WinRT\TextAlignmentToHorizontalAlignmentConverter.cs"> <Link>TextAlignmentToHorizontalAlignmentConverter.cs</Link> |