зеркало из https://github.com/DeGsoft/maui-linux.git
259 строки
7.4 KiB
C#
259 строки
7.4 KiB
C#
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;
|
|
using Xamarin.Forms.Internals;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|