[Android] ToolbarHandler and fixes for various page nesting scenarios (#2781)
* Nested Navigation Page setup * - toolbar handler * - remove control root manager for now * - clean up events * - cleanup code * - remove no longer needed handlers * - cleanup shell code * - cleanup adding removing tabbedpage * - cleanup adding removing pages * - fix up fragment reuse * - cleanup * - create remap for shell * - mapper extension methods * - fix bottom tabs offset * - rename to StackNavigationManager * - toolbar not visible by default * - IElement only * - fix toolbar to be more swappable * - remove navigationlayout * - fix toolbar so it recreates if app is refreshed * - if user doesn't handle back event and there are no more pages in the stack then just close the activity * - fix context stub * - fix test * - merge with main * - remove static classes * - remove code * - fix tests * - fix parenting check * - fix appearing tests to work with window * Update src/Controls/src/Core/Handlers/Toolbar/ToolbarHandler.Android.cs Co-authored-by: Matthew Leibowitz <mattleibow@live.com> * - only create top level root manager * - fix nav root creation * WinUI Toolbar Handler (#2875) * Wire up Window ToolbarHandler * - fix NRE * - fix null exception * - fix compile error Co-authored-by: Matthew Leibowitz <mattleibow@live.com>
This commit is contained in:
Родитель
9903a2c0fb
Коммит
e2f3aaa222
|
@ -2,6 +2,7 @@ using System;
|
|||
using Android.Content;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using AndroidX.CoordinatorLayout.Widget;
|
||||
using AndroidX.Fragment.App;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
|
@ -32,7 +33,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
Child.UpdateLayout();
|
||||
|
||||
if (Child.View is ContentViewGroup ||
|
||||
Child.View is NavigationLayout ||
|
||||
Child.View is CoordinatorLayout ||
|
||||
Child.View is FragmentContainerView)
|
||||
{
|
||||
// This is a way to handle situations where the root page is shimmed and uses fragments to host other pages (e.g., NavigationPageRenderer)
|
||||
|
|
|
@ -11,6 +11,7 @@ using Microsoft.Maui.Controls.Platform;
|
|||
using AndroidAnimation = Android.Views.Animations.Animation;
|
||||
using AnimationSet = Android.Views.Animations.AnimationSet;
|
||||
using AView = Android.Views.View;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
||||
{
|
||||
|
@ -68,7 +69,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
AView _root;
|
||||
ShellPageContainer _shellPageContainer;
|
||||
ShellContent _shellContent;
|
||||
Toolbar _toolbar;
|
||||
AToolbar _toolbar;
|
||||
IShellToolbarTracker _toolbarTracker;
|
||||
bool _disposed;
|
||||
|
||||
|
@ -133,7 +134,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
|
||||
_root = inflater.Inflate(Resource.Layout.shellcontent, null).JavaCast<CoordinatorLayout>();
|
||||
|
||||
_toolbar = _root.FindViewById<Toolbar>(Resource.Id.shellcontent_toolbar);
|
||||
_toolbar = _root.FindViewById<AToolbar>(Resource.Id.shellcontent_toolbar);
|
||||
|
||||
_renderer = Platform.CreateRenderer(_page, Context);
|
||||
Platform.SetRenderer(_page, _renderer);
|
||||
|
|
|
@ -16,7 +16,7 @@ using AView = Android.Views.View;
|
|||
using Color = Microsoft.Maui.Graphics.Color;
|
||||
using LP = Android.Views.ViewGroup.LayoutParams;
|
||||
using Paint = Android.Graphics.Paint;
|
||||
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
||||
{
|
||||
|
@ -105,7 +105,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
return CreateShellSectionRenderer(shellSection);
|
||||
}
|
||||
|
||||
IShellToolbarTracker Microsoft.Maui.Controls.Platform.IShellContext.CreateTrackerForToolbar(Toolbar toolbar)
|
||||
IShellToolbarTracker Microsoft.Maui.Controls.Platform.IShellContext.CreateTrackerForToolbar(AToolbar toolbar)
|
||||
{
|
||||
return CreateTrackerForToolbar(toolbar);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
return new ShellSectionRenderer(this);
|
||||
}
|
||||
|
||||
protected virtual IShellToolbarTracker CreateTrackerForToolbar(Toolbar toolbar)
|
||||
protected virtual IShellToolbarTracker CreateTrackerForToolbar(AToolbar toolbar)
|
||||
{
|
||||
return new ShellToolbarTracker(this, toolbar, ((IShellContext)this).CurrentDrawerLayout);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ using Google.Android.Material.Tabs;
|
|||
using Microsoft.Maui.Controls.Compatibility.Platform.Android.AppCompat;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using AView = Android.Views.View;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
||||
{
|
||||
|
@ -114,7 +115,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
bool _selecting;
|
||||
TabLayout _tablayout;
|
||||
IShellTabLayoutAppearanceTracker _tabLayoutAppearanceTracker;
|
||||
Toolbar _toolbar;
|
||||
AToolbar _toolbar;
|
||||
IShellToolbarAppearanceTracker _toolbarAppearanceTracker;
|
||||
IShellToolbarTracker _toolbarTracker;
|
||||
FormsViewPager _viewPager;
|
||||
|
@ -143,7 +144,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
|
||||
var root = inflater.Inflate(Resource.Layout.rootlayout, null).JavaCast<CoordinatorLayout>();
|
||||
|
||||
_toolbar = root.FindViewById<Toolbar>(Resource.Id.maui_toolbar);
|
||||
_toolbar = root.FindViewById<AToolbar>(Resource.Id.maui_toolbar);
|
||||
_viewPager = root.FindViewById<FormsViewPager>(Resource.Id.main_viewpager);
|
||||
_tablayout = root.FindViewById<TabLayout>(Resource.Id.main_tablayout);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ using Android.Graphics.Drawables;
|
|||
using AndroidX.AppCompat.Widget;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
||||
{
|
||||
|
@ -17,7 +18,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
_shellContext = shellContext;
|
||||
}
|
||||
|
||||
public virtual void SetAppearance(Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
|
||||
public virtual void SetAppearance(AToolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
|
||||
{
|
||||
var foreground = appearance.ForegroundColor;
|
||||
var background = appearance.BackgroundColor;
|
||||
|
@ -26,12 +27,12 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
SetColors(toolbar, toolbarTracker, foreground, background, titleColor);
|
||||
}
|
||||
|
||||
public virtual void ResetAppearance(Toolbar toolbar, IShellToolbarTracker toolbarTracker)
|
||||
public virtual void ResetAppearance(AToolbar toolbar, IShellToolbarTracker toolbarTracker)
|
||||
{
|
||||
SetColors(toolbar, toolbarTracker, ShellRenderer.DefaultForegroundColor, ShellRenderer.DefaultBackgroundColor, ShellRenderer.DefaultTitleColor);
|
||||
}
|
||||
|
||||
protected virtual void SetColors(Toolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Color background, Color title)
|
||||
protected virtual void SetColors(AToolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Color background, Color title)
|
||||
{
|
||||
var titleArgb = title.ToAndroid(ShellRenderer.DefaultTitleColor).ToArgb();
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ using Color = Microsoft.Maui.Graphics.Color;
|
|||
using LP = Android.Views.ViewGroup.LayoutParams;
|
||||
using Paint = Android.Graphics.Paint;
|
||||
using R = Android.Resource;
|
||||
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
||||
{
|
||||
|
@ -57,14 +57,14 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
protected IShellContext ShellContext { get; private set; }
|
||||
//assume the default
|
||||
Color _tintColor = null;
|
||||
Toolbar _toolbar;
|
||||
AToolbar _toolbar;
|
||||
AppBarLayout _appBar;
|
||||
float _appBarElevation;
|
||||
GenericGlobalLayoutListener _globalLayoutListener;
|
||||
List<IMenuItem> _currentMenuItems = new List<IMenuItem>();
|
||||
List<ToolbarItem> _currentToolbarItems = new List<ToolbarItem>();
|
||||
|
||||
public ShellToolbarTracker(IShellContext shellContext, Toolbar toolbar, DrawerLayout drawerLayout)
|
||||
public ShellToolbarTracker(IShellContext shellContext, AToolbar toolbar, DrawerLayout drawerLayout)
|
||||
{
|
||||
ShellContext = shellContext ?? throw new ArgumentNullException(nameof(shellContext));
|
||||
_toolbar = toolbar ?? throw new ArgumentNullException(nameof(toolbar));
|
||||
|
@ -333,7 +333,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
return image;
|
||||
}
|
||||
|
||||
protected virtual async void UpdateLeftBarButtonItem(Context context, Toolbar toolbar, DrawerLayout drawerLayout, Page page)
|
||||
protected virtual async void UpdateLeftBarButtonItem(Context context, AToolbar toolbar, DrawerLayout drawerLayout, Page page)
|
||||
{
|
||||
if (_drawerToggle == null)
|
||||
{
|
||||
|
@ -435,12 +435,12 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
}
|
||||
|
||||
|
||||
protected virtual Task UpdateDrawerArrow(Context context, Toolbar toolbar, DrawerLayout drawerLayout)
|
||||
protected virtual Task UpdateDrawerArrow(Context context, AToolbar toolbar, DrawerLayout drawerLayout)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual void UpdateToolbarIconAccessibilityText(Toolbar toolbar, Shell shell)
|
||||
protected virtual void UpdateToolbarIconAccessibilityText(AToolbar toolbar, Shell shell)
|
||||
{
|
||||
var backButtonHandler = Shell.GetBackButtonBehavior(Page);
|
||||
var image = GetFlyoutIcon(backButtonHandler, Page);
|
||||
|
@ -459,7 +459,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual Task UpdateDrawerArrowFromBackButtonBehavior(Context context, Toolbar toolbar, DrawerLayout drawerLayout, BackButtonBehavior backButtonHandler)
|
||||
protected virtual Task UpdateDrawerArrowFromBackButtonBehavior(Context context, AToolbar toolbar, DrawerLayout drawerLayout, BackButtonBehavior backButtonHandler)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
});
|
||||
}
|
||||
|
||||
protected virtual void UpdateNavBarVisible(Toolbar toolbar, Page page)
|
||||
protected virtual void UpdateNavBarVisible(AToolbar toolbar, Page page)
|
||||
{
|
||||
var navBarVisible = Shell.GetNavBarIsVisible(page);
|
||||
toolbar.Visibility = navBarVisible ? ViewStates.Visible : ViewStates.Gone;
|
||||
|
@ -510,12 +510,12 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdatePageTitle(Toolbar toolbar, Page page)
|
||||
protected virtual void UpdatePageTitle(AToolbar toolbar, Page page)
|
||||
{
|
||||
_toolbar.Title = page.Title;
|
||||
}
|
||||
|
||||
protected virtual void UpdateTitleView(Context context, Toolbar toolbar, View titleView)
|
||||
protected virtual void UpdateTitleView(Context context, AToolbar toolbar, View titleView)
|
||||
{
|
||||
if (titleView == null)
|
||||
{
|
||||
|
@ -530,7 +530,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
{
|
||||
_titleViewContainer = new ContainerView(context, titleView);
|
||||
_titleViewContainer.MatchHeight = _titleViewContainer.MatchWidth = true;
|
||||
_titleViewContainer.LayoutParameters = new Toolbar.LayoutParams(LP.MatchParent, LP.MatchParent)
|
||||
_titleViewContainer.LayoutParameters = new AToolbar.LayoutParams(LP.MatchParent, LP.MatchParent)
|
||||
{
|
||||
LeftMargin = (int)context.ToPixels(titleView.Margin.Left),
|
||||
TopMargin = (int)context.ToPixels(titleView.Margin.Top),
|
||||
|
@ -546,7 +546,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateToolbarItems(Toolbar toolbar, Page page)
|
||||
protected virtual void UpdateToolbarItems(AToolbar toolbar, Page page)
|
||||
{
|
||||
var menu = toolbar.Menu;
|
||||
var sortedItems = page.ToolbarItems.OrderBy(x => x.Order);
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel;
|
||||
using Android.Content;
|
||||
using Android.Views;
|
||||
using AndroidX.CoordinatorLayout.Widget;
|
||||
using AndroidX.Fragment.App;
|
||||
using Microsoft.Maui.Controls.Internals;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
|
@ -97,7 +98,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
|
|||
formsViewGroup.MeasureAndLayout(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.Exactly), x, y, x + width, y + height);
|
||||
Performance.Stop(reference, "MeasureAndLayout");
|
||||
}
|
||||
else if ((aview is LayoutViewGroup || aview is ContentViewGroup || aview is NavigationLayout || aview is FragmentContainerView) && width == 0 && height == 0)
|
||||
else if ((aview is LayoutViewGroup || aview is ContentViewGroup || aview is CoordinatorLayout || aview is FragmentContainerView) && width == 0 && height == 0)
|
||||
{
|
||||
// Nothing to do here; just chill.
|
||||
}
|
||||
|
|
|
@ -163,6 +163,7 @@ namespace Microsoft.Maui.Controls.Hosting
|
|||
VisualElement.RemapForControls();
|
||||
Label.RemapForControls();
|
||||
Button.RemapForControls();
|
||||
Window.RemapForControls();
|
||||
});
|
||||
|
||||
builder.AddMauiCompat();
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP
|
||||
{
|
||||
internal class MenuItemCommand : ICommand
|
||||
{
|
||||
readonly MenuItem _menuItem;
|
||||
|
||||
public MenuItemCommand(MenuItem item)
|
||||
{
|
||||
_menuItem = item;
|
||||
_menuItem.PropertyChanged += OnElementPropertyChanged;
|
||||
}
|
||||
|
||||
public virtual bool CanExecute(object parameter)
|
||||
{
|
||||
return _menuItem.IsEnabled;
|
||||
}
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
((IMenuItemController)_menuItem).Activate();
|
||||
}
|
||||
|
||||
void OnCanExecuteChanged()
|
||||
{
|
||||
EventHandler changed = CanExecuteChanged;
|
||||
if (changed != null)
|
||||
changed(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
|
||||
OnCanExecuteChanged();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -143,5 +143,10 @@
|
|||
<Link>Resources\layout\rootlayout.axml</Link>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="..\..\..\Core\src\Platform\Android\Resources\Layout\fragment_backstack.axml">
|
||||
<Link>Resources\layout\fragment_backstack.axml</Link>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
|
@ -6,8 +6,9 @@
|
|||
xmlns:views="clr-namespace:Maui.Controls.Sample.Pages.Base"
|
||||
Title="Tabbed Page">
|
||||
<ContentPage Title="Tab 1">
|
||||
<StackLayout>
|
||||
<Label Text="Welcome to Tab 1"></Label>
|
||||
</StackLayout>
|
||||
<VerticalStackLayout>
|
||||
<Button Text="Set Tabbed Page as Root" Clicked="OnTabbedPageAsRoot"></Button>
|
||||
<Button Text="Toggle Bottom Tabs (Android)" Clicked="OnSetToBottomTabs"></Button>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
||||
</TabbedPage>
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
using AndroidSpecific = Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;
|
||||
namespace Maui.Controls.Sample.Pages
|
||||
{
|
||||
public partial class TabbedPageGallery
|
||||
|
@ -10,5 +11,40 @@ namespace Maui.Controls.Sample.Pages
|
|||
InitializeComponent();
|
||||
this.Children.Add(new NavigationGallery());
|
||||
}
|
||||
|
||||
void OnTabbedPageAsRoot(object sender, EventArgs e)
|
||||
{
|
||||
var topTabs =
|
||||
new TabbedPage()
|
||||
{
|
||||
Children =
|
||||
{
|
||||
Handler.MauiContext.Services.GetRequiredService<Page>(),
|
||||
new NavigationPage(new Pages.NavigationGallery()) { Title = "Navigation Gallery" }
|
||||
}
|
||||
};
|
||||
|
||||
this.Handler?.DisconnectHandler();
|
||||
Application.Current.MainPage?.Handler?.DisconnectHandler();
|
||||
Application.Current.MainPage = topTabs;
|
||||
}
|
||||
|
||||
void OnSetToBottomTabs(object sender, EventArgs e)
|
||||
{
|
||||
var bottomTabs = new TabbedPage()
|
||||
{
|
||||
Children =
|
||||
{
|
||||
Handler.MauiContext.Services.GetRequiredService<Page>(),
|
||||
new NavigationPage(new Pages.NavigationGallery()) { Title = "Navigation Gallery" }
|
||||
}
|
||||
};
|
||||
|
||||
this.Handler?.DisconnectHandler();
|
||||
Application.Current.MainPage?.Handler?.DisconnectHandler();
|
||||
|
||||
AndroidSpecific.TabbedPage.SetToolbarPlacement(bottomTabs, AndroidSpecific.ToolbarPlacement.Bottom);
|
||||
Application.Current.MainPage = bottomTabs;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,4 +51,4 @@
|
|||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</views:BasePage.Content>
|
||||
</views:BasePage>
|
||||
</views:BasePage>
|
|
@ -3,6 +3,6 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Maui.Controls.Sample.Pages.CustomNavigationPage"
|
||||
BarBackgroundColor="{AppThemeBinding Light={StaticResource LightAccentColor}, Dark={StaticResource DarkAccentColor}}"
|
||||
BarTextColor="{StaticResource WhiteColor}"
|
||||
BarTextColor="{StaticResource WhiteColor}"
|
||||
Title="Custom Nav Page">
|
||||
</NavigationPage>
|
||||
|
|
|
@ -12,4 +12,4 @@ namespace Maui.Controls.Sample.Pages
|
|||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
xmlns:views="clr-namespace:Maui.Controls.Sample.Pages.Base"
|
||||
x:Name="HomePage"
|
||||
BackgroundColor="{DynamicResource BackgroundColor}"
|
||||
NavigationPage.IconColor="Pink"
|
||||
Title="Gallery">
|
||||
<views:BasePage.Resources>
|
||||
<ResourceDictionary>
|
||||
|
|
|
@ -28,4 +28,4 @@ namespace Maui.Controls.Sample
|
|||
|
||||
public IServiceProvider Services { get; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,11 @@ namespace Microsoft.Maui.Controls
|
|||
{
|
||||
public partial class NavigationPage : INavigationView
|
||||
{
|
||||
partial void Init()
|
||||
{
|
||||
this.Appearing += OnAppearing;
|
||||
}
|
||||
|
||||
Thickness IView.Margin => Thickness.Zero;
|
||||
|
||||
protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
|
||||
|
@ -86,34 +91,24 @@ namespace Microsoft.Maui.Controls
|
|||
|
||||
IReadOnlyList<IView> NavigationStack => this.Navigation.NavigationStack;
|
||||
|
||||
static void CurrentPagePropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
|
||||
static void OnCurrentPageChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
var np = (NavigationPage)bindable;
|
||||
if (oldValue is Page oldPage)
|
||||
oldPage.SendDisappearing();
|
||||
|
||||
if (oldValue is INotifyPropertyChanged ncpOld)
|
||||
{
|
||||
ncpOld.PropertyChanged -= np.CurrentPagePropertyChanged;
|
||||
}
|
||||
|
||||
if (newValue is INotifyPropertyChanged ncpNew)
|
||||
{
|
||||
ncpNew.PropertyChanged += np.CurrentPagePropertyChanged;
|
||||
}
|
||||
if (newValue is Page newPage && ((NavigationPage)bindable).HasAppeared)
|
||||
newPage.SendAppearing();
|
||||
}
|
||||
|
||||
void CurrentPagePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.IsOneOf(NavigationPage.HasNavigationBarProperty,
|
||||
NavigationPage.HasBackButtonProperty,
|
||||
NavigationPage.TitleIconImageSourceProperty,
|
||||
NavigationPage.TitleViewProperty,
|
||||
NavigationPage.IconColorProperty) ||
|
||||
e.IsOneOf(Page.TitleProperty, PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage.BarHeightProperty))
|
||||
{
|
||||
Handler?.UpdateValue(e.PropertyName);
|
||||
}
|
||||
}
|
||||
|
||||
void OnAppearing(object sender, EventArgs e)
|
||||
{
|
||||
// Update the Window level Toolbar with my Toolbar information
|
||||
var window = this.FindParentOfType<Window>();
|
||||
if (window?.Toolbar != null)
|
||||
window.Toolbar.ApplyNavigationPage(this);
|
||||
}
|
||||
|
||||
Task WaitForCurrentNavigationTask() =>
|
||||
CurrentNavigationTask ?? Task.CompletedTask;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System;
|
||||
using Android.App;
|
||||
using AndroidX.AppCompat.App;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Microsoft.Maui.Controls
|
||||
{
|
||||
|
|
|
@ -24,8 +24,11 @@ namespace Microsoft.Maui.Controls
|
|||
ReadOnlyCollection<Element>? _logicalChildren;
|
||||
List<IVisualTreeElement> _visualChildren;
|
||||
|
||||
internal Toolbar Toolbar { get; }
|
||||
|
||||
public Window()
|
||||
{
|
||||
Toolbar = new Toolbar();
|
||||
_visualChildren = new List<IVisualTreeElement>();
|
||||
AlertManager = new AlertManager(this);
|
||||
ModalNavigationManager = new ModalNavigationManager(this);
|
||||
|
@ -259,7 +262,7 @@ namespace Microsoft.Maui.Controls
|
|||
}
|
||||
}
|
||||
|
||||
bool IWindow.BackButtonPressed()
|
||||
bool IWindow.BackButtonClicked()
|
||||
{
|
||||
return this.Page?.SendBackButtonPressed() ?? false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Microsoft.Maui.Controls
|
||||
{
|
||||
public partial class Window
|
||||
{
|
||||
public static IPropertyMapper<IWindow, WindowHandler> ControlsLabelMapper = new PropertyMapper<IWindow, WindowHandler>(WindowHandler.WindowMapper)
|
||||
{
|
||||
#if __ANDROID__ || WINDOWS
|
||||
[nameof(IWindow.Content)] = MapContent,
|
||||
[nameof(Toolbar)] = MapToolbar,
|
||||
#endif
|
||||
};
|
||||
|
||||
public static void RemapForControls()
|
||||
{
|
||||
WindowHandler.WindowMapper = ControlsLabelMapper;
|
||||
}
|
||||
|
||||
|
||||
#if ANDROID || WINDOWS
|
||||
public static void MapToolbar(WindowHandler handler, IWindow view)
|
||||
{
|
||||
_ = handler.MauiContext ?? throw new InvalidOperationException($"{nameof(handler.MauiContext)} null");
|
||||
|
||||
if (view is Window window && window.Toolbar != null)
|
||||
{
|
||||
_ = window.Toolbar.ToNative(handler.MauiContext);
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapContent(WindowHandler handler, IWindow view)
|
||||
{
|
||||
if (view.Content is not Shell)
|
||||
{
|
||||
WindowHandler.MapContent(handler, view);
|
||||
return;
|
||||
}
|
||||
#if ANDROID
|
||||
var nativeContent = view.Content.ToContainerView(handler.MauiContext!);
|
||||
handler.NativeView.SetContentView(nativeContent);
|
||||
#else
|
||||
if (handler.NativeView.Content is UI.Xaml.Controls.Panel panel)
|
||||
{
|
||||
var nativeContent = view.Content.ToNative(handler.MauiContext!);
|
||||
panel.Children.Clear();
|
||||
panel.Children.Add(nativeContent);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Handlers
|
||||
{
|
||||
// Currently only inheriting because we can't tap into CreateNativeView
|
||||
// Once we can wire up into CreateNativeView then all of this code can move into the
|
||||
// Remap structures
|
||||
internal partial class NavigationPageHandler : NavigationViewHandler
|
||||
{
|
||||
public static PropertyMapper<NavigationPage, NavigationPageHandler> NavigationPageMapper =
|
||||
new PropertyMapper<NavigationPage, NavigationPageHandler>(NavigationViewHandler.NavigationViewMapper)
|
||||
{
|
||||
[NavigationPage.HasNavigationBarProperty.PropertyName] = UpdateToolBar,
|
||||
[NavigationPage.HasBackButtonProperty.PropertyName] = UpdateToolBar,
|
||||
[NavigationPage.TitleIconImageSourceProperty.PropertyName] = UpdateToolBar,
|
||||
[NavigationPage.TitleViewProperty.PropertyName] = UpdateToolBar,
|
||||
[NavigationPage.IconColorProperty.PropertyName] = UpdateToolBar,
|
||||
[Page.TitleProperty.PropertyName] = UpdateToolBar,
|
||||
[NavigationPage.CurrentPageProperty.PropertyName] = UpdateToolBar,
|
||||
[PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage.BarHeightProperty.PropertyName] = UpdateToolBar,
|
||||
};
|
||||
|
||||
ControlsNavigationManager _controlsNavigationManager;
|
||||
public NavigationPageHandler() : base(NavigationPageMapper)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override NavigationManager CreateNavigationManager()
|
||||
=> _controlsNavigationManager ??= new ControlsNavigationManager(MauiContext);
|
||||
|
||||
private static void UpdateToolBar(NavigationPageHandler arg1, NavigationPage arg2)
|
||||
{
|
||||
arg1._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
using System;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Handlers
|
||||
{
|
||||
// Currently only inheriting because we can't tap into CreateNativeView
|
||||
// Once we can wire up into CreateNativeView then all of this code can move into the
|
||||
// Remap structures
|
||||
internal partial class NavigationPageHandler : Microsoft.Maui.Handlers.NavigationViewHandler
|
||||
{
|
||||
public static PropertyMapper<NavigationPage, NavigationPageHandler> NavigationPageMapper =
|
||||
new PropertyMapper<NavigationPage, NavigationPageHandler>(NavigationViewHandler.NavigationViewMapper)
|
||||
{
|
||||
[NavigationPage.HasNavigationBarProperty.PropertyName] = MapHasNavigationBar,
|
||||
[NavigationPage.HasBackButtonProperty.PropertyName] = MapHasBackButton,
|
||||
[NavigationPage.TitleIconImageSourceProperty.PropertyName] = MapTitleIconImageSource,
|
||||
[NavigationPage.TitleViewProperty.PropertyName] = MapTitleView,
|
||||
[NavigationPage.IconColorProperty.PropertyName] = MapIconColor,
|
||||
[Page.TitleProperty.PropertyName] = MapTitle,
|
||||
[NavigationPage.CurrentPageProperty.PropertyName] = MapCurrentPage,
|
||||
[NavigationPage.BarBackgroundColorProperty.PropertyName] = MapBarBackground,
|
||||
[NavigationPage.BarBackgroundProperty.PropertyName] = MapBarBackground,
|
||||
[PlatformConfiguration.WindowsSpecific.Page.ToolbarPlacementProperty.PropertyName] = MapToolbarPlacement,
|
||||
[PlatformConfiguration.WindowsSpecific.Page.ToolbarDynamicOverflowEnabledProperty.PropertyName] = MapToolbarDynamicOverflowEnabled,
|
||||
};
|
||||
|
||||
// TODO MAUI: break these out into extension methods
|
||||
public static void MapBarBackground(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapToolbarDynamicOverflowEnabled(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapToolbarPlacement(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapCurrentPage(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapTitle(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapIconColor(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapTitleView(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapTitleIconImageSource(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapHasBackButton(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
public static void MapHasNavigationBar(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
|
||||
ControlsNavigationManager _controlsNavigationManager;
|
||||
public NavigationPageHandler() : base(NavigationPageMapper)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override NavigationManager CreateNavigationManager()
|
||||
=> _controlsNavigationManager ??= new ControlsNavigationManager(MauiContext!);
|
||||
|
||||
public static void UpdateToolBar(NavigationPageHandler handler, NavigationPage view)
|
||||
{
|
||||
handler._controlsNavigationManager.ToolbarPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,16 +11,11 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
{
|
||||
public sealed class TabbedPageHandler : ViewHandler<TabbedPage, ViewPager2>
|
||||
{
|
||||
public TabLayout TabLayout =>
|
||||
_tabbedPageManager.IsBottomTabPlacement ? null :
|
||||
_tabbedPageManager.TabLayout;
|
||||
|
||||
public BottomNavigationView BottomNavigationView =>
|
||||
_tabbedPageManager.IsBottomTabPlacement ? _tabbedPageManager.BottomNavigationView :
|
||||
null;
|
||||
public static PropertyMapper<TabbedPage, TabbedPageHandler> Mapper =
|
||||
new PropertyMapper<TabbedPage, TabbedPageHandler>(ViewMapper);
|
||||
|
||||
TabbedPageManager _tabbedPageManager;
|
||||
public TabbedPageHandler() : base(ViewHandler.ViewMapper, null)
|
||||
public TabbedPageHandler() : base(Mapper, null)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -35,5 +30,11 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
base.SetVirtualView(view);
|
||||
_tabbedPageManager.SetElement((TabbedPage)view);
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(ViewPager2 nativeView)
|
||||
{
|
||||
base.DisconnectHandler(nativeView);
|
||||
_tabbedPageManager.SetElement(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Android.Content;
|
||||
using Android.Content.Res;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.Views;
|
||||
using AndroidX.AppCompat.App;
|
||||
using AndroidX.AppCompat.Graphics.Drawable;
|
||||
using AndroidX.DrawerLayout.Widget;
|
||||
using Google.Android.Material.AppBar;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Handlers
|
||||
{
|
||||
public partial class ToolbarHandler : ElementHandler<Toolbar, MaterialToolbar>
|
||||
{
|
||||
IViewHandler? _titleViewHandler;
|
||||
Container? _titleView;
|
||||
List<IMenuItem> _currentMenuItems = new List<IMenuItem>();
|
||||
List<ToolbarItem> _currentToolbarItems = new List<ToolbarItem>();
|
||||
|
||||
NavigationRootManager? NavigationRootManager =>
|
||||
MauiContext?.GetNavigationRootManager();
|
||||
|
||||
protected override MaterialToolbar CreateNativeElement()
|
||||
{
|
||||
return NavigationRootManager!
|
||||
.NavigationLayout
|
||||
.FindViewById<MaterialToolbar>(Resource.Id.navigationlayout_toolbar)!;
|
||||
}
|
||||
|
||||
protected virtual void OnToolbarItemPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
var toolbarItems = VirtualView.ToolbarItems;
|
||||
List<ToolbarItem> newToolBarItems = new List<ToolbarItem>();
|
||||
if (toolbarItems != null)
|
||||
newToolBarItems.AddRange(toolbarItems);
|
||||
|
||||
if (sender is ToolbarItem ti)
|
||||
NativeView.OnToolbarItemPropertyChanged(e, ti, newToolBarItems, MauiContext!, null, OnToolbarItemPropertyChanged, _currentMenuItems, _currentToolbarItems, UpdateMenuItemIcon);
|
||||
}
|
||||
|
||||
protected virtual void UpdateMenuItemIcon(Context context, IMenuItem menuItem, ToolbarItem toolBarItem)
|
||||
{
|
||||
_ = MauiContext ?? throw new ArgumentNullException(nameof(MauiContext));
|
||||
ToolbarExtensions.UpdateMenuItemIcon(MauiContext, menuItem, toolBarItem, null);
|
||||
}
|
||||
|
||||
void UpdateMenu()
|
||||
{
|
||||
_ = MauiContext ?? throw new ArgumentNullException(nameof(MauiContext));
|
||||
|
||||
if (_currentMenuItems == null)
|
||||
return;
|
||||
|
||||
NativeView.UpdateMenuItems(VirtualView.ToolbarItems, MauiContext, null, OnToolbarItemPropertyChanged, _currentMenuItems, _currentToolbarItems, UpdateMenuItemIcon);
|
||||
}
|
||||
|
||||
void UpdateTitleView()
|
||||
{
|
||||
_ = MauiContext ?? throw new ArgumentNullException(nameof(MauiContext));
|
||||
_ = MauiContext.Context ?? throw new ArgumentNullException(nameof(MauiContext.Context));
|
||||
|
||||
VisualElement titleView = VirtualView.TitleView;
|
||||
if (_titleViewHandler != null)
|
||||
{
|
||||
var reflectableType = _titleViewHandler as System.Reflection.IReflectableType;
|
||||
var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : _titleViewHandler.GetType();
|
||||
if (titleView == null || Internals.Registrar.Registered.GetHandlerTypeForObject(titleView) != rendererType)
|
||||
{
|
||||
if (_titleView != null)
|
||||
_titleView.Child = null;
|
||||
|
||||
if (_titleViewHandler?.VirtualView != null)
|
||||
_titleViewHandler.VirtualView.Handler = null;
|
||||
|
||||
_titleViewHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (titleView == null)
|
||||
return;
|
||||
|
||||
if (_titleViewHandler != null)
|
||||
_titleViewHandler.SetVirtualView(titleView);
|
||||
else
|
||||
{
|
||||
titleView.ToNative(MauiContext);
|
||||
_titleViewHandler = titleView.Handler;
|
||||
|
||||
if (_titleView == null)
|
||||
{
|
||||
_titleView = new Container(MauiContext.Context);
|
||||
NativeView.AddView(_titleView);
|
||||
}
|
||||
|
||||
_titleView.Child = (INativeViewHandler)_titleViewHandler;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void MapBarTextColor(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBarTextColor(arg2);
|
||||
}
|
||||
|
||||
public static void MapBarBackground(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBarBackground(arg2);
|
||||
}
|
||||
|
||||
public static void MapBarBackgroundColor(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBarBackgroundColor(arg2);
|
||||
}
|
||||
|
||||
public static void MapBackButtonTitle(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBackButton(arg2);
|
||||
}
|
||||
|
||||
public static void MapToolbarItems(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.UpdateMenu();
|
||||
}
|
||||
|
||||
public static void MapTitle(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateTitle(arg2);
|
||||
}
|
||||
|
||||
public static void MapIconColor(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateIconColor(arg2);
|
||||
}
|
||||
|
||||
public static void MapTitleView(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.UpdateTitleView();
|
||||
}
|
||||
|
||||
public static void MapTitleIcon(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateTitleIcon(arg2);
|
||||
}
|
||||
|
||||
public static void MapBackButtonVisible(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBackButton(arg2);
|
||||
}
|
||||
|
||||
public static void MapIsVisible(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateIsVisible(arg2);
|
||||
}
|
||||
|
||||
internal class Container : ViewGroup
|
||||
{
|
||||
INativeViewHandler? _child;
|
||||
|
||||
public Container(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public INativeViewHandler? Child
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_child != null)
|
||||
RemoveView(_child.NativeView);
|
||||
|
||||
_child = value;
|
||||
|
||||
if (value != null)
|
||||
AddView(value.NativeView);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLayout(bool changed, int l, int t, int r, int b)
|
||||
{
|
||||
if (_child?.NativeView == null)
|
||||
return;
|
||||
|
||||
_child.NativeView.Layout(l, t, r, b);
|
||||
}
|
||||
|
||||
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
if (_child?.NativeView == null)
|
||||
{
|
||||
SetMeasuredDimension(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
_child.NativeView.Measure(widthMeasureSpec, heightMeasureSpec);
|
||||
SetMeasuredDimension(_child.NativeView.MeasuredWidth, _child.NativeView.MeasuredHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Handlers;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using WImage = Microsoft.UI.Xaml.Controls.Image;
|
||||
using NativeAutomationProperties = Microsoft.UI.Xaml.Automation.AutomationProperties;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Handlers
|
||||
{
|
||||
public partial class ToolbarHandler : ElementHandler<Toolbar, WindowHeader>
|
||||
{
|
||||
readonly ImageConverter _imageConverter = new ImageConverter();
|
||||
readonly ImageSourceIconElementConverter _imageSourceIconElementConverter = new ImageSourceIconElementConverter();
|
||||
|
||||
NavigationRootManager? NavigationRootManager =>
|
||||
MauiContext?.GetNavigationRootManager();
|
||||
|
||||
|
||||
protected override WindowHeader CreateNativeElement()
|
||||
{
|
||||
if(NavigationRootManager?.RootView is NavigationView nv &&
|
||||
nv.Header is WindowHeader windowHeader)
|
||||
{
|
||||
windowHeader.NavigationView = nv as MauiNavigationView;
|
||||
return windowHeader;
|
||||
}
|
||||
|
||||
return new WindowHeader()
|
||||
{
|
||||
NavigationView = NavigationRootManager?.RootView as MauiNavigationView
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
internal void UpdateMenu()
|
||||
{
|
||||
if (NavigationRootManager == null)
|
||||
return;
|
||||
|
||||
if (NavigationRootManager.RootView is not MauiNavigationView)
|
||||
return;
|
||||
|
||||
var commandBar = NavigationRootManager.GetCommandBar();
|
||||
|
||||
if (commandBar == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commandBar.PrimaryCommands.Clear();
|
||||
commandBar.SecondaryCommands.Clear();
|
||||
|
||||
List<ToolbarItem> toolbarItems = new List<ToolbarItem>(VirtualView.ToolbarItems ?? new ToolbarItem[0]);
|
||||
|
||||
foreach (ToolbarItem item in toolbarItems)
|
||||
{
|
||||
var button = new AppBarButton();
|
||||
button.SetBinding(AppBarButton.LabelProperty, "Text");
|
||||
|
||||
if (commandBar.IsDynamicOverflowEnabled && item.Order == ToolbarItemOrder.Secondary)
|
||||
{
|
||||
button.SetBinding(AppBarButton.IconProperty, "IconImageSource", _imageSourceIconElementConverter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var img = new WImage();
|
||||
img.SetBinding(WImage.SourceProperty, "Value");
|
||||
img.SetBinding(WImage.DataContextProperty, "IconImageSource", _imageConverter);
|
||||
button.Content = img;
|
||||
}
|
||||
|
||||
button.Command = new MenuItemCommand(item);
|
||||
button.DataContext = item;
|
||||
button.SetValue(NativeAutomationProperties.AutomationIdProperty, item.AutomationId);
|
||||
button.SetAutomationPropertiesName(item);
|
||||
button.SetAutomationPropertiesAccessibilityView(item);
|
||||
button.SetAutomationPropertiesHelpText(item);
|
||||
|
||||
button.SetAutomationPropertiesLabeledBy(item, null);
|
||||
|
||||
ToolbarItemOrder order = item.Order == ToolbarItemOrder.Default ? ToolbarItemOrder.Primary : item.Order;
|
||||
if (order == ToolbarItemOrder.Primary)
|
||||
{
|
||||
commandBar.PrimaryCommands.Add(button);
|
||||
}
|
||||
else
|
||||
{
|
||||
commandBar.SecondaryCommands.Add(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapToolbarPlacement(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
}
|
||||
|
||||
public static void MapToolbarDynamicOverflowEnabled(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateToolbarDynamicOverflowEnabled(arg2);
|
||||
}
|
||||
|
||||
public static void MapBarTextColor(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBarTextColor(arg2);
|
||||
}
|
||||
|
||||
public static void MapBarBackground(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBarBackground(arg2);
|
||||
}
|
||||
|
||||
public static void MapBarBackgroundColor(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBarBackgroundColor(arg2);
|
||||
}
|
||||
|
||||
public static void MapBackButtonTitle(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBackButton(arg2);
|
||||
}
|
||||
|
||||
public static void MapToolbarItems(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.UpdateMenu();
|
||||
}
|
||||
|
||||
public static void MapTitle(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateTitle(arg2);
|
||||
}
|
||||
|
||||
public static void MapIconColor(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateIconColor(arg2);
|
||||
}
|
||||
|
||||
public static void MapTitleView(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateTitleView(arg2);
|
||||
}
|
||||
|
||||
public static void MapTitleIcon(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateTitleIcon(arg2);
|
||||
}
|
||||
|
||||
public static void MapBackButtonVisible(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateBackButton(arg2);
|
||||
}
|
||||
|
||||
public static void MapIsVisible(ToolbarHandler arg1, Toolbar arg2)
|
||||
{
|
||||
arg1.NativeView.UpdateIsVisible(arg2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Handlers
|
||||
{
|
||||
#if ANDROID || WINDOWS
|
||||
public partial class ToolbarHandler
|
||||
{
|
||||
public static IPropertyMapper<Toolbar, ToolbarHandler> Mapper =
|
||||
new PropertyMapper<Toolbar, ToolbarHandler>(ElementMapper)
|
||||
{
|
||||
[nameof(Toolbar.IsVisible)] = MapIsVisible,
|
||||
[nameof(Toolbar.BackButtonVisible)] = MapBackButtonVisible,
|
||||
[nameof(Toolbar.TitleIcon)] = MapTitleIcon,
|
||||
[nameof(Toolbar.TitleView)] = MapTitleView,
|
||||
[nameof(Toolbar.IconColor)] = MapIconColor,
|
||||
[nameof(Toolbar.Title)] = MapTitle,
|
||||
[nameof(Toolbar.ToolbarItems)] = MapToolbarItems,
|
||||
[nameof(Toolbar.BackButtonTitle)] = MapBackButtonTitle,
|
||||
[nameof(Toolbar.BarBackgroundColor)] = MapBarBackgroundColor,
|
||||
[nameof(Toolbar.BarBackground)] = MapBarBackground,
|
||||
[nameof(Toolbar.BarTextColor)] = MapBarTextColor,
|
||||
[nameof(Toolbar.IconColor)] = MapIconColor,
|
||||
#if WINDOWS
|
||||
[PlatformConfiguration.WindowsSpecific.Page.ToolbarPlacementProperty.PropertyName] = MapToolbarPlacement,
|
||||
[PlatformConfiguration.WindowsSpecific.Page.ToolbarDynamicOverflowEnabledProperty.PropertyName] = MapToolbarDynamicOverflowEnabled,
|
||||
#endif
|
||||
};
|
||||
|
||||
public static CommandMapper<Toolbar, ToolbarHandler> CommandMapper = new()
|
||||
{
|
||||
};
|
||||
|
||||
public ToolbarHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -51,11 +51,12 @@ namespace Microsoft.Maui.Controls.Hosting
|
|||
{ typeof(RefreshView), typeof(RefreshViewHandler) },
|
||||
|
||||
#endif
|
||||
#if WINDOWS
|
||||
{ typeof(NavigationPage), typeof(NavigationPageHandler) },
|
||||
#if WINDOWS || ANDROID
|
||||
{ typeof(NavigationPage), typeof(NavigationViewHandler) },
|
||||
{ typeof(Toolbar), typeof(Controls.Handlers.ToolbarHandler) },
|
||||
#endif
|
||||
#if __ANDROID__
|
||||
//{ typeof(TabbedPage), typeof(Controls.Handlers.TabbedPageHandler) },
|
||||
{ typeof(TabbedPage), typeof(Controls.Handlers.TabbedPageHandler) },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -79,13 +79,19 @@ namespace Microsoft.Maui.Controls
|
|||
var previousPage = _current;
|
||||
OnPropertyChanging();
|
||||
|
||||
// TODO MAUI refine this to fire earlier
|
||||
// TODO: MAUI refine this to fire earlier
|
||||
_current?.SendNavigatingFrom(new NavigatingFromEventArgs());
|
||||
|
||||
_current = value;
|
||||
|
||||
previousPage?.SendDisappearing();
|
||||
|
||||
OnPropertyChanged();
|
||||
OnCurrentPageChanged();
|
||||
|
||||
if (HasAppeared)
|
||||
_current?.SendAppearing();
|
||||
|
||||
previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(_current));
|
||||
_current?.SendNavigatedTo(new NavigatedToEventArgs(previousPage));
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace Microsoft.Maui.Controls
|
|||
|
||||
public static readonly BindableProperty TitleViewProperty = BindableProperty.CreateAttached("TitleView", typeof(View), typeof(NavigationPage), null, propertyChanging: TitleViewPropertyChanging);
|
||||
|
||||
static readonly BindablePropertyKey CurrentPagePropertyKey = BindableProperty.CreateReadOnly("CurrentPage", typeof(Page), typeof(NavigationPage), null, propertyChanged: CurrentPagePropertyChanged);
|
||||
static readonly BindablePropertyKey CurrentPagePropertyKey = BindableProperty.CreateReadOnly("CurrentPage", typeof(Page), typeof(NavigationPage), null, propertyChanged: OnCurrentPageChanged);
|
||||
|
||||
public static readonly BindableProperty CurrentPageProperty = CurrentPagePropertyKey.BindableProperty;
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace Microsoft.Maui.Controls
|
|||
{
|
||||
_platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<NavigationPage>>(() => new PlatformConfigurationRegistry<NavigationPage>(this));
|
||||
|
||||
#if WINDOWS
|
||||
#if WINDOWS || __ANDROID__
|
||||
Navigation = new MauiNavigationImpl(this);
|
||||
#else
|
||||
Navigation = new NavigationImpl(this);
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace Microsoft.Maui.Controls.Internals
|
|||
|
||||
public Task PushModalAsync(Page modal, bool animated)
|
||||
{
|
||||
if (modal.RealParent != null)
|
||||
if (modal.RealParent != null && modal.RealParent is not IWindow)
|
||||
throw new InvalidOperationException("Page must not already have a parent.");
|
||||
return OnPushModal(modal, animated);
|
||||
}
|
||||
|
|
|
@ -412,6 +412,14 @@ namespace Microsoft.Maui.Controls
|
|||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void SendAppearing()
|
||||
{
|
||||
// Only fire appearing if the page has been added to the windows
|
||||
// Visual Hierarchy
|
||||
var window = this.FindParentOfType<Window>();
|
||||
if (window == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hasAppeared)
|
||||
return;
|
||||
|
||||
|
|
|
@ -1,634 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Android.Animation;
|
||||
using Android.Content;
|
||||
using Android.Content.Res;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using AndroidX.AppCompat.Graphics.Drawable;
|
||||
using AndroidX.CoordinatorLayout.Widget;
|
||||
using AndroidX.DrawerLayout.Widget;
|
||||
using AndroidX.Fragment.App;
|
||||
using AndroidX.Navigation;
|
||||
using Google.Android.Material.AppBar;
|
||||
using Google.Android.Material.Tabs;
|
||||
using Microsoft.Maui.Controls.Handlers;
|
||||
using static Android.Views.View;
|
||||
using static Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage;
|
||||
using ActionBarDrawerToggle = AndroidX.AppCompat.App.ActionBarDrawerToggle;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
using AView = Android.Views.View;
|
||||
using Color = Microsoft.Maui.Graphics.Color;
|
||||
using FragmentManager = AndroidX.Fragment.App.FragmentManager;
|
||||
using Object = Java.Lang.Object;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
// This class is still a bit too over complicated
|
||||
// As we move things into Core we'll better split it apart
|
||||
public class ControlsNavigationManager : NavigationManager, IManageFragments
|
||||
{
|
||||
|
||||
AppBarLayout _appBar;
|
||||
Fragment _tabLayoutFragment;
|
||||
internal AppBarLayout AppBar =>
|
||||
_appBar ??= NavigationLayout.FindViewById<AppBarLayout>(Resource.Id.appbar)
|
||||
?? throw new InvalidOperationException($"AppBar cannot be null");
|
||||
|
||||
ActionBarDrawerToggle _drawerToggle;
|
||||
FragmentManager _fragmentManager;
|
||||
ToolbarTracker ToolbarTracker;
|
||||
DrawerMultiplexedListener _drawerListener;
|
||||
DrawerLayout _drawerLayout;
|
||||
FlyoutPage _flyoutPage;
|
||||
IViewHandler _titleViewHandler;
|
||||
Container _titleView;
|
||||
Android.Widget.ImageView _titleIconView;
|
||||
ImageSource _imageSource;
|
||||
List<IMenuItem> _currentMenuItems = new List<IMenuItem>();
|
||||
List<ToolbarItem> _currentToolbarItems = new List<ToolbarItem>();
|
||||
|
||||
new NavigationPage NavigationView => (NavigationPage)base.VirtualView;
|
||||
|
||||
new Page CurrentPage => (Page)base.CurrentPage;
|
||||
public ControlsNavigationManager(IMauiContext mauiContext) : base(mauiContext)
|
||||
{
|
||||
}
|
||||
|
||||
INavigationPageController NavigationPageController => NavigationView as INavigationPageController;
|
||||
|
||||
IPageController PageController => NavigationView;
|
||||
|
||||
|
||||
void IManageFragments.SetFragmentManager(FragmentManager childFragmentManager)
|
||||
{
|
||||
if (_fragmentManager == null)
|
||||
_fragmentManager = childFragmentManager;
|
||||
}
|
||||
|
||||
public override void Connect(IView navigationView, NavigationLayout nativeView)
|
||||
{
|
||||
base.Connect(navigationView, nativeView);
|
||||
|
||||
if (ToolbarTracker == null)
|
||||
{
|
||||
ToolbarTracker = new ToolbarTracker();
|
||||
ToolbarTracker.CollectionChanged += ToolbarTrackerOnCollectionChanged;
|
||||
}
|
||||
|
||||
ToolbarTracker.AdditionalTargets = NavigationView.GetParentPages();
|
||||
}
|
||||
|
||||
// These are only relevant when nested inside a drawer layout
|
||||
void AnimateArrowIn()
|
||||
{
|
||||
var icon = Toolbar.NavigationIcon as DrawerArrowDrawable;
|
||||
if (icon == null)
|
||||
return;
|
||||
|
||||
ValueAnimator valueAnim = ValueAnimator.OfFloat(0, 1);
|
||||
valueAnim.SetDuration(200);
|
||||
valueAnim.Update += (s, a) => icon.Progress = (float)a.Animation.AnimatedValue;
|
||||
valueAnim.Start();
|
||||
}
|
||||
|
||||
void AnimateArrowOut()
|
||||
{
|
||||
var icon = Toolbar.NavigationIcon as DrawerArrowDrawable;
|
||||
if (icon == null)
|
||||
return;
|
||||
|
||||
ValueAnimator valueAnim = ValueAnimator.OfFloat(1, 0);
|
||||
valueAnim.SetDuration(200);
|
||||
valueAnim.Update += (s, a) => icon.Progress = (float)a.Animation.AnimatedValue;
|
||||
valueAnim.Start();
|
||||
}
|
||||
|
||||
public void OnClick(AView v)
|
||||
{
|
||||
NavigationView?.PopAsync();
|
||||
}
|
||||
|
||||
public override void RequestNavigation(NavigationRequest e)
|
||||
{
|
||||
NavAnimationInProgress = true;
|
||||
base.RequestNavigation(e);
|
||||
NavAnimationInProgress = false;
|
||||
|
||||
var currentStack = NavigationStack;
|
||||
var newStackSize = e.NavigationStack.Count;
|
||||
|
||||
bool animated = e.Animated;
|
||||
bool removed = currentStack.Count > newStackSize;
|
||||
|
||||
if (animated)
|
||||
{
|
||||
var page = (Page)e.NavigationStack[newStackSize - 1];
|
||||
if (!removed)
|
||||
{
|
||||
UpdateToolbar();
|
||||
if (_drawerToggle != null && NavigationPageController.StackDepth == 2 &&
|
||||
NavigationPage.GetHasBackButton(page))
|
||||
AnimateArrowIn();
|
||||
}
|
||||
else if (_drawerToggle != null && NavigationPageController.StackDepth == 2 &&
|
||||
NavigationPage.GetHasBackButton(page))
|
||||
{
|
||||
AnimateArrowOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetTabLayout(TabbedPageHandler tabbedPageHandler)
|
||||
{
|
||||
if (tabbedPageHandler == null)
|
||||
{
|
||||
if (_tabLayoutFragment != null)
|
||||
{
|
||||
MauiContext
|
||||
.GetFragmentManager()
|
||||
.BeginTransaction()
|
||||
.Remove(_tabLayoutFragment)
|
||||
.SetReorderingAllowed(true)
|
||||
.Commit();
|
||||
|
||||
_tabLayoutFragment = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int id;
|
||||
if (tabbedPageHandler.BottomNavigationView != null)
|
||||
{
|
||||
id = Resource.Id.bottomtab_containerview;
|
||||
_tabLayoutFragment = new ViewFragment(tabbedPageHandler.BottomNavigationView);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tabLayoutFragment = new ViewFragment(tabbedPageHandler.TabLayout);
|
||||
id = Resource.Id.toptabs_containerview;
|
||||
}
|
||||
|
||||
MauiContext
|
||||
.GetFragmentManager()
|
||||
.BeginTransaction()
|
||||
.Replace(id, _tabLayoutFragment)
|
||||
.SetReorderingAllowed(true)
|
||||
.Commit();
|
||||
}
|
||||
|
||||
protected override void OnNavigationViewFragmentResumed(FragmentManager fm, NavigationViewFragment navHostPageFragment)
|
||||
{
|
||||
base.OnNavigationViewFragmentResumed(fm, navHostPageFragment);
|
||||
// This appears to be the best place to update the toolbar so that the tinting works
|
||||
// Any early and the tinting will be replaced by the native tinting
|
||||
UpdateToolbar();
|
||||
}
|
||||
|
||||
protected override void OnDestinationChanged(NavController navController, NavDestination navDestination, Bundle bundle)
|
||||
{
|
||||
base.OnDestinationChanged(navController, navDestination, bundle);
|
||||
|
||||
if (ToolbarTracker != null)
|
||||
{
|
||||
ToolbarTracker.Target = CurrentPage;
|
||||
}
|
||||
|
||||
// Check if the current Visible View has a Set of Tabs it would like to display
|
||||
if (CurrentPage.Handler == null)
|
||||
{
|
||||
CurrentPage.HandlerChanged += OnHandlerChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateTablayout();
|
||||
}
|
||||
|
||||
void OnHandlerChanged(object sender, EventArgs __)
|
||||
{
|
||||
UpdateTablayout();
|
||||
((Element)sender).HandlerChanged -= OnHandlerChanged;
|
||||
}
|
||||
|
||||
void UpdateTablayout()
|
||||
{
|
||||
if (CurrentPage.Handler is TabbedPageHandler tph)
|
||||
{
|
||||
SetTabLayout(tph);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTabLayout(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterToolbar()
|
||||
{
|
||||
Context context = NavigationLayout.Context;
|
||||
AToolbar bar = Toolbar;
|
||||
Element page = NavigationView.RealParent;
|
||||
|
||||
_flyoutPage = null;
|
||||
while (page != null)
|
||||
{
|
||||
if (page is FlyoutPage)
|
||||
{
|
||||
_flyoutPage = page as FlyoutPage;
|
||||
break;
|
||||
}
|
||||
page = page.RealParent;
|
||||
}
|
||||
|
||||
if (_flyoutPage == null)
|
||||
{
|
||||
if (PageController.InternalChildren.Count > 0)
|
||||
_flyoutPage = PageController.InternalChildren[0] as FlyoutPage;
|
||||
|
||||
if (_flyoutPage == null)
|
||||
return;
|
||||
}
|
||||
|
||||
if (((IFlyoutPageController)_flyoutPage).ShouldShowSplitMode)
|
||||
return;
|
||||
|
||||
var renderer = _flyoutPage.ToNative(NavigationView.Handler.MauiContext) as DrawerLayout;
|
||||
if (renderer == null)
|
||||
return;
|
||||
|
||||
_drawerLayout = renderer;
|
||||
|
||||
AutomationPropertiesProvider.GetDrawerAccessibilityResources(context, _flyoutPage, out int resourceIdOpen, out int resourceIdClose);
|
||||
|
||||
if (_drawerToggle != null)
|
||||
{
|
||||
_drawerToggle.ToolbarNavigationClickListener = null;
|
||||
_drawerToggle.Dispose();
|
||||
}
|
||||
|
||||
_drawerToggle = new ActionBarDrawerToggle(context.GetActivity(), _drawerLayout, bar,
|
||||
resourceIdOpen == 0 ? global::Android.Resource.String.Ok : resourceIdOpen,
|
||||
resourceIdClose == 0 ? global::Android.Resource.String.Ok : resourceIdClose)
|
||||
{
|
||||
ToolbarNavigationClickListener = new ClickListener(NavigationView)
|
||||
};
|
||||
|
||||
if (_drawerListener != null)
|
||||
{
|
||||
_drawerLayout.RemoveDrawerListener(_drawerListener);
|
||||
_drawerListener.Dispose();
|
||||
}
|
||||
|
||||
_drawerListener = new DrawerMultiplexedListener { Listeners = { _drawerToggle, (DrawerLayout.IDrawerListener)_drawerLayout } };
|
||||
_drawerLayout.AddDrawerListener(_drawerListener);
|
||||
}
|
||||
|
||||
|
||||
// AFAICT this is specific to ListView and Context Items
|
||||
bool _navAnimationInProgress;
|
||||
internal const string CloseContextActionsSignalName = "Xamarin.CloseContextActions";
|
||||
internal bool NavAnimationInProgress
|
||||
{
|
||||
get { return _navAnimationInProgress; }
|
||||
set
|
||||
{
|
||||
if (_navAnimationInProgress == value)
|
||||
return;
|
||||
_navAnimationInProgress = value;
|
||||
if (value)
|
||||
MessagingCenter.Send(this, CloseContextActionsSignalName);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolbarTrackerOnCollectionChanged(object sender, EventArgs eventArgs)
|
||||
{
|
||||
UpdateMenu();
|
||||
}
|
||||
|
||||
void UpdateMenu()
|
||||
{
|
||||
if (_currentMenuItems == null)
|
||||
return;
|
||||
|
||||
Toolbar.UpdateMenuItems(ToolbarTracker?.ToolbarItems, NavigationView.FindMauiContext(), null, OnToolbarItemPropertyChanged, _currentMenuItems, _currentToolbarItems, UpdateMenuItemIcon);
|
||||
}
|
||||
|
||||
protected virtual void OnToolbarItemPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
var toolbarItems = ToolbarTracker?.ToolbarItems;
|
||||
List<ToolbarItem> newToolBarItems = new List<ToolbarItem>();
|
||||
if (toolbarItems != null)
|
||||
newToolBarItems.AddRange(toolbarItems);
|
||||
|
||||
Toolbar.OnToolbarItemPropertyChanged(e, (ToolbarItem)sender, newToolBarItems, NavigationView.FindMauiContext(), null, OnToolbarItemPropertyChanged, _currentMenuItems, _currentToolbarItems, UpdateMenuItemIcon);
|
||||
}
|
||||
|
||||
protected virtual void UpdateMenuItemIcon(Context context, IMenuItem menuItem, ToolbarItem toolBarItem)
|
||||
{
|
||||
ToolbarExtensions.UpdateMenuItemIcon(NavigationView.FindMauiContext(), menuItem, toolBarItem, null);
|
||||
}
|
||||
|
||||
|
||||
void UpdateToolbarVisibility()
|
||||
{
|
||||
bool showNavBar = NavigationPage.GetHasNavigationBar(CurrentPage);
|
||||
var lp = Toolbar.LayoutParameters;
|
||||
if (lp == null)
|
||||
return;
|
||||
|
||||
if (!showNavBar)
|
||||
{
|
||||
lp.Height = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NavigationView.IsSet(BarHeightProperty))
|
||||
lp.Height = NavigationView.OnThisPlatform().GetBarHeight();
|
||||
else
|
||||
lp.Height = ActionBarHeight();
|
||||
}
|
||||
|
||||
Toolbar.LayoutParameters = lp;
|
||||
|
||||
int ActionBarHeight()
|
||||
{
|
||||
int actionBarHeight = (int)NavigationLayout.Context.GetThemeAttributePixels(Resource.Attribute.actionBarSize);
|
||||
return actionBarHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Drawable _defaultNavigationIcon;
|
||||
|
||||
internal void ToolbarPropertyChanged() => UpdateToolbar();
|
||||
|
||||
protected virtual void UpdateToolbar()
|
||||
{
|
||||
ActionBarDrawerToggle toggle = _drawerToggle;
|
||||
|
||||
if (Toolbar == null || NavigationStack.Count == 0 || CurrentPage == null || VirtualView == null)
|
||||
return;
|
||||
|
||||
bool isNavigated = NavigationStack.Count > 1;
|
||||
Page currentPage = CurrentPage;
|
||||
|
||||
_defaultNavigationIcon ??= Toolbar.NavigationIcon;
|
||||
|
||||
if (isNavigated)
|
||||
{
|
||||
if (NavigationPage.GetHasBackButton(currentPage))
|
||||
{
|
||||
Toolbar.NavigationIcon ??= _defaultNavigationIcon;
|
||||
if (toggle != null)
|
||||
{
|
||||
toggle.DrawerIndicatorEnabled = false;
|
||||
toggle.SyncState();
|
||||
}
|
||||
|
||||
var prevPage = (Page)NavigationStack[NavigationStack.Count - 2];
|
||||
var backButtonTitle = NavigationPage.GetBackButtonTitle(prevPage);
|
||||
|
||||
ImageSource image = NavigationPage.GetTitleIconImageSource(currentPage);
|
||||
if (!string.IsNullOrEmpty(backButtonTitle))
|
||||
{
|
||||
Toolbar.NavigationContentDescription = backButtonTitle;
|
||||
}
|
||||
else if (image == null ||
|
||||
Toolbar.SetNavigationContentDescription(image) == null)
|
||||
{
|
||||
Toolbar.SetNavigationContentDescription(Resource.String.nav_app_bar_navigate_up_description);
|
||||
}
|
||||
}
|
||||
else if (toggle != null && _flyoutPage != null)
|
||||
{
|
||||
toggle.DrawerIndicatorEnabled = _flyoutPage.ShouldShowToolbarButton();
|
||||
toggle.SyncState();
|
||||
}
|
||||
else
|
||||
{
|
||||
Toolbar.NavigationIcon = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (toggle != null && _flyoutPage != null)
|
||||
{
|
||||
toggle.DrawerIndicatorEnabled = _flyoutPage.ShouldShowToolbarButton();
|
||||
toggle.SyncState();
|
||||
Toolbar.SetNavigationContentDescription(Resource.String.nav_app_bar_open_drawer_description);
|
||||
}
|
||||
}
|
||||
|
||||
Color tintColor = NavigationView.BarBackgroundColor;
|
||||
|
||||
if (tintColor == null)
|
||||
Toolbar.BackgroundTintMode = null;
|
||||
else
|
||||
{
|
||||
Toolbar.BackgroundTintMode = PorterDuff.Mode.Src;
|
||||
Toolbar.BackgroundTintList = ColorStateList.ValueOf(tintColor.ToNative());
|
||||
}
|
||||
|
||||
Brush barBackground = NavigationView.BarBackground;
|
||||
Toolbar.UpdateBackground(barBackground);
|
||||
|
||||
Color textColor = NavigationView.BarTextColor;
|
||||
if (textColor != null)
|
||||
Toolbar.SetTitleTextColor(textColor.ToNative().ToArgb());
|
||||
|
||||
Color navIconColor = NavigationPage.GetIconColor(CurrentPage);
|
||||
if (navIconColor != null && Toolbar.NavigationIcon != null)
|
||||
DrawableExtensions.SetColorFilter(Toolbar.NavigationIcon, navIconColor, FilterMode.SrcAtop);
|
||||
|
||||
Toolbar.Title = currentPage?.Title ?? string.Empty;
|
||||
|
||||
if (Toolbar.NavigationIcon != null && textColor != null)
|
||||
{
|
||||
var icon = this.Toolbar.NavigationIcon as DrawerArrowDrawable;
|
||||
if (icon != null)
|
||||
icon.Color = textColor.ToNative().ToArgb();
|
||||
}
|
||||
|
||||
UpdateTitleIcon();
|
||||
UpdateTitleView();
|
||||
UpdateToolbarVisibility();
|
||||
}
|
||||
|
||||
void UpdateTitleIcon()
|
||||
{
|
||||
Page currentPage = CurrentPage;
|
||||
|
||||
if (currentPage == null)
|
||||
return;
|
||||
|
||||
ImageSource source = NavigationPage.GetTitleIconImageSource(currentPage);
|
||||
|
||||
if (source == null || source.IsEmpty)
|
||||
{
|
||||
Toolbar.RemoveView(_titleIconView);
|
||||
_titleIconView?.Dispose();
|
||||
_titleIconView = null;
|
||||
_imageSource = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_titleIconView == null)
|
||||
{
|
||||
_titleIconView = new Android.Widget.ImageView(NavigationLayout.Context);
|
||||
Toolbar.AddView(_titleIconView, 0);
|
||||
}
|
||||
|
||||
if (_imageSource != source)
|
||||
{
|
||||
_imageSource = source;
|
||||
_titleIconView.SetImageResource(global::Android.Resource.Color.Transparent);
|
||||
|
||||
source.LoadImage(MauiContext, (result) =>
|
||||
{
|
||||
_titleIconView.SetImageDrawable(result?.Value);
|
||||
AutomationPropertiesProvider.AccessibilitySettingsChanged(_titleIconView, source);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateTitleView()
|
||||
{
|
||||
AToolbar bar = Toolbar;
|
||||
|
||||
if (bar == null)
|
||||
return;
|
||||
|
||||
Page currentPage = CurrentPage;
|
||||
|
||||
if (currentPage == null)
|
||||
return;
|
||||
|
||||
VisualElement titleView = NavigationPage.GetTitleView(currentPage);
|
||||
if (_titleViewHandler != null)
|
||||
{
|
||||
var reflectableType = _titleViewHandler as System.Reflection.IReflectableType;
|
||||
var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : _titleViewHandler.GetType();
|
||||
if (titleView == null || Internals.Registrar.Registered.GetHandlerTypeForObject(titleView) != rendererType)
|
||||
{
|
||||
if (_titleView != null)
|
||||
_titleView.Child = null;
|
||||
|
||||
_titleViewHandler.VirtualView.Handler = null;
|
||||
_titleViewHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (titleView == null)
|
||||
return;
|
||||
|
||||
if (_titleViewHandler != null)
|
||||
_titleViewHandler.SetVirtualView(titleView);
|
||||
else
|
||||
{
|
||||
titleView.ToNative(MauiContext);
|
||||
_titleViewHandler = titleView.Handler;
|
||||
|
||||
if (_titleView == null)
|
||||
{
|
||||
_titleView = new Container(NavigationLayout.Context);
|
||||
bar.AddView(_titleView);
|
||||
}
|
||||
|
||||
_titleView.Child = (INativeViewHandler)_titleViewHandler;
|
||||
}
|
||||
}
|
||||
|
||||
class ClickListener : Object, IOnClickListener
|
||||
{
|
||||
readonly NavigationPage _element;
|
||||
|
||||
public ClickListener(NavigationPage element)
|
||||
{
|
||||
_element = element;
|
||||
}
|
||||
|
||||
public void OnClick(AView v)
|
||||
{
|
||||
_element?.PopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
internal class Container : ViewGroup
|
||||
{
|
||||
INativeViewHandler _child;
|
||||
|
||||
public Container(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public INativeViewHandler Child
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_child != null)
|
||||
RemoveView(_child.NativeView);
|
||||
|
||||
_child = value;
|
||||
|
||||
if (value != null)
|
||||
AddView(value.NativeView);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLayout(bool changed, int l, int t, int r, int b)
|
||||
{
|
||||
if (_child == null)
|
||||
return;
|
||||
|
||||
_child.NativeView.Layout(l, t, r, b);
|
||||
}
|
||||
|
||||
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
if (_child == null)
|
||||
{
|
||||
SetMeasuredDimension(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
_child.NativeView.Measure(widthMeasureSpec, heightMeasureSpec);
|
||||
SetMeasuredDimension(_child.NativeView.MeasuredWidth, _child.NativeView.MeasuredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
class DrawerMultiplexedListener : Object, DrawerLayout.IDrawerListener
|
||||
{
|
||||
public List<DrawerLayout.IDrawerListener> Listeners { get; } = new List<DrawerLayout.IDrawerListener>(2);
|
||||
|
||||
public void OnDrawerClosed(AView drawerView)
|
||||
{
|
||||
foreach (DrawerLayout.IDrawerListener listener in Listeners)
|
||||
listener.OnDrawerClosed(drawerView);
|
||||
}
|
||||
|
||||
public void OnDrawerOpened(AView drawerView)
|
||||
{
|
||||
foreach (DrawerLayout.IDrawerListener listener in Listeners)
|
||||
listener.OnDrawerOpened(drawerView);
|
||||
}
|
||||
|
||||
public void OnDrawerSlide(AView drawerView, float slideOffset)
|
||||
{
|
||||
foreach (DrawerLayout.IDrawerListener listener in Listeners)
|
||||
listener.OnDrawerSlide(drawerView, slideOffset);
|
||||
}
|
||||
|
||||
public void OnDrawerStateChanged(int newState)
|
||||
{
|
||||
foreach (DrawerLayout.IDrawerListener listener in Listeners)
|
||||
listener.OnDrawerStateChanged(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,10 +3,15 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Android.Content;
|
||||
using Android.Content.Res;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
#nullable enable
|
||||
using Android.Text;
|
||||
using Android.Text.Style;
|
||||
using Android.Views;
|
||||
using AndroidX.AppCompat.Graphics.Drawable;
|
||||
using AndroidX.AppCompat.Widget;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using ATextView = global::Android.Widget.TextView;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
@ -17,6 +22,151 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
{
|
||||
internal static class ToolbarExtensions
|
||||
{
|
||||
static Drawable? _defaultNavigationIcon;
|
||||
|
||||
public static void UpdateIsVisible(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
_ = nativeToolbar.Context ?? throw new ArgumentNullException(nameof(nativeToolbar.Context));
|
||||
|
||||
bool showNavBar = toolbar.IsVisible;
|
||||
var lp = nativeToolbar.LayoutParameters;
|
||||
if (lp == null)
|
||||
return;
|
||||
|
||||
if (!showNavBar)
|
||||
{
|
||||
lp.Height = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (toolbar.BarHeight != null)
|
||||
lp.Height = (int)nativeToolbar.Context.ToPixels(toolbar.BarHeight.Value);
|
||||
else
|
||||
lp.Height = ActionBarHeight();
|
||||
}
|
||||
|
||||
nativeToolbar.LayoutParameters = lp;
|
||||
|
||||
int ActionBarHeight()
|
||||
{
|
||||
int actionBarHeight = (int)nativeToolbar.Context.GetThemeAttributePixels(Resource.Attribute.actionBarSize);
|
||||
return actionBarHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateTitleIcon(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
_ = nativeToolbar.Context ?? throw new ArgumentNullException(nameof(nativeToolbar.Context));
|
||||
_ = toolbar?.Handler?.MauiContext ?? throw new ArgumentNullException(nameof(toolbar.Handler.MauiContext));
|
||||
|
||||
ImageSource source = toolbar.TitleIcon;
|
||||
|
||||
if (source == null || source.IsEmpty)
|
||||
{
|
||||
if (nativeToolbar.GetChildAt(0) is ToolbarTitleIconImageView existingImageView)
|
||||
nativeToolbar.RemoveView(existingImageView);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var iconView = new ToolbarTitleIconImageView(nativeToolbar.Context);
|
||||
nativeToolbar.AddView(iconView, 0);
|
||||
iconView.SetImageResource(global::Android.Resource.Color.Transparent);
|
||||
|
||||
source.LoadImage(toolbar.Handler.MauiContext, (result) =>
|
||||
{
|
||||
iconView.SetImageDrawable(result?.Value);
|
||||
AutomationPropertiesProvider.AccessibilitySettingsChanged(iconView, source);
|
||||
});
|
||||
}
|
||||
|
||||
public static void UpdateBackButton(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
bool isNavigated = toolbar.HasBackStack;
|
||||
|
||||
_defaultNavigationIcon ??= nativeToolbar.NavigationIcon;
|
||||
|
||||
if (isNavigated)
|
||||
{
|
||||
if (toolbar.BackButtonVisible)
|
||||
{
|
||||
nativeToolbar.NavigationIcon ??= _defaultNavigationIcon;
|
||||
|
||||
var backButtonTitle = toolbar.BackButtonTitle;
|
||||
ImageSource image = toolbar.TitleIcon;
|
||||
|
||||
if (!string.IsNullOrEmpty(backButtonTitle))
|
||||
{
|
||||
nativeToolbar.NavigationContentDescription = backButtonTitle;
|
||||
}
|
||||
else if (image == null ||
|
||||
nativeToolbar.SetNavigationContentDescription(image) == null)
|
||||
{
|
||||
nativeToolbar.SetNavigationContentDescription(Resource.String.nav_app_bar_navigate_up_description);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nativeToolbar.NavigationIcon = null;
|
||||
}
|
||||
}
|
||||
|
||||
nativeToolbar.UpdateIconColor(toolbar);
|
||||
nativeToolbar.UpdateBarTextColor(toolbar);
|
||||
}
|
||||
|
||||
public static void UpdateBarBackgroundColor(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
var tintColor = toolbar.BarBackgroundColor;
|
||||
|
||||
if (tintColor == null)
|
||||
nativeToolbar.BackgroundTintMode = null;
|
||||
else
|
||||
{
|
||||
nativeToolbar.BackgroundTintMode = PorterDuff.Mode.Src;
|
||||
nativeToolbar.BackgroundTintList = ColorStateList.ValueOf(tintColor.ToNative());
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateBarBackground(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
Brush barBackground = toolbar.BarBackground;
|
||||
nativeToolbar.UpdateBackground(barBackground);
|
||||
}
|
||||
|
||||
public static void UpdateIconColor(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
var navIconColor = toolbar.IconColor;
|
||||
if (navIconColor != null && nativeToolbar.NavigationIcon != null)
|
||||
DrawableExtensions.SetColorFilter(nativeToolbar.NavigationIcon, navIconColor, FilterMode.SrcAtop);
|
||||
}
|
||||
|
||||
public static void UpdateTitle(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
nativeToolbar.Title = toolbar?.Title ?? string.Empty;
|
||||
}
|
||||
|
||||
public static void UpdateBarTextColor(this AToolbar nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
var textColor = toolbar.BarTextColor;
|
||||
if (textColor != null)
|
||||
nativeToolbar.SetTitleTextColor(textColor.ToNative().ToArgb());
|
||||
|
||||
if (nativeToolbar.NavigationIcon != null && textColor != null)
|
||||
{
|
||||
var icon = nativeToolbar.NavigationIcon as DrawerArrowDrawable;
|
||||
if (icon != null)
|
||||
icon.Color = textColor.ToNative().ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
class ToolbarTitleIconImageView : AppCompatImageView
|
||||
{
|
||||
public ToolbarTitleIconImageView(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
const int DefaultDisabledToolbarAlpha = 127;
|
||||
public static void DisposeMenuItems(this AToolbar toolbar, IEnumerable<ToolbarItem> toolbarItems, PropertyChangedEventHandler toolbarItemChanged)
|
||||
{
|
||||
|
@ -74,8 +224,11 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
List<ToolbarItem> previousToolBarItems,
|
||||
Action<Context, IMenuItem, ToolbarItem>? updateMenuItemIcon = null)
|
||||
{
|
||||
var context = mauiContext.Context!;
|
||||
var context = mauiContext.Context ??
|
||||
throw new ArgumentNullException($"{nameof(mauiContext.Context)}");
|
||||
|
||||
IMenu menu = toolbar.Menu;
|
||||
|
||||
item.PropertyChanged -= toolbarItemChanged;
|
||||
item.PropertyChanged += toolbarItemChanged;
|
||||
|
||||
|
@ -104,7 +257,8 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
|
||||
if (menuItemIndex == null || menuItemIndex >= previousMenuItems?.Count)
|
||||
{
|
||||
menuitem = menu.Add(0, AView.GenerateViewId(), 0, newTitle)!;
|
||||
menuitem = menu.Add(0, AView.GenerateViewId(), 0, newTitle) ??
|
||||
throw new InvalidOperationException($"Failed to create menuitem: {newTitle}");
|
||||
previousMenuItems?.Add(menuitem);
|
||||
}
|
||||
else
|
||||
|
@ -158,8 +312,8 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
|
||||
if (baseDrawable != null)
|
||||
{
|
||||
using (var constant = baseDrawable.GetConstantState()!)
|
||||
using (var newDrawable = constant.NewDrawable())
|
||||
using (var constant = baseDrawable.GetConstantState())
|
||||
using (var newDrawable = constant!.NewDrawable())
|
||||
using (var iconDrawable = newDrawable.Mutate())
|
||||
{
|
||||
if (tintColor != null)
|
||||
|
|
|
@ -14,10 +14,9 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
{
|
||||
readonly WeakReference _pageRenderer;
|
||||
readonly IMauiContext _mauiContext;
|
||||
Action<PageContainer> _onCreateCallback;
|
||||
PageContainer _pageContainer;
|
||||
Action<AView> _onCreateCallback;
|
||||
AView _pageContainer;
|
||||
INativeViewHandler _viewhandler;
|
||||
//bool _isVisible = false;
|
||||
AView NativeView => _viewhandler?.NativeView as AView;
|
||||
|
||||
public FragmentContainer(IMauiContext mauiContext)
|
||||
|
@ -33,31 +32,38 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
|
||||
public virtual Page Page => (Page)_pageRenderer?.Target;
|
||||
|
||||
IPageController PageController => Page as IPageController;
|
||||
|
||||
public static Fragment CreateInstance(Page page, IMauiContext mauiContext)
|
||||
public static FragmentContainer CreateInstance(Page page, IMauiContext mauiContext)
|
||||
{
|
||||
return new FragmentContainer(page, mauiContext) { Arguments = new Bundle() };
|
||||
}
|
||||
|
||||
public void SetOnCreateCallback(Action<PageContainer> callback)
|
||||
public void SetOnCreateCallback(Action<AView> callback)
|
||||
{
|
||||
_onCreateCallback = callback;
|
||||
}
|
||||
|
||||
protected virtual PageContainer CreatePageContainer(Context context, INativeViewHandler child, bool inFragment)
|
||||
{
|
||||
return new PageContainer(context, child, inFragment);
|
||||
}
|
||||
ViewGroup _parent;
|
||||
|
||||
public override AView OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
_parent = container ?? _parent;
|
||||
|
||||
if (Page != null)
|
||||
{
|
||||
Page.ToNative(_mauiContext);
|
||||
_viewhandler = (INativeViewHandler)Page.Handler;
|
||||
_pageContainer = Page?.Handler?.NativeView as AView;
|
||||
|
||||
_pageContainer = CreatePageContainer(inflater.Context, _viewhandler, true);
|
||||
if (_pageContainer == null)
|
||||
{
|
||||
var scopedContext =
|
||||
_mauiContext.MakeScoped(inflater, ChildFragmentManager);
|
||||
|
||||
_pageContainer = Page.ToNative(scopedContext);
|
||||
_viewhandler = (INativeViewHandler)Page.Handler;
|
||||
}
|
||||
else
|
||||
{
|
||||
_parent = _parent ?? (_pageContainer.Parent as ViewGroup);
|
||||
}
|
||||
|
||||
_onCreateCallback?.Invoke(_pageContainer);
|
||||
|
||||
|
@ -67,81 +73,22 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
return null;
|
||||
}
|
||||
|
||||
protected virtual void RecyclePage()
|
||||
public override void OnResume()
|
||||
{
|
||||
// Page.Handler = null;
|
||||
}
|
||||
if (_pageContainer == null)
|
||||
return;
|
||||
|
||||
public override void OnDestroyView()
|
||||
{
|
||||
if (Page != null)
|
||||
_parent = (_pageContainer.Parent as ViewGroup) ?? _parent;
|
||||
if (_pageContainer.Parent == null && _parent != null)
|
||||
{
|
||||
if (_viewhandler != null)
|
||||
{
|
||||
if (NativeView.IsAlive())
|
||||
{
|
||||
NativeView.RemoveFromParent();
|
||||
}
|
||||
|
||||
RecyclePage();
|
||||
}
|
||||
// Re-add the view to the container if Android removed it
|
||||
// Because we are re-using views inside OnCreateView Android
|
||||
// will remove the "previous" view from the parent but since our
|
||||
// "previous" view and "current" view are the same we have to re-add it
|
||||
_parent.AddView(_pageContainer);
|
||||
}
|
||||
|
||||
_onCreateCallback = null;
|
||||
_viewhandler = null;
|
||||
|
||||
base.OnDestroyView();
|
||||
base.OnResume();
|
||||
}
|
||||
|
||||
//public override void OnHiddenChanged(bool hidden)
|
||||
//{
|
||||
// base.OnHiddenChanged(hidden);
|
||||
|
||||
// if (Page == null)
|
||||
// return;
|
||||
|
||||
// if (hidden)
|
||||
// PageController?.SendDisappearing();
|
||||
// else
|
||||
// PageController?.SendAppearing();
|
||||
//}
|
||||
|
||||
// TODO MAUI
|
||||
//public override void OnPause()
|
||||
//{
|
||||
// _isVisible = false;
|
||||
|
||||
// bool shouldSendEvent = Application.Current.OnThisPlatform().GetSendDisappearingEventOnPause();
|
||||
// if (shouldSendEvent)
|
||||
// SendLifecycleEvent(false);
|
||||
|
||||
// base.OnPause();
|
||||
//}
|
||||
|
||||
//public override void OnResume()
|
||||
//{
|
||||
// _isVisible = true;
|
||||
|
||||
// bool shouldSendEvent = Application.Current.OnThisPlatform().GetSendAppearingEventOnResume();
|
||||
// if (shouldSendEvent)
|
||||
// SendLifecycleEvent(true);
|
||||
|
||||
// base.OnResume();
|
||||
//}
|
||||
|
||||
//void SendLifecycleEvent(bool isAppearing)
|
||||
//{
|
||||
// var flyoutPage = Application.Current.MainPage as FlyoutPage;
|
||||
// var pageContainer = (flyoutPage != null ? flyoutPage.Detail : Application.Current.MainPage) as IPageContainer<Page>;
|
||||
// Page currentPage = pageContainer?.CurrentPage;
|
||||
|
||||
// if (!(currentPage == null || currentPage == PageController))
|
||||
// return;
|
||||
|
||||
// if (isAppearing && _isVisible)
|
||||
// PageController?.SendAppearing();
|
||||
// else if (!isAppearing)
|
||||
// PageController?.SendDisappearing();
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -1,26 +1,20 @@
|
|||
using System.Collections.Generic;
|
||||
using AndroidX.AppCompat.App;
|
||||
using AndroidX.Fragment.App;
|
||||
using AndroidX.ViewPager2.Adapter;
|
||||
using FragmentTransit = Android.App.FragmentTransit;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
internal class MultiPageFragmentStateAdapter<T> : FragmentStateAdapter where T : Page
|
||||
{
|
||||
MultiPage<T> _page;
|
||||
FragmentManager _fragmentManager;
|
||||
readonly IMauiContext _context;
|
||||
List<Fragment> _fragments;
|
||||
|
||||
public MultiPageFragmentStateAdapter(
|
||||
MultiPage<T> page, FragmentManager fragmentManager, IMauiContext context)
|
||||
: base(fragmentManager, (context.GetActivity() as AppCompatActivity).Lifecycle)
|
||||
: base(fragmentManager, context.GetActivity().Lifecycle)
|
||||
{
|
||||
_page = page;
|
||||
_fragmentManager = fragmentManager;
|
||||
_context = context;
|
||||
_fragments = new List<Fragment>();
|
||||
}
|
||||
|
||||
public override int ItemCount => CountOverride;
|
||||
|
@ -30,9 +24,6 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
public override Fragment CreateFragment(int position)
|
||||
{
|
||||
var fragment = FragmentContainer.CreateInstance(_page.Children[position], _context);
|
||||
|
||||
_fragments.Add(fragment);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
using System;
|
||||
using Android.Content;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using AView = Android.Views.View;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
|
||||
// TODO Probably just get rid of this?
|
||||
internal class PageContainer : ViewGroup
|
||||
{
|
||||
public PageContainer(Context context, IViewHandler child, bool inFragment = false) : base(context)
|
||||
{
|
||||
Id = AView.GenerateViewId();
|
||||
Child = child;
|
||||
IsInFragment = inFragment;
|
||||
AddView((AView)child.NativeView);
|
||||
}
|
||||
|
||||
public IViewHandler Child { get; set; }
|
||||
|
||||
public bool IsInFragment { get; set; }
|
||||
|
||||
protected PageContainer(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnLayout(bool changed, int l, int t, int r, int b)
|
||||
{
|
||||
if (changed && Child.NativeView is AView aView)
|
||||
aView.Layout(l, t, r, b);
|
||||
}
|
||||
|
||||
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
if (Child.NativeView is AView aView)
|
||||
{
|
||||
aView.Measure(widthMeasureSpec, heightMeasureSpec);
|
||||
SetMeasuredDimension(aView.MeasuredWidth, aView.MeasuredHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -76,7 +76,10 @@ namespace Microsoft.Maui.Controls
|
|||
public static int bottomtab_tabbar = 2131230818;
|
||||
|
||||
// aapt resource value: 0x7F080063
|
||||
public static int bottomtab_containerview = 2131230819;
|
||||
public static int navigationlayout_bottomtabs = 2131230819;
|
||||
|
||||
// aapt resource value: 0x7F08013E
|
||||
public static int navigationlayout_content = 2131231038;
|
||||
|
||||
// aapt resource value: 0x7F0800C7
|
||||
public static int flyoutcontent_appbar = 2131230919;
|
||||
|
@ -97,7 +100,10 @@ namespace Microsoft.Maui.Controls
|
|||
public static int shellcontent_toolbar = 2131231101;
|
||||
|
||||
// aapt resource value: 0x7F0801CD
|
||||
public static int toptabs_containerview = 2131231181;
|
||||
public static int navigationlayout_toptabs = 2131231181;
|
||||
|
||||
// aapt resource value: 0x7F08013F
|
||||
public static int navigationlayout_toolbar = 2131231039;
|
||||
|
||||
static Id()
|
||||
{
|
||||
|
@ -110,6 +116,9 @@ namespace Microsoft.Maui.Controls
|
|||
// aapt resource value: 0x7F0B001C
|
||||
public static int bottomtablayout = 2131427356;
|
||||
|
||||
// aapt resource value: 0x7F0B002E
|
||||
public static int fragment_backstack = 2131427374;
|
||||
|
||||
// aapt resource value: 0x7F0B002F
|
||||
public static int flyoutcontent = 2131427375;
|
||||
|
||||
|
@ -125,6 +134,17 @@ namespace Microsoft.Maui.Controls
|
|||
}
|
||||
}
|
||||
|
||||
public partial class Dimension
|
||||
{
|
||||
// aapt resource value: 0x7F060067
|
||||
public static int design_bottom_navigation_height = 2131099751;
|
||||
|
||||
static Dimension()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class String
|
||||
{
|
||||
// aapt resource value: 0x7F0D0065
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Android.Content;
|
||||
using AndroidX.AppCompat.Widget;
|
||||
using AndroidX.DrawerLayout.Widget;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
|
@ -18,7 +19,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
|
||||
IShellSectionView CreateShellSectionView(ShellSection shellSection);
|
||||
|
||||
IShellToolbarTracker CreateTrackerForToolbar(Toolbar toolbar);
|
||||
IShellToolbarTracker CreateTrackerForToolbar(AToolbar toolbar);
|
||||
|
||||
IShellToolbarAppearanceTracker CreateToolbarAppearanceTracker();
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
using System;
|
||||
using AndroidX.AppCompat.Widget;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
public interface IShellToolbarAppearanceTracker : IDisposable
|
||||
{
|
||||
void SetAppearance(Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance);
|
||||
void ResetAppearance(Toolbar toolbar, IShellToolbarTracker toolbarTracker);
|
||||
void SetAppearance(AToolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance);
|
||||
void ResetAppearance(AToolbar toolbar, IShellToolbarTracker toolbarTracker);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ using Google.Android.Material.AppBar;
|
|||
using AndroidAnimation = Android.Views.Animations.Animation;
|
||||
using AnimationSet = Android.Views.Animations.AnimationSet;
|
||||
using AView = Android.Views.View;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
|
@ -66,7 +67,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
AView _root;
|
||||
ShellPageContainer _shellPageContainer;
|
||||
ShellContent _shellContent;
|
||||
Toolbar _toolbar;
|
||||
AToolbar _toolbar;
|
||||
IShellToolbarTracker _toolbarTracker;
|
||||
bool _disposed;
|
||||
IMauiContext MauiContext => _shellContext.Shell.Handler.MauiContext;
|
||||
|
@ -132,7 +133,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
|
||||
_root = inflater.Inflate(Resource.Layout.shellcontent, null).JavaCast<CoordinatorLayout>();
|
||||
|
||||
_toolbar = _root.FindViewById<Toolbar>(Resource.Id.shellcontent_toolbar);
|
||||
_toolbar = _root.FindViewById<AToolbar>(Resource.Id.shellcontent_toolbar);
|
||||
_page.ToNative(MauiContext);
|
||||
_viewhandler = (INativeViewHandler)_page.Handler;
|
||||
|
||||
|
|
|
@ -3,36 +3,31 @@ using Android.Content;
|
|||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using AndroidX.Fragment.App;
|
||||
using AView = Android.Views.View;
|
||||
using LP = Android.Views.ViewGroup.LayoutParams;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
internal class ShellFragmentContainer : FragmentContainer
|
||||
internal class ShellFragmentContainer : Fragment
|
||||
{
|
||||
Page _page;
|
||||
readonly IMauiContext _mauiContext;
|
||||
|
||||
public ShellContent ShellContentTab { get; private set; }
|
||||
|
||||
public ShellFragmentContainer(ShellContent shellContent, IMauiContext mauiContext) : base(mauiContext)
|
||||
public ShellFragmentContainer(ShellContent shellContent, IMauiContext mauiContext)
|
||||
{
|
||||
ShellContentTab = shellContent;
|
||||
}
|
||||
|
||||
public override Page Page => _page;
|
||||
|
||||
protected override PageContainer CreatePageContainer(Context context, INativeViewHandler child, bool inFragment)
|
||||
{
|
||||
return new ShellPageContainer(context, child, inFragment)
|
||||
{
|
||||
LayoutParameters = new LP(LP.MatchParent, LP.MatchParent)
|
||||
};
|
||||
_mauiContext = mauiContext;
|
||||
}
|
||||
|
||||
public override AView OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
_page = ((IShellContentController)ShellContentTab).GetOrCreateContent();
|
||||
return base.OnCreateView(inflater, container, savedInstanceState);
|
||||
var view = _page.ToNative(_mauiContext);
|
||||
view.LayoutParameters = new LP(LP.MatchParent, LP.MatchParent);
|
||||
return view;
|
||||
}
|
||||
|
||||
public override void OnDestroyView()
|
||||
|
@ -42,11 +37,6 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
_page = null;
|
||||
}
|
||||
|
||||
protected override void RecyclePage()
|
||||
{
|
||||
// Don't remove the handler inside shell we just keep it around
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(Dispose);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Android.Content;
|
||||
using Android.Views;
|
||||
using AndroidX.Core.Content;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using AColor = Android.Graphics.Color;
|
||||
|
@ -7,13 +8,20 @@ using AView = Android.Views.View;
|
|||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
internal class ShellPageContainer : PageContainer
|
||||
internal class ShellPageContainer : ViewGroup
|
||||
{
|
||||
static int? DarkBackground;
|
||||
static int? LightBackground;
|
||||
|
||||
public ShellPageContainer(Context context, INativeViewHandler child, bool inFragment = false) : base(context, child, inFragment)
|
||||
|
||||
public IViewHandler Child { get; set; }
|
||||
|
||||
public bool IsInFragment { get; set; }
|
||||
|
||||
public ShellPageContainer(Context context, INativeViewHandler child, bool inFragment = false) : base(context)
|
||||
{
|
||||
Child = child;
|
||||
IsInFragment = inFragment;
|
||||
if (child.VirtualView.Background == null)
|
||||
{
|
||||
int color;
|
||||
|
@ -34,5 +42,14 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
if (Child.NativeView is AView aView)
|
||||
aView.Layout(0, 0, width, height);
|
||||
}
|
||||
|
||||
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
if (Child.NativeView is AView aView)
|
||||
{
|
||||
aView.Measure(widthMeasureSpec, heightMeasureSpec);
|
||||
SetMeasuredDimension(aView.MeasuredWidth, aView.MeasuredHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ using AndroidX.ViewPager.Widget;
|
|||
using AndroidX.ViewPager2.Widget;
|
||||
using Google.Android.Material.Tabs;
|
||||
using AView = Android.Views.View;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
|
@ -104,7 +105,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
bool _selecting;
|
||||
TabLayout _tablayout;
|
||||
IShellTabLayoutAppearanceTracker _tabLayoutAppearanceTracker;
|
||||
Toolbar _toolbar;
|
||||
AToolbar _toolbar;
|
||||
IShellToolbarAppearanceTracker _toolbarAppearanceTracker;
|
||||
IShellToolbarTracker _toolbarTracker;
|
||||
ViewPager2 _viewPager;
|
||||
|
@ -134,7 +135,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
|
||||
var root = inflater.Inflate(Resource.Layout.shellrootlayout, null).JavaCast<CoordinatorLayout>();
|
||||
|
||||
_toolbar = root.FindViewById<Toolbar>(Resource.Id.maui_toolbar);
|
||||
_toolbar = root.FindViewById<AToolbar>(Resource.Id.maui_toolbar);
|
||||
if (Context.GetActivity() is AppCompatActivity aca)
|
||||
aca.SetSupportActionBar(_toolbar);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ using Android.Graphics.Drawables;
|
|||
using AndroidX.AppCompat.Widget;
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
|
@ -17,7 +18,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
_shellContext = shellContext;
|
||||
}
|
||||
|
||||
public virtual void SetAppearance(Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
|
||||
public virtual void SetAppearance(AToolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
|
||||
{
|
||||
var foreground = appearance.ForegroundColor;
|
||||
var background = appearance.BackgroundColor;
|
||||
|
@ -26,12 +27,12 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
SetColors(toolbar, toolbarTracker, foreground, background, titleColor);
|
||||
}
|
||||
|
||||
public virtual void ResetAppearance(Toolbar toolbar, IShellToolbarTracker toolbarTracker)
|
||||
public virtual void ResetAppearance(AToolbar toolbar, IShellToolbarTracker toolbarTracker)
|
||||
{
|
||||
SetColors(toolbar, toolbarTracker, ShellView.DefaultForegroundColor, ShellView.DefaultBackgroundColor, ShellView.DefaultTitleColor);
|
||||
}
|
||||
|
||||
protected virtual void SetColors(Toolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Color background, Color title)
|
||||
protected virtual void SetColors(AToolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Color background, Color title)
|
||||
{
|
||||
var titleArgb = title.ToNative(ShellView.DefaultTitleColor).ToArgb();
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ using Color = Microsoft.Maui.Graphics.Color;
|
|||
using LP = Android.Views.ViewGroup.LayoutParams;
|
||||
using Paint = Android.Graphics.Paint;
|
||||
using R = Android.Resource;
|
||||
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
protected IShellContext ShellContext { get; private set; }
|
||||
//assume the default
|
||||
Color _tintColor = null;
|
||||
Toolbar _toolbar;
|
||||
AToolbar _toolbar;
|
||||
AppBarLayout _appBar;
|
||||
float _appBarElevation;
|
||||
GenericGlobalLayoutListener _globalLayoutListener;
|
||||
|
@ -67,7 +67,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
List<ToolbarItem> _currentToolbarItems = new List<ToolbarItem>();
|
||||
protected IMauiContext MauiContext => ShellContext.Shell.Handler.MauiContext;
|
||||
|
||||
public ShellToolbarTracker(IShellContext shellContext, Toolbar toolbar, DrawerLayout drawerLayout)
|
||||
public ShellToolbarTracker(IShellContext shellContext, AToolbar toolbar, DrawerLayout drawerLayout)
|
||||
{
|
||||
ShellContext = shellContext ?? throw new ArgumentNullException(nameof(shellContext));
|
||||
_toolbar = toolbar ?? throw new ArgumentNullException(nameof(toolbar));
|
||||
|
@ -336,7 +336,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
return image;
|
||||
}
|
||||
|
||||
protected virtual async void UpdateLeftBarButtonItem(Context context, Toolbar toolbar, DrawerLayout drawerLayout, Page page)
|
||||
protected virtual async void UpdateLeftBarButtonItem(Context context, AToolbar toolbar, DrawerLayout drawerLayout, Page page)
|
||||
{
|
||||
if (_drawerToggle == null)
|
||||
{
|
||||
|
@ -438,12 +438,12 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
}
|
||||
|
||||
|
||||
protected virtual Task UpdateDrawerArrow(Context context, Toolbar toolbar, DrawerLayout drawerLayout)
|
||||
protected virtual Task UpdateDrawerArrow(Context context, AToolbar toolbar, DrawerLayout drawerLayout)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual void UpdateToolbarIconAccessibilityText(Toolbar toolbar, Shell shell)
|
||||
protected virtual void UpdateToolbarIconAccessibilityText(AToolbar toolbar, Shell shell)
|
||||
{
|
||||
var backButtonHandler = Shell.GetBackButtonBehavior(Page);
|
||||
var image = GetFlyoutIcon(backButtonHandler, Page);
|
||||
|
@ -465,7 +465,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual Task UpdateDrawerArrowFromBackButtonBehavior(Context context, Toolbar toolbar, DrawerLayout drawerLayout, BackButtonBehavior backButtonHandler)
|
||||
protected virtual Task UpdateDrawerArrowFromBackButtonBehavior(Context context, AToolbar toolbar, DrawerLayout drawerLayout, BackButtonBehavior backButtonHandler)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
@ -493,7 +493,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
});
|
||||
}
|
||||
|
||||
protected virtual void UpdateNavBarVisible(Toolbar toolbar, Page page)
|
||||
protected virtual void UpdateNavBarVisible(AToolbar toolbar, Page page)
|
||||
{
|
||||
var navBarVisible = Shell.GetNavBarIsVisible(page);
|
||||
toolbar.Visibility = navBarVisible ? ViewStates.Visible : ViewStates.Gone;
|
||||
|
@ -517,12 +517,12 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdatePageTitle(Toolbar toolbar, Page page)
|
||||
protected virtual void UpdatePageTitle(AToolbar toolbar, Page page)
|
||||
{
|
||||
_toolbar.Title = page.Title;
|
||||
}
|
||||
|
||||
protected virtual void UpdateTitleView(Context context, Toolbar toolbar, View titleView)
|
||||
protected virtual void UpdateTitleView(Context context, AToolbar toolbar, View titleView)
|
||||
{
|
||||
if (titleView == null)
|
||||
{
|
||||
|
@ -537,7 +537,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
{
|
||||
_titleViewContainer = new ShellContainerView(context, titleView, MauiContext);
|
||||
_titleViewContainer.MatchHeight = _titleViewContainer.MatchWidth = true;
|
||||
_titleViewContainer.LayoutParameters = new Toolbar.LayoutParams(LP.MatchParent, LP.MatchParent)
|
||||
_titleViewContainer.LayoutParameters = new AToolbar.LayoutParams(LP.MatchParent, LP.MatchParent)
|
||||
{
|
||||
LeftMargin = (int)context.ToPixels(titleView.Margin.Left),
|
||||
TopMargin = (int)context.ToPixels(titleView.Margin.Top),
|
||||
|
@ -553,7 +553,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateToolbarItems(Toolbar toolbar, Page page)
|
||||
protected virtual void UpdateToolbarItems(AToolbar toolbar, Page page)
|
||||
{
|
||||
var menu = toolbar.Menu;
|
||||
var sortedItems = page.ToolbarItems.OrderBy(x => x.Order);
|
||||
|
|
|
@ -16,7 +16,7 @@ using AView = Android.Views.View;
|
|||
using Color = Microsoft.Maui.Graphics.Color;
|
||||
using LP = Android.Views.ViewGroup.LayoutParams;
|
||||
using Paint = Android.Graphics.Paint;
|
||||
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
return CreateShellSectionView(shellSection);
|
||||
}
|
||||
|
||||
IShellToolbarTracker IShellContext.CreateTrackerForToolbar(Toolbar toolbar)
|
||||
IShellToolbarTracker IShellContext.CreateTrackerForToolbar(AToolbar toolbar)
|
||||
{
|
||||
return CreateTrackerForToolbar(toolbar);
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
return new ShellSectionView(this);
|
||||
}
|
||||
|
||||
protected virtual IShellToolbarTracker CreateTrackerForToolbar(Toolbar toolbar)
|
||||
protected virtual IShellToolbarTracker CreateTrackerForToolbar(AToolbar toolbar)
|
||||
{
|
||||
return new ShellToolbarTracker(this, toolbar, ((IShellContext)this).CurrentDrawerLayout);
|
||||
}
|
||||
|
|
|
@ -29,12 +29,11 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
{
|
||||
public class TabbedPageManager
|
||||
{
|
||||
Fragment _tabLayoutFragment;
|
||||
ColorStateList _originalTabTextColors;
|
||||
ColorStateList _orignalTabIconColors;
|
||||
|
||||
ColorStateList _newTabTextColors;
|
||||
ColorStateList _newTabIconColors;
|
||||
|
||||
FragmentManager _fragmentManager;
|
||||
TabLayout _tabLayout;
|
||||
BottomNavigationView _bottomNavigationView;
|
||||
|
@ -46,16 +45,17 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
int _defaultARGBColor = Colors.Transparent.ToNative().ToArgb();
|
||||
AColor _defaultAndroidColor = Colors.Transparent.ToNative();
|
||||
readonly IMauiContext _context;
|
||||
private readonly Listeners _listeners;
|
||||
|
||||
readonly Listeners _listeners;
|
||||
TabbedPage Element { get; set; }
|
||||
internal TabLayout TabLayout => _tabLayout;
|
||||
internal BottomNavigationView BottomNavigationView => _bottomNavigationView;
|
||||
internal ViewPager2 ViewPager => _viewPager;
|
||||
NavigationRootManager NavigationRootManager { get; }
|
||||
|
||||
public TabbedPageManager(IMauiContext context)
|
||||
{
|
||||
_context = context;
|
||||
NavigationRootManager = _context.GetNavigationRootManager();
|
||||
_listeners = new Listeners(this);
|
||||
_viewPager = new ViewPager2(context.Context)
|
||||
{
|
||||
|
@ -104,11 +104,16 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
{
|
||||
Element.PropertyChanged -= OnElementPropertyChanged;
|
||||
((IPageController)Element).InternalChildren.CollectionChanged -= OnChildrenCollectionChanged;
|
||||
Element.Appearing -= OnTabbedPageAppearing;
|
||||
Element.Disappearing -= OnTabbedPageDisappearing;
|
||||
RemoveTabs();
|
||||
}
|
||||
|
||||
Element = tabbedPage;
|
||||
if (Element != null)
|
||||
{
|
||||
Element.Appearing += OnTabbedPageAppearing;
|
||||
Element.Disappearing += OnTabbedPageDisappearing;
|
||||
_viewPager.Adapter = new MultiPageFragmentStateAdapter<Page>(tabbedPage, FragmentManager, _context) { CountOverride = tabbedPage.Children.Count };
|
||||
Element.PropertyChanged += OnElementPropertyChanged;
|
||||
if (IsBottomTabPlacement)
|
||||
|
@ -126,7 +131,6 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
if (_tabLayout == null)
|
||||
{
|
||||
var layoutInflater = Element.Handler.MauiContext.GetLayoutInflater();
|
||||
var navManager = Element.Handler.MauiContext.GetNavigationManager();
|
||||
_tabLayout = new TabLayout(_context.Context)
|
||||
{
|
||||
TabMode = TabLayout.ModeFixed,
|
||||
|
@ -150,9 +154,83 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
UpdateItemIconColor();
|
||||
UpdateSwipePaging();
|
||||
UpdateOffscreenPageLimit();
|
||||
SetTabLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveTabs()
|
||||
{
|
||||
if (_tabLayoutFragment != null)
|
||||
{
|
||||
var fragment = _tabLayoutFragment;
|
||||
_tabLayoutFragment = null;
|
||||
_ = _context
|
||||
.GetNavigationRootManager()
|
||||
.FragmentManager
|
||||
.BeginTransaction()
|
||||
.Remove(fragment)
|
||||
.SetReorderingAllowed(true)
|
||||
.Commit();
|
||||
|
||||
_tabplacementId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OnTabbedPageDisappearing(object sender, EventArgs e)
|
||||
{
|
||||
RemoveTabs();
|
||||
}
|
||||
|
||||
void OnTabbedPageAppearing(object sender, EventArgs e)
|
||||
{
|
||||
SetTabLayout();
|
||||
}
|
||||
|
||||
int _tabplacementId;
|
||||
internal void SetTabLayout()
|
||||
{
|
||||
int id;
|
||||
var rootManager =
|
||||
_context.GetNavigationRootManager();
|
||||
|
||||
if (IsBottomTabPlacement)
|
||||
{
|
||||
id = Resource.Id.navigationlayout_bottomtabs;
|
||||
if (_tabplacementId == id)
|
||||
return;
|
||||
|
||||
_tabLayoutFragment = new ViewFragment(BottomNavigationView);
|
||||
|
||||
var layoutContent = rootManager.RootView.FindViewById(Resource.Id.navigationlayout_content);
|
||||
if (layoutContent.LayoutParameters is ViewGroup.MarginLayoutParams cl)
|
||||
{
|
||||
cl.BottomMargin = _context.Context.Resources.GetDimensionPixelSize(Resource.Dimension.design_bottom_navigation_height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = Resource.Id.navigationlayout_toptabs;
|
||||
if (_tabplacementId == id)
|
||||
return;
|
||||
|
||||
_tabLayoutFragment = new ViewFragment(TabLayout);
|
||||
var layoutContent = rootManager.RootView.FindViewById(Resource.Id.navigationlayout_content);
|
||||
if (layoutContent.LayoutParameters is ViewGroup.MarginLayoutParams cl)
|
||||
{
|
||||
cl.BottomMargin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_tabplacementId = id;
|
||||
_ = rootManager
|
||||
.FragmentManager
|
||||
.BeginTransaction()
|
||||
.Replace(id, _tabLayoutFragment)
|
||||
.SetReorderingAllowed(true)
|
||||
.Commit();
|
||||
}
|
||||
|
||||
|
||||
void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(TabbedPage.CurrentPage))
|
||||
|
@ -181,14 +259,14 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
{
|
||||
e.Apply((o, i, c) => SetupPage((Page)o), (o, i) => TeardownPage((Page)o), Reset);
|
||||
|
||||
ViewPager2 pager = _viewPager;
|
||||
var adapter = (MultiPageFragmentStateAdapter<Page>)pager.Adapter;
|
||||
adapter.CountOverride = Element.Children.Count;
|
||||
if (IsBottomTabPlacement)
|
||||
{
|
||||
ViewPager2 pager = _viewPager;
|
||||
BottomNavigationView bottomNavigationView = _bottomNavigationView;
|
||||
|
||||
((MultiPageFragmentStateAdapter<Page>)pager.Adapter).CountOverride = Element.Children.Count;
|
||||
|
||||
pager.Adapter.NotifyDataSetChanged();
|
||||
adapter.NotifyDataSetChanged();
|
||||
|
||||
if (Element.Children.Count == 0)
|
||||
{
|
||||
|
@ -204,11 +282,9 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
}
|
||||
else
|
||||
{
|
||||
ViewPager2 pager = _viewPager;
|
||||
TabLayout tabs = _tabLayout;
|
||||
|
||||
((MultiPageFragmentStateAdapter<Page>)pager.Adapter).CountOverride = Element.Children.Count;
|
||||
pager.Adapter.NotifyDataSetChanged();
|
||||
adapter.NotifyDataSetChanged();
|
||||
if (Element.Children.Count == 0)
|
||||
{
|
||||
tabs.RemoveAllTabs();
|
||||
|
@ -375,7 +451,7 @@ namespace Microsoft.Maui.Controls.Handlers
|
|||
_context,
|
||||
result =>
|
||||
{
|
||||
SetTabIconImageSource(tab, result.Value);
|
||||
SetTabIconImageSource(tab, result?.Value);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,154 +0,0 @@
|
|||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using WImage = Microsoft.UI.Xaml.Controls.Image;
|
||||
using NativeAutomationProperties = Microsoft.UI.Xaml.Automation.AutomationProperties;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
public class ControlsNavigationManager : NavigationManager
|
||||
{
|
||||
readonly ImageConverter _imageConverter = new ImageConverter();
|
||||
readonly ImageSourceIconElementConverter _imageSourceIconElementConverter = new ImageSourceIconElementConverter();
|
||||
public new Page CurrentPage => (Page)base.CurrentPage;
|
||||
public new NavigationPage? NavigationView => (NavigationPage?)base.NavigationView;
|
||||
|
||||
public ControlsNavigationManager(IMauiContext mauiContext) : base(mauiContext)
|
||||
{
|
||||
}
|
||||
|
||||
internal void ToolbarPropertyChanged() => UpdateToolbar();
|
||||
|
||||
public override void NavigateTo(NavigationRequest arg3)
|
||||
{
|
||||
base.NavigateTo(arg3);
|
||||
UpdateToolbar();
|
||||
}
|
||||
|
||||
// TODO MAUI: This will need to be updated to handle multiple nested navigation pages
|
||||
protected virtual void UpdateToolbar()
|
||||
{
|
||||
if (WindowManager.RootView is not MauiNavigationView nativeNavigationView || NavigationStack.Count == 0)
|
||||
return;
|
||||
|
||||
var commandBar = WindowManager.GetCommandBar();
|
||||
var header = nativeNavigationView.Header as WindowHeader;
|
||||
|
||||
// TODO MAUI: these only apply for the top level NavigationManager
|
||||
if (commandBar != null)
|
||||
commandBar.IsDynamicOverflowEnabled = NavigationView.OnThisPlatform().GetToolbarDynamicOverflowEnabled();
|
||||
|
||||
bool hasNavigationBar = NavigationPage.GetHasNavigationBar(CurrentPage);
|
||||
bool hasBackButton =
|
||||
NavigationPage.GetHasBackButton(CurrentPage) &&
|
||||
hasNavigationBar &&
|
||||
NavigationStack.Count > 1;
|
||||
|
||||
var title = CurrentPage.Title;
|
||||
var titleIcon = NavigationPage.GetTitleIconImageSource(CurrentPage);
|
||||
var titleView = NavigationPage.GetTitleView(CurrentPage);
|
||||
|
||||
var barBackground = NavigationView?.BarBackground;
|
||||
var barBackgroundColor = NavigationView?.BarBackgroundColor;
|
||||
var barTextColor = NavigationView?.BarTextColor;
|
||||
|
||||
// TODO MAUI: it seems like this isn't wired up on WinUI
|
||||
//var iconColor = NavigationPage.GetIconColor(CurrentPage);
|
||||
|
||||
// TODO MAUI: Should be able to just modify the GRID inside NavigationLayout to move header to footer
|
||||
// Or we add a control in the footer
|
||||
var toolbarPlacement = NavigationView?.OnThisPlatform().GetToolbarPlacement();
|
||||
|
||||
if (header != null)
|
||||
{
|
||||
header.Visibility = (hasNavigationBar) ? UI.Xaml.Visibility.Visible : UI.Xaml.Visibility.Collapsed;
|
||||
|
||||
// HeaderContent is set to a MinHeight of 48 so we have to collapse it if we
|
||||
// we want to hide the navbar completely
|
||||
if (nativeNavigationView.HeaderContent != null)
|
||||
nativeNavigationView.HeaderContent.Visibility = header.Visibility;
|
||||
|
||||
header.Title = title;
|
||||
|
||||
titleIcon.LoadImage(MauiContext, (result) =>
|
||||
{
|
||||
header.TitleIcon = result?.Value;
|
||||
});
|
||||
if (barTextColor != null)
|
||||
header.TitleColor = barTextColor.ToNative();
|
||||
|
||||
header.TitleView = titleView?.ToNative(MauiContext);
|
||||
}
|
||||
|
||||
nativeNavigationView.IsBackButtonVisible = (hasBackButton) ? NavigationViewBackButtonVisible.Visible : NavigationViewBackButtonVisible.Collapsed;
|
||||
nativeNavigationView.IsBackEnabled = true;
|
||||
nativeNavigationView.UpdateBarBackgroundBrush(
|
||||
barBackground?.ToBrush() ?? barBackgroundColor?.ToNative());
|
||||
|
||||
UpdateToolbarItems();
|
||||
nativeNavigationView.PaneDisplayMode = NavigationViewPaneDisplayMode.LeftMinimal;
|
||||
nativeNavigationView.IsPaneOpen = false;
|
||||
}
|
||||
|
||||
//TODO MAUI: This will need to be updated to handle nested pages propagating up
|
||||
internal void UpdateToolbarItems()
|
||||
{
|
||||
if (WindowManager.RootView is not MauiNavigationView navigationView || NavigationStack.Count == 0)
|
||||
return;
|
||||
|
||||
var commandBar = WindowManager.GetCommandBar();
|
||||
|
||||
if (commandBar == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commandBar.PrimaryCommands.Clear();
|
||||
commandBar.SecondaryCommands.Clear();
|
||||
|
||||
List<ToolbarItem> toolbarItems = new List<ToolbarItem>();
|
||||
if (NavigationView != null)
|
||||
toolbarItems.AddRange(NavigationView.ToolbarItems);
|
||||
toolbarItems.AddRange(CurrentPage.ToolbarItems);
|
||||
|
||||
foreach (ToolbarItem item in toolbarItems)
|
||||
{
|
||||
var button = new AppBarButton();
|
||||
button.SetBinding(AppBarButton.LabelProperty, "Text");
|
||||
|
||||
if (commandBar.IsDynamicOverflowEnabled && item.Order == ToolbarItemOrder.Secondary)
|
||||
{
|
||||
button.SetBinding(AppBarButton.IconProperty, "IconImageSource", _imageSourceIconElementConverter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var img = new WImage();
|
||||
img.SetBinding(WImage.SourceProperty, "Value");
|
||||
img.SetBinding(WImage.DataContextProperty, "IconImageSource", _imageConverter);
|
||||
button.Content = img;
|
||||
}
|
||||
|
||||
// TODO MAUI: MenuItemCommand is no longer available in WinUI
|
||||
//button.Command = new MenuItemCommand(item);
|
||||
button.DataContext = item;
|
||||
button.SetValue(NativeAutomationProperties.AutomationIdProperty, item.AutomationId);
|
||||
button.SetAutomationPropertiesName(item);
|
||||
button.SetAutomationPropertiesAccessibilityView(item);
|
||||
button.SetAutomationPropertiesHelpText(item);
|
||||
|
||||
button.SetAutomationPropertiesLabeledBy(item, null);
|
||||
|
||||
ToolbarItemOrder order = item.Order == ToolbarItemOrder.Default ? ToolbarItemOrder.Primary : item.Order;
|
||||
if (order == ToolbarItemOrder.Primary)
|
||||
{
|
||||
commandBar.PrimaryCommands.Add(button);
|
||||
}
|
||||
else
|
||||
{
|
||||
commandBar.SecondaryCommands.Add(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Color = Microsoft.Maui.Graphics.Color;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Platform
|
||||
{
|
||||
internal static class ToolbarExtensions
|
||||
{
|
||||
public static void UpdateIsVisible(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
nativeToolbar.Visibility = (toolbar.IsVisible) ? UI.Xaml.Visibility.Visible : UI.Xaml.Visibility.Collapsed;
|
||||
if (nativeToolbar.NavigationView?.HeaderContent != null)
|
||||
nativeToolbar.NavigationView.HeaderContent.Visibility = nativeToolbar.Visibility;
|
||||
}
|
||||
|
||||
public static void UpdateTitleIcon(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
_ = toolbar?.Handler?.MauiContext ?? throw new ArgumentNullException(nameof(toolbar.Handler.MauiContext));
|
||||
toolbar.TitleIcon.LoadImage(toolbar.Handler.MauiContext, (result) =>
|
||||
{
|
||||
if (result != null)
|
||||
{
|
||||
nativeToolbar.TitleIconImageSource = result.Value;
|
||||
toolbar.Handler.UpdateValue(nameof(Toolbar.IconColor));
|
||||
}
|
||||
else
|
||||
nativeToolbar.TitleIconImageSource = null;
|
||||
});
|
||||
}
|
||||
|
||||
public static void UpdateBackButton(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
if (nativeToolbar.NavigationView == null)
|
||||
return;
|
||||
|
||||
nativeToolbar
|
||||
.NavigationView
|
||||
.IsBackButtonVisible = (toolbar.BackButtonVisible) ? NavigationViewBackButtonVisible.Visible : NavigationViewBackButtonVisible.Collapsed;
|
||||
|
||||
nativeToolbar.NavigationView.IsBackEnabled = toolbar.BackButtonVisible;
|
||||
toolbar.Handler.UpdateValue(nameof(Toolbar.BarBackground));
|
||||
}
|
||||
|
||||
public static void UpdateBarBackgroundColor(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
UpdateBarBackground(nativeToolbar, toolbar);
|
||||
}
|
||||
|
||||
public static void UpdateBarBackground(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
if (nativeToolbar.NavigationView == null)
|
||||
return;
|
||||
|
||||
|
||||
var barBackground = toolbar.BarBackground;
|
||||
var barBackgroundColor = toolbar.BarBackgroundColor;
|
||||
|
||||
nativeToolbar.NavigationView.UpdateBarBackgroundBrush(
|
||||
barBackground?.ToBrush() ?? barBackgroundColor?.ToNative());
|
||||
}
|
||||
|
||||
public static void UpdateTitleView(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
_ = toolbar.Handler?.MauiContext ?? throw new ArgumentNullException(nameof(toolbar.Handler.MauiContext));
|
||||
|
||||
nativeToolbar.TitleView = toolbar.TitleView?.ToNative(toolbar.Handler.MauiContext);
|
||||
}
|
||||
|
||||
public static void UpdateIconColor(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
// This property wasn't wired up in Controls
|
||||
}
|
||||
|
||||
public static void UpdateTitle(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
nativeToolbar.Title = toolbar.Title;
|
||||
}
|
||||
|
||||
public static void UpdateBarTextColor(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
if (toolbar.BarTextColor != null)
|
||||
nativeToolbar.TitleColor = toolbar.BarTextColor.ToNative();
|
||||
}
|
||||
|
||||
public static void UpdateToolbarDynamicOverflowEnabled(this WindowHeader nativeToolbar, Toolbar toolbar)
|
||||
{
|
||||
if (nativeToolbar.CommandBar == null)
|
||||
return;
|
||||
|
||||
nativeToolbar.CommandBar.IsDynamicOverflowEnabled = toolbar.DynamicOverflowEnabled;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1363,6 +1363,7 @@ namespace Microsoft.Maui.Controls
|
|||
if (ModalStack.Count == 0 && !_shell.CurrentItem.CurrentItem.IsPoppingModalStack)
|
||||
_shell.CurrentItem.SendAppearing();
|
||||
|
||||
modalPopped.Parent = null;
|
||||
return modalPopped;
|
||||
}
|
||||
|
||||
|
@ -1371,6 +1372,8 @@ namespace Microsoft.Maui.Controls
|
|||
if (ModalStack.Count == 0)
|
||||
_shell.CurrentItem.SendDisappearing();
|
||||
|
||||
modal.Parent = (Element)_shell.FindParentOfType<IWindow>();
|
||||
|
||||
if (!_shell.CurrentItem.CurrentItem.IsPushingModalStack)
|
||||
modal.SendAppearing();
|
||||
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace Microsoft.Maui.Controls
|
||||
{
|
||||
public class Toolbar : Microsoft.Maui.IElement
|
||||
{
|
||||
NavigationPage _currentNavigationPage;
|
||||
Page _currentPage;
|
||||
VisualElement _titleView;
|
||||
string _title;
|
||||
Color _iconColor;
|
||||
Color _barTextColor;
|
||||
Brush _barBackground;
|
||||
Color _barBackgroundColor;
|
||||
ImageSource _titleIcon;
|
||||
string _backButtonTitle;
|
||||
double? _barHeight;
|
||||
bool _backButtonVisible;
|
||||
bool _hasBackStack;
|
||||
bool _isVisible = false;
|
||||
IEnumerable<ToolbarItem> _toolbarItems;
|
||||
ToolbarTracker _toolbarTracker = new ToolbarTracker();
|
||||
bool _dynamicOverflowEnabled;
|
||||
|
||||
public Toolbar()
|
||||
{
|
||||
_toolbarTracker.CollectionChanged += (_, __) => ToolbarItems = _toolbarTracker.ToolbarItems;
|
||||
}
|
||||
|
||||
public IEnumerable<ToolbarItem> ToolbarItems { get => _toolbarItems; set => SetProperty(ref _toolbarItems, value); }
|
||||
public bool IsVisible { get => _isVisible; set => SetProperty(ref _isVisible, value); }
|
||||
public bool HasBackStack { get => _hasBackStack; set => SetProperty(ref _hasBackStack, value); }
|
||||
public bool BackButtonVisible { get => _backButtonVisible; set => SetProperty(ref _backButtonVisible, value); }
|
||||
public double? BarHeight { get => _barHeight; set => SetProperty(ref _barHeight, value); }
|
||||
public string BackButtonTitle { get => _backButtonTitle; set => SetProperty(ref _backButtonTitle, value); }
|
||||
public ImageSource TitleIcon { get => _titleIcon; set => SetProperty(ref _titleIcon, value); }
|
||||
public Color BarBackgroundColor { get => _barBackgroundColor; set => SetProperty(ref _barBackgroundColor, value); }
|
||||
public Brush BarBackground { get => _barBackground; set => SetProperty(ref _barBackground, value); }
|
||||
public Color BarTextColor { get => _barTextColor; set => SetProperty(ref _barTextColor, value); }
|
||||
public Color IconColor { get => _iconColor; set => SetProperty(ref _iconColor, value); }
|
||||
public string Title { get => _title; set => SetProperty(ref _title, value); }
|
||||
public VisualElement TitleView { get => _titleView; set => SetProperty(ref _titleView, value); }
|
||||
public bool DynamicOverflowEnabled { get => _dynamicOverflowEnabled; set => SetProperty(ref _dynamicOverflowEnabled, value); }
|
||||
|
||||
public IElementHandler Handler { get; set; }
|
||||
|
||||
Maui.IElement _parent;
|
||||
Maui.IElement Maui.IElement.Parent => _parent;
|
||||
|
||||
void SetProperty<T>(ref T backingStore, T value,
|
||||
[CallerMemberName] string propertyName = "")
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(backingStore, value))
|
||||
return;
|
||||
|
||||
backingStore = value;
|
||||
Handler?.UpdateValue(propertyName);
|
||||
}
|
||||
|
||||
internal void ApplyNavigationPage(NavigationPage navigationPage)
|
||||
{
|
||||
_parent = _parent ?? navigationPage.FindParentOfType<Window>();
|
||||
if (_currentNavigationPage == navigationPage)
|
||||
return;
|
||||
|
||||
if (_currentNavigationPage != null)
|
||||
_currentNavigationPage.PropertyChanged -= OnPropertyChanged;
|
||||
|
||||
_currentNavigationPage = navigationPage;
|
||||
_currentNavigationPage.PropertyChanged += OnPropertyChanged;
|
||||
UpdateCurrentPage();
|
||||
ApplyChanges(_currentNavigationPage);
|
||||
}
|
||||
|
||||
void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (sender == _currentNavigationPage && e.Is(NavigationPage.CurrentPageProperty))
|
||||
{
|
||||
UpdateCurrentPage();
|
||||
ApplyChanges(_currentNavigationPage);
|
||||
}
|
||||
else if (e.IsOneOf(NavigationPage.HasNavigationBarProperty,
|
||||
NavigationPage.HasBackButtonProperty,
|
||||
NavigationPage.TitleIconImageSourceProperty,
|
||||
NavigationPage.TitleViewProperty,
|
||||
NavigationPage.IconColorProperty) ||
|
||||
e.IsOneOf(Page.TitleProperty,
|
||||
PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage.BarHeightProperty,
|
||||
NavigationPage.BarBackgroundColorProperty,
|
||||
NavigationPage.BarBackgroundProperty,
|
||||
NavigationPage.BarTextColorProperty) ||
|
||||
e.IsOneOf(
|
||||
PlatformConfiguration.WindowsSpecific.Page.ToolbarDynamicOverflowEnabledProperty,
|
||||
PlatformConfiguration.WindowsSpecific.Page.ToolbarPlacementProperty))
|
||||
{
|
||||
ApplyChanges(_currentNavigationPage);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCurrentPage()
|
||||
{
|
||||
if (_currentNavigationPage == null)
|
||||
return;
|
||||
|
||||
var stack = _currentNavigationPage.Navigation.NavigationStack;
|
||||
if (stack.Count == 0)
|
||||
return;
|
||||
|
||||
if (_currentPage == _currentNavigationPage.CurrentPage)
|
||||
return;
|
||||
|
||||
if (_currentPage != null)
|
||||
_currentPage.PropertyChanged -= OnPropertyChanged;
|
||||
|
||||
_currentPage = _currentNavigationPage.CurrentPage;
|
||||
_currentNavigationPage.CurrentPage.PropertyChanged += OnPropertyChanged;
|
||||
|
||||
HasBackStack = _currentNavigationPage.Navigation.NavigationStack.Count > 1;
|
||||
}
|
||||
|
||||
void ApplyChanges(NavigationPage navigationPage)
|
||||
{
|
||||
var stack = navigationPage.Navigation.NavigationStack;
|
||||
if (stack.Count == 0)
|
||||
return;
|
||||
|
||||
UpdateCurrentPage();
|
||||
var currentPage = _currentPage;
|
||||
|
||||
Page previousPage = null;
|
||||
if (stack.Count > 1)
|
||||
previousPage = stack[stack.Count - 1];
|
||||
|
||||
_toolbarTracker.Target = navigationPage.CurrentPage;
|
||||
_toolbarTracker.AdditionalTargets = navigationPage.GetParentPages();
|
||||
ToolbarItems = _toolbarTracker.ToolbarItems;
|
||||
IsVisible = NavigationPage.GetHasNavigationBar(currentPage);
|
||||
BackButtonVisible = NavigationPage.GetHasBackButton(currentPage) && stack.Count > 1;
|
||||
|
||||
if (navigationPage.IsSet(PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage.BarHeightProperty))
|
||||
BarHeight = PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage.GetBarHeight(navigationPage);
|
||||
else
|
||||
BarHeight = null;
|
||||
|
||||
if (previousPage != null)
|
||||
BackButtonTitle = NavigationPage.GetBackButtonTitle(previousPage);
|
||||
else
|
||||
BackButtonTitle = null;
|
||||
|
||||
TitleIcon = NavigationPage.GetTitleIconImageSource(currentPage);
|
||||
BarBackgroundColor = navigationPage.BarBackgroundColor;
|
||||
BarBackground = navigationPage.BarBackground;
|
||||
BarTextColor = navigationPage.BarTextColor;
|
||||
IconColor = NavigationPage.GetIconColor(currentPage);
|
||||
Title = currentPage.Title;
|
||||
TitleView = NavigationPage.GetTitleView(navigationPage);
|
||||
DynamicOverflowEnabled = PlatformConfiguration.WindowsSpecific.Page.GetToolbarDynamicOverflowEnabled(_currentPage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ using System.Collections.ObjectModel;
|
|||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Microsoft.Maui.Controls.Internals;
|
||||
|
||||
namespace Microsoft.Maui.Controls
|
||||
{
|
||||
|
|
|
@ -19,8 +19,9 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
=> resultPage = (ContentPage)sender;
|
||||
|
||||
NavigationPage nav = new NavigationPage(contentPage);
|
||||
|
||||
Assert.IsNull(resultPage);
|
||||
nav.SendAppearing();
|
||||
_ = new Window(nav);
|
||||
Assert.AreEqual(resultPage, contentPage);
|
||||
}
|
||||
|
||||
|
@ -40,6 +41,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
=> pageAppearing = (ContentPage)sender;
|
||||
|
||||
NavigationPage nav = new NavigationPage(initialPage);
|
||||
_ = new Window(nav);
|
||||
nav.SendAppearing();
|
||||
|
||||
await nav.PushAsync(pushedPage);
|
||||
|
@ -58,6 +60,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
ContentPage pageDisappeared = null;
|
||||
|
||||
NavigationPage nav = new NavigationPage(initialPage);
|
||||
_ = new Window(nav);
|
||||
nav.SendAppearing();
|
||||
|
||||
initialPage.Appearing += (sender, _)
|
||||
|
@ -86,6 +89,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
ContentPage pageDisappeared = null;
|
||||
|
||||
NavigationPage nav = new NavigationPage(initialPage);
|
||||
_ = new Window(nav);
|
||||
nav.SendAppearing();
|
||||
|
||||
initialPage.Appearing += (sender, _)
|
||||
|
@ -115,6 +119,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
ContentPage pageDisappeared = null;
|
||||
|
||||
NavigationPage nav = new NavigationPage(initialPage);
|
||||
_ = new Window(nav);
|
||||
nav.SendAppearing();
|
||||
|
||||
var pageToRemove = new ContentPage();
|
||||
|
|
|
@ -329,7 +329,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
|
||||
Assert.That(sent, Is.False, "Busy message sent while not visible");
|
||||
|
||||
((IPageController)page).SendAppearing();
|
||||
_ = new Window(page);
|
||||
|
||||
Assert.That(sent, Is.True, "Busy message not sent when visible");
|
||||
}
|
||||
|
@ -338,6 +338,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
public void BusySentWhenBusyPageDisappears()
|
||||
{
|
||||
var page = new ContentPage { IsBusy = true };
|
||||
_ = new Window(page);
|
||||
((IPageController)page).SendAppearing();
|
||||
|
||||
var sent = false;
|
||||
|
@ -359,6 +360,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
MessagingCenter.Subscribe<Page, bool>(this, Page.BusySetSignalName, (p, b) => sent = true);
|
||||
|
||||
var page = new ContentPage();
|
||||
_ = new Window(page);
|
||||
((IPageController)page).SendAppearing();
|
||||
|
||||
Assert.That(sent, Is.False, "Busy message sent appearing while not busy");
|
||||
|
@ -457,7 +459,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
bool sent = false;
|
||||
page.Appearing += (sender, args) => sent = true;
|
||||
|
||||
((IPageController)page).SendAppearing();
|
||||
_ = new Window(page);
|
||||
|
||||
Assert.True(sent);
|
||||
}
|
||||
|
@ -466,6 +468,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
public void SendDisappearing()
|
||||
{
|
||||
var page = new ContentPage();
|
||||
_ = new Window(page);
|
||||
|
||||
((IPageController)page).SendAppearing();
|
||||
|
||||
|
@ -485,7 +488,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
int countAppearing = 0;
|
||||
page.Appearing += (sender, args) => countAppearing++;
|
||||
|
||||
((IPageController)page).SendAppearing();
|
||||
_ = new Window(page);
|
||||
((IPageController)page).SendAppearing();
|
||||
|
||||
Assert.That(countAppearing, Is.EqualTo(1));
|
||||
|
@ -515,7 +518,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
};
|
||||
navPage.Appearing += (sender, e) => sentNav = true;
|
||||
|
||||
((IPageController)navPage).SendAppearing();
|
||||
_ = new Window(navPage);
|
||||
|
||||
Assert.True(sentNav);
|
||||
Assert.True(sent);
|
||||
|
@ -528,6 +531,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
var page = new ContentPage();
|
||||
|
||||
var navPage = new NavigationPage(page);
|
||||
_ = new Window(navPage);
|
||||
((IPageController)navPage).SendAppearing();
|
||||
|
||||
bool sentNav = false;
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public void AppearingOnCreate()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
|
||||
FlyoutItem flyoutItem = new FlyoutItem();
|
||||
Tab tab = new Tab();
|
||||
|
@ -43,7 +43,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public void MisfiringOfAppearingWithMultipleTabs()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
|
||||
var item0 = CreateShellItem(shellContentRoute: "Outbox", templated: true);
|
||||
var item1 = CreateShellItem(shellSectionRoute: "RequestType1", shellContentRoute: "RequestType1Details", templated: true);
|
||||
|
@ -72,7 +72,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public void AppearingOnCreateFromTemplate()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
|
||||
FlyoutItem flyoutItem = new FlyoutItem();
|
||||
Tab tab = new Tab();
|
||||
|
@ -112,7 +112,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[TestCase(false)]
|
||||
public void EnsureOnAppearingFiresAfterParentIsSet(bool templated)
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
|
||||
ContentPage page = new ContentPage();
|
||||
|
||||
|
@ -137,7 +137,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task EnsureOnAppearingFiresForNavigatedToPage()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
await shell.GoToAsync("LifeCyclePage");
|
||||
|
||||
|
@ -150,7 +150,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task EnsureOnAppearingFiresForLastPageOnly()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
LifeCyclePage shellContentPage = new LifeCyclePage();
|
||||
shell.Items.Add(CreateShellItem(page: shellContentPage));
|
||||
await shell.GoToAsync("LifeCyclePage/LifeCyclePage");
|
||||
|
@ -165,7 +165,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task EnsureOnAppearingFiresForLastPageOnlyAbsoluteRoute()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
LifeCyclePage shellContentPage = new LifeCyclePage();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
shell.Items.Add(CreateShellItem(page: shellContentPage, shellItemRoute: "ShellItemRoute"));
|
||||
|
@ -183,7 +183,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task EnsureOnAppearingFiresForPushedPage()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
shell.Navigation.PushAsync(new LifeCyclePage());
|
||||
var page = (LifeCyclePage)shell.GetVisiblePage();
|
||||
|
@ -194,7 +194,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task NavigatedFiresAfterContentIsCreatedWhenUsingTemplate()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
|
||||
FlyoutItem flyoutItem = new FlyoutItem();
|
||||
Tab tab = new Tab();
|
||||
|
@ -239,7 +239,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public void AppearingOnShellContentChanged()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
var section = item.SearchForRoute<ShellSection>(SectionRoute);
|
||||
|
||||
|
@ -266,7 +266,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public void AppearingOnShellSectionChanged()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
var section = item.SearchForRoute<ShellSection>(SectionRoute);
|
||||
var newSection = CreateShellSection();
|
||||
|
@ -294,7 +294,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public void AppearingOnShellItemChanged()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
var item2 = CreateShellItem();
|
||||
shell.Items.Add(item2);
|
||||
|
@ -322,7 +322,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ShellPartWithModalPush()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
ShellLifeCycleState lifeCycleState = new ShellLifeCycleState(item);
|
||||
shell.Items.Add(item);
|
||||
|
@ -340,7 +340,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ShellPartWithPagePush()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
ShellLifeCycleState lifeCycleState = new ShellLifeCycleState(item);
|
||||
shell.Items.Add(item);
|
||||
|
@ -373,7 +373,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ShellPartWithPopToRoot()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
ShellLifeCycleState lifeCycleState = new ShellLifeCycleState(item);
|
||||
shell.Items.Add(item);
|
||||
|
@ -397,7 +397,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PagePushModal()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
ShellLifeCycleState lifeCycleState = new ShellLifeCycleState(item);
|
||||
shell.Items.Add(item);
|
||||
|
@ -421,7 +421,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PagePush()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item = CreateShellItem(shellContentRoute: ContentRoute, shellSectionRoute: SectionRoute, shellItemRoute: ItemRoute);
|
||||
shell.Items.Add(item);
|
||||
|
||||
|
@ -442,7 +442,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
public void OnNavigatedOnlyFiresOnce()
|
||||
{
|
||||
int navigated = 0;
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Navigated += (_, __) =>
|
||||
{
|
||||
navigated++;
|
||||
|
@ -457,7 +457,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public void AppearingOnlyForVisiblePage()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var pageAppearing = new ContentPage();
|
||||
var pageNotAppearing = new ContentPage();
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task BasicModalBehaviorTest()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
|
||||
await shell.GoToAsync("ModalTestPage");
|
||||
|
@ -29,7 +29,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ModalPopsWhenSwitchingShellItem()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute"));
|
||||
|
||||
|
@ -46,7 +46,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ModalPopsWhenSwitchingShellSection()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
shell.Items[0].Items.Add(CreateShellSection(shellSectionRoute: "NewRoute"));
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task AbsoluteRoutingToRootPopsModalPages()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellContentRoute: "MainContent"));
|
||||
|
||||
await shell.GoToAsync($"ModalTestPage/ModalTestPage");
|
||||
|
@ -77,7 +77,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PoppingEntireModalStackDoesntFireAppearingOnMiddlePages()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellContentRoute: "MainContent"));
|
||||
|
||||
await shell.GoToAsync($"ModalTestPage2/ModalTestPage");
|
||||
|
@ -90,7 +90,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PoppingModalStackFiresAppearingOnRevealedModalPage()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellContentRoute: "MainContent"));
|
||||
|
||||
await shell.GoToAsync($"ModalTestPage2/ModalTestPage");
|
||||
|
@ -105,7 +105,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ModalPopsWhenSwitchingShellContent()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
shell.Items[0].Items[0].Items.Add(CreateShellContent(shellContentRoute: "NewRoute"));
|
||||
|
||||
|
@ -122,7 +122,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ModalPopsWhenNavigatingWithoutModalRoute()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute"));
|
||||
|
||||
// pushes modal onto visible shell section
|
||||
|
@ -139,7 +139,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task ModalPopsWhenNavigatingToNewModalRoute()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute"));
|
||||
|
||||
// pushes modal onto visible shell section
|
||||
|
@ -157,7 +157,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
public async Task PagesPushToModalStack()
|
||||
{
|
||||
Routing.RegisterRoute("ContentPage", typeof(ContentPage));
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
await shell.GoToAsync("ModalNavigationTestPage/ContentPage");
|
||||
|
@ -173,7 +173,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
public async Task MultipleModalStacks()
|
||||
{
|
||||
Routing.RegisterRoute("ContentPage", typeof(ContentPage));
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
await shell.GoToAsync("ModalTestPage/ModalNavigationTestPage/ContentPage");
|
||||
|
@ -190,7 +190,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
public async Task MultipleModalStacksWithContentPageAlreadyPushed()
|
||||
{
|
||||
Routing.RegisterRoute("ContentPage", typeof(ContentPage));
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
await shell.GoToAsync("ContentPage/ModalNavigationTestPage/ContentPage/ModalNavigationTestPage/ContentPage");
|
||||
|
@ -201,7 +201,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task SwitchingModalStackAbsoluteNavigation()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
await shell.GoToAsync("ModalNavigationTestPage/ContentPage/ModalNavigationTestPage/ContentPage");
|
||||
|
@ -213,7 +213,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task SwitchingShellSectionsAndPushingModal()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content1"));
|
||||
shell.Items[0].Items[0].Items.Add(CreateShellContent(shellContentRoute: "Content2"));
|
||||
await shell.GoToAsync("//Content2/ModalNavigationTestPage");
|
||||
|
@ -224,7 +224,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PushingNonNavigationPage()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
Routing.RegisterRoute("ContentPage", typeof(ContentPage));
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
|
@ -237,7 +237,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PushingMultipleVersionsOfTheModalRoute()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
Routing.RegisterRoute("ContentPage", typeof(ContentPage));
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
|
@ -251,7 +251,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PushingContentPageToNonNavigationPageThrowsException()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
Routing.RegisterRoute("ContentPage", typeof(ContentPage));
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
|
@ -275,7 +275,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task AppearingAndDisappearingFiresOnShellWithModal()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.NavigationProxy.Inner = new NavigationProxy();
|
||||
var lifeCyclePage = new ShellLifeCycleTests.LifeCyclePage();
|
||||
shell.Items.Add(CreateShellItem(lifeCyclePage, shellItemRoute: "item", shellSectionRoute: "section", shellContentRoute: "content"));
|
||||
|
@ -292,7 +292,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task IsAppearingFiredOnLastModalPageOnly()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
await shell.GoToAsync("ModalTestPage/ModalTestPage2");
|
||||
|
@ -307,7 +307,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task BasicQueryStringTest()
|
||||
{
|
||||
var shell = new Shell();
|
||||
var shell = new TestShell();
|
||||
|
||||
var item = CreateShellItem(shellSectionRoute: "section2");
|
||||
shell.Items.Add(item);
|
||||
|
@ -337,7 +337,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task NavigatingAndNavigatedFiresForShellModal()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
ShellNavigatingEventArgs shellNavigatingEventArgs = null;
|
||||
|
@ -366,7 +366,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task GetCurrentPageInModalNavigation()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem(shellItemRoute: "NewRoute", shellSectionRoute: "Section", shellContentRoute: "Content"));
|
||||
|
||||
Page page = null;
|
||||
|
@ -384,7 +384,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
[Test]
|
||||
public async Task PopModalWithDots()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
shell.Items.Add(CreateShellItem());
|
||||
|
||||
await shell.CurrentPage.Navigation.PushModalAsync(new ContentPage());
|
||||
|
|
|
@ -322,6 +322,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
|
||||
public TestShell()
|
||||
{
|
||||
_ = new Window() { Page = this };
|
||||
Routing.RegisterRoute(nameof(TestPage1), typeof(TestPage1));
|
||||
Routing.RegisterRoute(nameof(TestPage2), typeof(TestPage2));
|
||||
Routing.RegisterRoute(nameof(TestPage3), typeof(TestPage3));
|
||||
|
@ -332,6 +333,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
|
||||
public TestShell(params ShellItem[] shellItems) : this()
|
||||
{
|
||||
_ = new Window() { Page = this };
|
||||
shellItems.ForEach(x => Items.Add(x));
|
||||
}
|
||||
|
||||
|
|
|
@ -1178,7 +1178,7 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
|
|||
|
||||
public async Task GetCurrentPageInShellNavigation()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
Shell shell = new TestShell();
|
||||
var item1 = CreateShellItem(asImplicit: true, shellContentRoute: "rootlevelcontent1");
|
||||
|
||||
shell.Items.Add(item1);
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Microsoft.Maui.DeviceTests.Stubs
|
|||
IServiceProvider _services;
|
||||
IAnimationManager _manager;
|
||||
#if WINDOWS
|
||||
WindowManager _windowManager;
|
||||
NavigationRootManager _windowManager;
|
||||
#endif
|
||||
|
||||
public ContextStub(IServiceProvider services)
|
||||
|
@ -30,8 +30,8 @@ namespace Microsoft.Maui.DeviceTests.Stubs
|
|||
if (serviceType == typeof(UIKit.UIWindow))
|
||||
return UIKit.UIApplication.SharedApplication.KeyWindow;
|
||||
#elif WINDOWS
|
||||
if (serviceType == typeof(WindowManager))
|
||||
return _windowManager ??= new WindowManager(this);
|
||||
if (serviceType == typeof(NavigationRootManager))
|
||||
return _windowManager ??= new NavigationRootManager(this);
|
||||
#endif
|
||||
|
||||
return _services.GetService(serviceType);
|
||||
|
|
|
@ -22,6 +22,6 @@ namespace Microsoft.Maui
|
|||
|
||||
void Destroying();
|
||||
|
||||
bool BackButtonPressed();
|
||||
bool BackButtonClicked();
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ namespace Microsoft.Maui.Handlers
|
|||
|
||||
public IElement? VirtualView { get; private protected set; }
|
||||
|
||||
public void SetMauiContext(IMauiContext mauiContext) =>
|
||||
public virtual void SetMauiContext(IMauiContext mauiContext) =>
|
||||
MauiContext = mauiContext;
|
||||
|
||||
public virtual void SetVirtualView(IElement view)
|
||||
|
|
|
@ -1,43 +1,62 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using AndroidX.Fragment.App;
|
||||
|
||||
namespace Microsoft.Maui.Handlers
|
||||
{
|
||||
public partial class NavigationViewHandler :
|
||||
ViewHandler<INavigationView, NavigationLayout>
|
||||
ViewHandler<INavigationView, View>
|
||||
{
|
||||
NavigationManager? _navigationManager;
|
||||
StackNavigationManager? _navigationManager;
|
||||
|
||||
protected override NavigationLayout CreateNativeView()
|
||||
protected override View CreateNativeView()
|
||||
{
|
||||
LayoutInflater? li = MauiContext?.GetLayoutInflater();
|
||||
_ = li ?? throw new InvalidOperationException($"LayoutInflater cannot be null");
|
||||
|
||||
var view = li.Inflate(Resource.Layout.navigationlayout, null).JavaCast<NavigationLayout>();
|
||||
var view = li.Inflate(Resource.Layout.fragment_backstack, null).JavaCast<FragmentContainerView>();
|
||||
_ = view ?? throw new InvalidOperationException($"Resource.Layout.navigationlayout view not found");
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
public override void SetVirtualView(IView view)
|
||||
public override void SetMauiContext(IMauiContext mauiContext)
|
||||
{
|
||||
_navigationManager ??= CreateNavigationManager();
|
||||
base.SetVirtualView(view);
|
||||
var currentInflater = mauiContext.GetLayoutInflater();
|
||||
var inflater =
|
||||
new StackNavigationManager.StackLayoutInflater(
|
||||
currentInflater,
|
||||
currentInflater.Context,
|
||||
CreateNavigationManager());
|
||||
|
||||
mauiContext =
|
||||
mauiContext.MakeScoped(inflater, context: inflater.Context);
|
||||
|
||||
base.SetMauiContext(mauiContext);
|
||||
}
|
||||
|
||||
protected virtual NavigationManager CreateNavigationManager() =>
|
||||
new NavigationManager(MauiContext!);
|
||||
StackNavigationManager CreateNavigationManager() =>
|
||||
_navigationManager ??= new StackNavigationManager();
|
||||
|
||||
protected override void ConnectHandler(NavigationLayout nativeView)
|
||||
protected override void ConnectHandler(View nativeView)
|
||||
{
|
||||
_navigationManager ??= CreateNavigationManager();
|
||||
nativeView.NavigationManager = _navigationManager;
|
||||
var rootContainer = MauiContext!.GetNavigationRootManager();
|
||||
var navigationLayout = rootContainer.NavigationLayout;
|
||||
|
||||
base.ConnectHandler(nativeView);
|
||||
_navigationManager.Connect(VirtualView, nativeView);
|
||||
_navigationManager?.Connect(VirtualView, navigationLayout);
|
||||
}
|
||||
|
||||
private protected override void OnDisconnectHandler(View nativeView)
|
||||
{
|
||||
_navigationManager?.Disconnect();
|
||||
base.OnDisconnectHandler(nativeView);
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(View nativeView)
|
||||
{
|
||||
base.DisconnectHandler(nativeView);
|
||||
}
|
||||
|
||||
public static void RequestNavigation(NavigationViewHandler arg1, INavigationView arg2, object? arg3)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using Android.App;
|
||||
using Google.Android.Material.AppBar;
|
||||
|
||||
namespace Microsoft.Maui.Handlers
|
||||
{
|
||||
|
@ -12,8 +13,9 @@ namespace Microsoft.Maui.Handlers
|
|||
_ = handler.MauiContext ?? throw new InvalidOperationException($"{nameof(MauiContext)} should have been set by base class.");
|
||||
|
||||
var nativeContent = window.Content.ToContainerView(handler.MauiContext);
|
||||
|
||||
handler.NativeView.SetContentView(nativeContent);
|
||||
var rootManager = handler.MauiContext.GetNavigationRootManager();
|
||||
rootManager.SetContentView(nativeContent);
|
||||
handler.NativeView.SetContentView(rootManager.RootView);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ namespace Microsoft.Maui.Handlers
|
|||
|
||||
protected override void DisconnectHandler(UI.Xaml.Window nativeView)
|
||||
{
|
||||
var windowManager = MauiContext?.GetWindowManager();
|
||||
var windowManager = MauiContext?.GetNavigationRootManager();
|
||||
windowManager?.Connect(VirtualView);
|
||||
|
||||
_rootPanel?.Children?.Clear();
|
||||
|
@ -42,7 +42,7 @@ namespace Microsoft.Maui.Handlers
|
|||
{
|
||||
_ = handler.MauiContext ?? throw new InvalidOperationException($"{nameof(MauiContext)} should have been set by base class.");
|
||||
|
||||
var windowManager = handler.MauiContext.GetWindowManager();
|
||||
var windowManager = handler.MauiContext.GetNavigationRootManager();
|
||||
windowManager.Connect(handler.VirtualView);
|
||||
handler?._rootPanel?.Children?.Clear();
|
||||
handler?._rootPanel?.Children?.Add(windowManager.RootView);
|
||||
|
|
|
@ -36,10 +36,13 @@ namespace Microsoft.Maui
|
|||
if (handler.VirtualView != view)
|
||||
handler.SetVirtualView(view);
|
||||
|
||||
if (((INativeViewHandler)handler).NativeView is not AView result)
|
||||
throw new InvalidOperationException($"Unable to convert {view} to {typeof(AView)}");
|
||||
if (handler is INativeViewHandler nvh && nvh.NativeView is AView)
|
||||
return nvh.NativeView;
|
||||
|
||||
return result;
|
||||
if (handler.NativeView is AView result)
|
||||
return result;
|
||||
|
||||
throw new InvalidOperationException($"Unable to convert {view} to {typeof(AView)}");
|
||||
}
|
||||
|
||||
public static void SetApplicationHandler(this Application nativeApplication, IApplication application, IMauiContext context) =>
|
||||
|
|
|
@ -17,8 +17,8 @@ namespace Microsoft.Maui
|
|||
return config.LayoutDirection.ToFlowDirection();
|
||||
}
|
||||
|
||||
public static NavigationManager GetNavigationManager(this IMauiContext mauiContext) =>
|
||||
mauiContext.Services.GetRequiredService<NavigationManager>();
|
||||
public static NavigationRootManager GetNavigationRootManager(this IMauiContext mauiContext) =>
|
||||
mauiContext.Services.GetRequiredService<NavigationRootManager>();
|
||||
|
||||
public static LayoutInflater GetLayoutInflater(this IMauiContext mauiContext)
|
||||
{
|
||||
|
@ -48,7 +48,10 @@ namespace Microsoft.Maui
|
|||
(mauiContext.Context?.GetActivity() as AppCompatActivity)
|
||||
?? throw new InvalidOperationException("AppCompatActivity Not Found");
|
||||
|
||||
public static IMauiContext MakeScoped(this IMauiContext mauiContext, LayoutInflater? layoutInflater = null, FragmentManager? fragmentManager = null)
|
||||
public static IMauiContext MakeScoped(this IMauiContext mauiContext,
|
||||
LayoutInflater? layoutInflater = null,
|
||||
FragmentManager? fragmentManager = null,
|
||||
Android.Content.Context? context = null)
|
||||
{
|
||||
var scopedContext = new MauiContext(mauiContext);
|
||||
|
||||
|
@ -58,14 +61,8 @@ namespace Microsoft.Maui
|
|||
if (fragmentManager != null)
|
||||
scopedContext.AddWeakSpecific(fragmentManager);
|
||||
|
||||
return scopedContext;
|
||||
}
|
||||
|
||||
public static IMauiContext MakeScoped(this IMauiContext mauiContext, NavigationManager navigationManager)
|
||||
{
|
||||
var scopedContext = new MauiContext(mauiContext);
|
||||
|
||||
scopedContext.AddSpecific(navigationManager);
|
||||
if (context != null)
|
||||
scopedContext.AddWeakSpecific(context);
|
||||
|
||||
return scopedContext;
|
||||
}
|
||||
|
@ -74,7 +71,7 @@ namespace Microsoft.Maui
|
|||
{
|
||||
var scopedContext = new MauiContext(mauiContext.Services, nativeWindow, mauiContext);
|
||||
|
||||
scopedContext.AddSpecific(nativeWindow);
|
||||
scopedContext.AddWeakSpecific(nativeWindow);
|
||||
|
||||
return scopedContext;
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
using System;
|
||||
using Android.Content;
|
||||
using Android.Runtime;
|
||||
using Android.Util;
|
||||
using AndroidX.AppCompat.Widget;
|
||||
using AndroidX.CoordinatorLayout.Widget;
|
||||
using Google.Android.Material.AppBar;
|
||||
|
||||
namespace Microsoft.Maui
|
||||
{
|
||||
public class NavigationLayout : CoordinatorLayout
|
||||
{
|
||||
// I'd prefer to not need this here but I'm not sure how else
|
||||
// to get this class to the NavigationViewFragment
|
||||
NavigationManager? _navigationManager;
|
||||
public NavigationManager NavigationManager
|
||||
{
|
||||
get => _navigationManager ?? throw new InvalidOperationException($"NavigationManager cannot be null");
|
||||
internal set => _navigationManager = value;
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 //FIXME: [Preserve] is obsolete
|
||||
[Preserve(Conditional = true)]
|
||||
public NavigationLayout(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
[Preserve(Conditional = true)]
|
||||
public NavigationLayout(Context context, IAttributeSet attrs) : base(context, attrs)
|
||||
{
|
||||
}
|
||||
|
||||
[Preserve(Conditional = true)]
|
||||
public NavigationLayout(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
|
||||
{
|
||||
}
|
||||
|
||||
[Preserve(Conditional = true)]
|
||||
protected NavigationLayout(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
#pragma warning restore CS0618 //FIXME: [Preserve] is obsolete
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Views.Animations;
|
||||
using AndroidX.AppCompat.Widget;
|
||||
using AndroidX.CoordinatorLayout.Widget;
|
||||
using AndroidX.Fragment.App;
|
||||
using Google.Android.Material.AppBar;
|
||||
using Google.Android.Material.Tabs;
|
||||
using AView = Android.Views.View;
|
||||
|
||||
namespace Microsoft.Maui
|
||||
{
|
||||
public class NavigationRootManager
|
||||
{
|
||||
CoordinatorLayout? _navigationLayout;
|
||||
IMauiContext _mauiContext;
|
||||
|
||||
internal CoordinatorLayout NavigationLayout => _navigationLayout ??=
|
||||
LayoutInflater
|
||||
.Inflate(Resource.Layout.navigationlayout, null)
|
||||
.JavaCast<CoordinatorLayout>()
|
||||
?? throw new InvalidOperationException($"Resource.Layout.navigationlayout missing");
|
||||
|
||||
LayoutInflater LayoutInflater => _mauiContext?.GetLayoutInflater()
|
||||
?? throw new InvalidOperationException($"LayoutInflater missing");
|
||||
|
||||
internal FragmentManager FragmentManager => _mauiContext?.GetFragmentManager()
|
||||
?? throw new InvalidOperationException($"FragmentManager missing");
|
||||
|
||||
public AView RootView => NavigationLayout;
|
||||
|
||||
public NavigationRootManager(IMauiContext mauiContext)
|
||||
{
|
||||
_mauiContext = mauiContext;
|
||||
}
|
||||
|
||||
// TODO MAUI: this will eventually get replaced by Navigation
|
||||
internal virtual void SetContentView(AView view)
|
||||
{
|
||||
FragmentManager.BeginTransaction()
|
||||
.Replace(Resource.Id.navigationlayout_content, new ViewFragment(view))
|
||||
.SetReorderingAllowed(true)
|
||||
.Commit();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using Android.Runtime;
|
|||
using Android.Views;
|
||||
using Android.Views.Animations;
|
||||
using AndroidX.Fragment.App;
|
||||
using AndroidX.Navigation;
|
||||
using AView = Android.Views.View;
|
||||
|
||||
namespace Microsoft.Maui
|
||||
|
@ -11,36 +12,14 @@ namespace Microsoft.Maui
|
|||
public class NavigationViewFragment : Fragment
|
||||
{
|
||||
AView? _currentView;
|
||||
NavigationLayout? _navigationLayout;
|
||||
FragmentContainerView? _fragmentContainerView;
|
||||
|
||||
// TODO MAUI: This currently feels like a very unreliable way to retrieve the NavigationLayout
|
||||
// If this is called before the Fragment View is parented then this call fails.
|
||||
// This should be converted to use Android ViewModels instead of just walking up the visual tree
|
||||
NavigationLayout NavigationLayout
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_navigationLayout != null)
|
||||
return _navigationLayout;
|
||||
|
||||
var view = FragmentContainerView.Parent;
|
||||
|
||||
while (view is not Maui.NavigationLayout && view != null)
|
||||
view = view?.Parent;
|
||||
|
||||
_navigationLayout = view as NavigationLayout;
|
||||
|
||||
return _navigationLayout ?? throw new InvalidOperationException($"NavigationLayout cannot be null here");
|
||||
}
|
||||
}
|
||||
|
||||
FragmentContainerView FragmentContainerView =>
|
||||
_fragmentContainerView ??= NavigationLayout.FindViewById<FragmentContainerView>(Resource.Id.nav_host)
|
||||
?? throw new InvalidOperationException($"FragmentContainerView cannot be null here");
|
||||
_fragmentContainerView ?? throw new InvalidOperationException($"FragmentContainerView cannot be null here");
|
||||
|
||||
// TODO Research ViewModels
|
||||
NavigationManager NavigationManager => NavigationLayout.NavigationManager
|
||||
StackNavigationManager? _navigationManager;
|
||||
|
||||
StackNavigationManager NavigationManager => _navigationManager
|
||||
?? throw new InvalidOperationException($"Graph cannot be null here");
|
||||
|
||||
protected NavigationViewFragment(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
|
@ -53,6 +32,12 @@ namespace Microsoft.Maui
|
|||
|
||||
public override AView OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
var context =
|
||||
(container.Context as StackNavigationManager.StackContext) ??
|
||||
(container.Parent as AView)?.Context as StackNavigationManager.StackContext
|
||||
?? throw new InvalidOperationException($"StackNavigationManager.StackContext not found");
|
||||
|
||||
_navigationManager = context.StackNavigationManager;
|
||||
_fragmentContainerView ??= (FragmentContainerView)container;
|
||||
|
||||
// When shuffling around the back stack sometimes we'll need a page to detach and then reattach.
|
||||
|
@ -70,8 +55,16 @@ namespace Microsoft.Maui
|
|||
// Then we can try some other approachs like just modifying the navbar ourselves to include a back button
|
||||
// Even if there's only one page on the stack
|
||||
|
||||
var scopedContext = NavigationManager.MauiContext.MakeScoped(inflater, ChildFragmentManager);
|
||||
_currentView = NavigationManager.CurrentPage.ToNative(scopedContext);
|
||||
_currentView =
|
||||
NavigationManager.CurrentPage.Handler?.NativeView as AView;
|
||||
|
||||
if (_currentView == null)
|
||||
{
|
||||
var scopedContext = NavigationManager.MauiContext.MakeScoped(inflater, ChildFragmentManager);
|
||||
|
||||
_currentView = NavigationManager.CurrentPage.ToNative(scopedContext);
|
||||
}
|
||||
|
||||
_currentView.RemoveFromParent();
|
||||
|
||||
return _currentView;
|
||||
|
@ -90,13 +83,6 @@ namespace Microsoft.Maui
|
|||
}
|
||||
|
||||
base.OnResume();
|
||||
|
||||
}
|
||||
|
||||
public override void OnDestroyView()
|
||||
{
|
||||
_navigationLayout = null;
|
||||
base.OnDestroyView();
|
||||
}
|
||||
|
||||
public override Animation OnCreateAnimation(int transit, bool enter, int nextAnim)
|
||||
|
|
|
@ -7,9 +7,9 @@ namespace Microsoft.Maui
|
|||
{
|
||||
class ProcessBackClick : AndroidX.Activity.OnBackPressedCallback, AView.IOnClickListener
|
||||
{
|
||||
NavigationManager _navigationManager;
|
||||
StackNavigationManager _navigationManager;
|
||||
|
||||
public ProcessBackClick(NavigationManager navHostPageFragment)
|
||||
public ProcessBackClick(StackNavigationManager navHostPageFragment)
|
||||
: base(true)
|
||||
{
|
||||
_navigationManager = navHostPageFragment;
|
||||
|
@ -17,12 +17,12 @@ namespace Microsoft.Maui
|
|||
|
||||
public override void HandleOnBackPressed()
|
||||
{
|
||||
_navigationManager.BackButtonPressed();
|
||||
_navigationManager.HardwareBackButtonClicked();
|
||||
}
|
||||
|
||||
public void OnClick(AView? v)
|
||||
{
|
||||
HandleOnBackPressed();
|
||||
_navigationManager.ToolbarBackButtonClicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
using System.Collections.Generic;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Views;
|
||||
using AndroidX.AppCompat.View;
|
||||
using AndroidX.AppCompat.Widget;
|
||||
using AndroidX.CoordinatorLayout.Widget;
|
||||
using AndroidX.Navigation;
|
||||
using AndroidX.Navigation.Fragment;
|
||||
using AndroidX.Navigation.UI;
|
||||
|
@ -11,14 +14,14 @@ using AView = Android.Views.View;
|
|||
|
||||
namespace Microsoft.Maui
|
||||
{
|
||||
public class NavigationManager
|
||||
public class StackNavigationManager
|
||||
{
|
||||
Toolbar? _toolbar;
|
||||
NavHostFragment? _navHost;
|
||||
FragmentNavigator? _fragmentNavigator;
|
||||
NavGraph? _navGraph;
|
||||
IView? _currentPage;
|
||||
NavigationLayout? _navigationLayout;
|
||||
CoordinatorLayout? _navigationLayout;
|
||||
ProcessBackClick BackClick { get; }
|
||||
internal IView? VirtualView { get; private set; }
|
||||
internal INavigationView? NavigationView { get; private set; }
|
||||
|
@ -38,23 +41,24 @@ namespace Microsoft.Maui
|
|||
internal NavGraph NavGraph => _navGraph ??
|
||||
throw new InvalidOperationException($"NavGraph cannot be null");
|
||||
|
||||
internal NavigationLayout NavigationLayout => _navigationLayout ??
|
||||
internal CoordinatorLayout NavigationLayout => _navigationLayout ??
|
||||
throw new InvalidOperationException($"NavigationLayout cannot be null");
|
||||
|
||||
public IView CurrentPage
|
||||
=> _currentPage ?? throw new InvalidOperationException("CurrentPage cannot be null");
|
||||
|
||||
public IMauiContext MauiContext { get; }
|
||||
public IMauiContext MauiContext =>
|
||||
VirtualView?.Handler?.MauiContext
|
||||
?? throw new InvalidOperationException("MauiContext cannot be null");
|
||||
|
||||
public NavigationManager(IMauiContext mauiContext)
|
||||
public StackNavigationManager()
|
||||
{
|
||||
MauiContext = mauiContext.MakeScoped(this);
|
||||
BackClick = new ProcessBackClick(this);
|
||||
}
|
||||
|
||||
internal Toolbar Toolbar =>
|
||||
_toolbar ??= NavigationLayout.FindViewById<MaterialToolbar>(Resource.Id.maui_toolbar)
|
||||
?? throw new InvalidOperationException($"ToolBar cannot be null");
|
||||
internal Toolbar? Toolbar =>
|
||||
_toolbar ??=
|
||||
NavigationLayout.FindViewById<MaterialToolbar>(Resource.Id.navigationlayout_toolbar);
|
||||
|
||||
/*
|
||||
* The important thing to know going into reading this method is that it's not possible to
|
||||
|
@ -208,6 +212,7 @@ namespace Microsoft.Maui
|
|||
public virtual FragmentNavigator.Destination AddFragmentDestination()
|
||||
{
|
||||
var destination = new FragmentNavigator.Destination(FragmentNavigator);
|
||||
|
||||
destination.SetClassName(Java.Lang.Class.FromType(typeof(NavigationViewFragment)).CanonicalName);
|
||||
destination.Id = AView.GenerateViewId();
|
||||
NavGraph.AddDestination(destination);
|
||||
|
@ -265,7 +270,11 @@ namespace Microsoft.Maui
|
|||
_currentPage = NavigationStack[NavigationStack.Count - 1];
|
||||
}
|
||||
|
||||
public virtual void Connect(IView navigationView, NavigationLayout nativeView)
|
||||
public virtual void Disconnect()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Connect(IView navigationView, CoordinatorLayout nativeView)
|
||||
{
|
||||
VirtualView = navigationView;
|
||||
NavigationView = (INavigationView)navigationView;
|
||||
|
@ -306,7 +315,7 @@ namespace Microsoft.Maui
|
|||
ApplyNavigationRequest(e);
|
||||
}
|
||||
|
||||
protected virtual void OnBackButtonPressed()
|
||||
protected virtual void OnToolbarBackButtonClicked()
|
||||
{
|
||||
_ = NavigationView ?? throw new InvalidOperationException($"NavigationView cannot be null");
|
||||
var stack = new List<IView>(NavigationStack);
|
||||
|
@ -314,7 +323,18 @@ namespace Microsoft.Maui
|
|||
ApplyNavigationRequest(new NavigationRequest(stack, true));
|
||||
}
|
||||
|
||||
internal void BackButtonPressed() => OnBackButtonPressed();
|
||||
internal void ToolbarBackButtonClicked() => OnToolbarBackButtonClicked();
|
||||
|
||||
protected virtual void OnHardwareBackButtonClicked()
|
||||
{
|
||||
if (MauiContext.GetActivity().GetWindow()?.BackButtonClicked() == false &&
|
||||
NavigationStack.Count == 1)
|
||||
{
|
||||
MauiContext.GetActivity().FinishAffinity();
|
||||
}
|
||||
}
|
||||
|
||||
internal void HardwareBackButtonClicked() => OnHardwareBackButtonClicked();
|
||||
|
||||
// Fragments are always destroyed if they aren't visible
|
||||
// The Handler/NativeView associated with the visible IView remain intact
|
||||
|
@ -346,19 +366,49 @@ namespace Microsoft.Maui
|
|||
|
||||
protected virtual void OnDestinationChanged(NavController navController, NavDestination navDestination, Bundle bundle)
|
||||
{
|
||||
if (CurrentPage is ITitledElement titledElement)
|
||||
}
|
||||
|
||||
internal class StackLayoutInflater : LayoutInflater
|
||||
{
|
||||
readonly LayoutInflater _original;
|
||||
|
||||
public StackLayoutInflater(
|
||||
LayoutInflater original,
|
||||
Context? context,
|
||||
StackNavigationManager stackNavigationManager) :
|
||||
base(original, new StackContext(context, stackNavigationManager))
|
||||
{
|
||||
Toolbar.Title = titledElement.Title;
|
||||
_original = original;
|
||||
StackNavigationManager = stackNavigationManager;
|
||||
}
|
||||
|
||||
public StackNavigationManager StackNavigationManager { get; }
|
||||
|
||||
public override LayoutInflater? CloneInContext(Context? newContext)
|
||||
{
|
||||
return new StackLayoutInflater(_original, newContext, StackNavigationManager);
|
||||
}
|
||||
}
|
||||
|
||||
internal class StackContext : AndroidX.AppCompat.View.ContextThemeWrapper
|
||||
{
|
||||
public StackContext(
|
||||
Context? context,
|
||||
StackNavigationManager stackNavigationManager) : base(context, context?.Theme)
|
||||
{
|
||||
StackNavigationManager = stackNavigationManager;
|
||||
}
|
||||
|
||||
public StackNavigationManager StackNavigationManager { get; }
|
||||
}
|
||||
|
||||
class Callbacks :
|
||||
AndroidX.Fragment.App.FragmentManager.FragmentLifecycleCallbacks,
|
||||
NavController.IOnDestinationChangedListener
|
||||
{
|
||||
NavigationManager _navigationManager;
|
||||
StackNavigationManager _navigationManager;
|
||||
|
||||
public Callbacks(NavigationManager navigationLayout)
|
||||
public Callbacks(StackNavigationManager navigationLayout)
|
||||
{
|
||||
_navigationManager = navigationLayout;
|
||||
}
|
||||
|
@ -382,6 +432,22 @@ namespace Microsoft.Maui
|
|||
f.RequireActivity()
|
||||
.OnBackPressedDispatcher
|
||||
.AddCallback(f, _navigationManager.BackClick);
|
||||
|
||||
|
||||
// Wire up the toolbar to the currently made visible Fragment
|
||||
var controller = NavHostFragment.FindNavController(f);
|
||||
var appbarConfig =
|
||||
new AppBarConfiguration
|
||||
.Builder(controller.Graph)
|
||||
.Build();
|
||||
|
||||
if (_navigationManager.Toolbar != null)
|
||||
{
|
||||
NavigationUI
|
||||
.SetupWithNavController(_navigationManager.Toolbar, controller, appbarConfig);
|
||||
|
||||
_navigationManager.Toolbar.SetNavigationOnClickListener(_navigationManager.BackClick);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnFragmentAttached(AndroidX.Fragment.App.FragmentManager fm, AndroidX.Fragment.App.Fragment f, Context context)
|
||||
|
@ -399,24 +465,6 @@ namespace Microsoft.Maui
|
|||
base.OnFragmentViewDestroyed(fm, f);
|
||||
}
|
||||
|
||||
public override void OnFragmentViewCreated(AndroidX.Fragment.App.FragmentManager fm, AndroidX.Fragment.App.Fragment f, AView v, Bundle savedInstanceState)
|
||||
{
|
||||
base.OnFragmentViewCreated(fm, f, v, savedInstanceState);
|
||||
|
||||
var controller = NavHostFragment.FindNavController(f);
|
||||
var appbarConfig =
|
||||
new AppBarConfiguration
|
||||
.Builder(controller.Graph)
|
||||
.Build();
|
||||
|
||||
// These have to get called/wired up every time a new fragment view is created
|
||||
// I'm not clear why this can't just be done once
|
||||
NavigationUI
|
||||
.SetupWithNavController(_navigationManager.Toolbar, controller, appbarConfig);
|
||||
|
||||
_navigationManager.Toolbar.SetNavigationOnClickListener(_navigationManager.BackClick);
|
||||
}
|
||||
|
||||
public override void OnFragmentCreated(AndroidX.Fragment.App.FragmentManager fm, AndroidX.Fragment.App.Fragment f, Bundle savedInstanceState)
|
||||
{
|
||||
base.OnFragmentCreated(fm, f, savedInstanceState);
|
|
@ -14,12 +14,10 @@ namespace Microsoft.Maui
|
|||
public ViewFragment(View aView)
|
||||
{
|
||||
_aView = aView;
|
||||
_aView.RemoveFromParent();
|
||||
}
|
||||
|
||||
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
_aView.RemoveFromParent();
|
||||
return _aView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,14 +69,26 @@ namespace Microsoft.Maui
|
|||
// aapt resource value: 0x7F080059
|
||||
public static int automation_tag_id = 2131230809;
|
||||
|
||||
// aapt resource value: 0x7F080061
|
||||
public static int bottomtab_containerview = 2131230817;
|
||||
// aapt resource value: 0x7F08013C
|
||||
public static int navigationlayout_appbar = 2131231036;
|
||||
|
||||
// aapt resource value: 0x7F080107
|
||||
public static int maui_toolbar = 2131230983;
|
||||
// aapt resource value: 0x7F08013D
|
||||
public static int navigationlayout_bottomtabs = 2131231037;
|
||||
|
||||
// aapt resource value: 0x7F08012D
|
||||
public static int nav_host = 2131231021;
|
||||
// aapt resource value: 0x7F08013E
|
||||
public static int navigationlayout_content = 2131231038;
|
||||
|
||||
// aapt resource value: 0x7F08013F
|
||||
public static int navigationlayout_toolbar = 2131231039;
|
||||
|
||||
// aapt resource value: 0x7F080140
|
||||
public static int navigationlayout_toptabs = 2131231040;
|
||||
|
||||
// aapt resource value: 0x7F080135
|
||||
public static int nav_host = 2131231029;
|
||||
|
||||
// aapt resource value: 0x7F080136
|
||||
public static int nav_host_fragment_container = 2131231030;
|
||||
|
||||
// aapt resource value: 0x7F08016A
|
||||
public static int search_button = 2131231082;
|
||||
|
@ -84,9 +96,6 @@ namespace Microsoft.Maui
|
|||
// aapt resource value: 0x7F08016B
|
||||
public static int search_close_btn = 2131231083;
|
||||
|
||||
// aapt resource value: 0x7F0801C6
|
||||
public static int toptabs_containerview = 2131231174;
|
||||
|
||||
static Id()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
|
@ -95,8 +104,13 @@ namespace Microsoft.Maui
|
|||
|
||||
public partial class Layout
|
||||
{
|
||||
// aapt resource value: 0x7F0B0059
|
||||
public static int navigationlayout = 2131427417;
|
||||
// aapt resource value: 0x7F0B005A
|
||||
public static int navigationlayout = 2131427418;
|
||||
|
||||
// aapt resource value: 0x7F0B002E
|
||||
public static int fragment_backstack = 2131427374;
|
||||
|
||||
|
||||
|
||||
static Layout()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/nav_host"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="false"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
>
|
||||
</androidx.fragment.app.FragmentContainerView>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<microsoft.maui.NavigationLayout
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -7,20 +7,22 @@
|
|||
>
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:id="@+id/navigationlayout_appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
>
|
||||
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/maui.toolbar"
|
||||
android:id="@+id/navigationlayout_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/toptabs_containerview"
|
||||
android:id="@+id/navigationlayout_toptabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
@ -28,17 +30,15 @@
|
|||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:id="@+id/navigationlayout_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
/>
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/bottomtab_containerview"
|
||||
android:id="@+id/navigationlayout_bottomtabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
/>
|
||||
</microsoft.maui.NavigationLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
@ -12,4 +12,4 @@ namespace Microsoft.Maui
|
|||
Android.Content.Context? Context { get; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ namespace Microsoft.Maui
|
|||
: this(services, parent)
|
||||
{
|
||||
AddWeakSpecific(context);
|
||||
|
||||
if (parent?.Services.GetService<NavigationRootManager>() == null && context is not Android.App.Application)
|
||||
AddSpecific(new NavigationRootManager(this));
|
||||
}
|
||||
#elif __IOS__
|
||||
public MauiContext(IServiceProvider services, UIKit.UIApplicationDelegate application, IMauiContext? parent = null)
|
||||
|
|
|
@ -29,12 +29,13 @@ namespace Microsoft.Maui
|
|||
if (handler.VirtualView != view)
|
||||
handler.SetVirtualView(view);
|
||||
|
||||
if (((INativeViewHandler)handler).NativeView is not FrameworkElement result)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to convert {view} to {typeof(FrameworkElement)}");
|
||||
}
|
||||
if (handler is INativeViewHandler nvh && nvh.NativeView is FrameworkElement)
|
||||
return nvh.NativeView;
|
||||
|
||||
return result;
|
||||
if (handler.NativeView is FrameworkElement result)
|
||||
return result;
|
||||
|
||||
throw new InvalidOperationException($"Unable to convert {view} to {typeof(FrameworkElement)}");
|
||||
}
|
||||
|
||||
public static void SetApplicationHandler(this UI.Xaml.Application nativeApplication, IApplication application, IMauiContext context) =>
|
||||
|
|
|
@ -16,8 +16,8 @@ namespace Microsoft.Maui
|
|||
return FlowDirection.MatchParent;
|
||||
}
|
||||
|
||||
public static WindowManager GetWindowManager(this IMauiContext mauiContext) =>
|
||||
mauiContext.Services.GetRequiredService<WindowManager>();
|
||||
public static NavigationRootManager GetNavigationRootManager(this IMauiContext mauiContext) =>
|
||||
mauiContext.Services.GetRequiredService<NavigationRootManager>();
|
||||
|
||||
public static UI.Xaml.Window GetNativeWindow(this IMauiContext mauiContext) =>
|
||||
mauiContext.Services.GetRequiredService<UI.Xaml.Window>();
|
||||
|
@ -29,7 +29,7 @@ namespace Microsoft.Maui
|
|||
{
|
||||
var scopedContext = new MauiContext(mauiContext);
|
||||
scopedContext.AddSpecific(nativeWindow);
|
||||
scopedContext.AddSpecific(new WindowManager(scopedContext));
|
||||
scopedContext.AddSpecific(new NavigationRootManager(scopedContext));
|
||||
return scopedContext;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Microsoft.Maui
|
|||
IView? _currentPage;
|
||||
IMauiContext _mauiContext;
|
||||
Frame? _navigationFrame;
|
||||
protected WindowManager WindowManager => _mauiContext.GetWindowManager();
|
||||
protected NavigationRootManager WindowManager => _mauiContext.GetNavigationRootManager();
|
||||
private protected INavigationView? NavigationView { get; private set; }
|
||||
public IReadOnlyList<IView> NavigationStack { get; set; } = new List<IView>();
|
||||
public IMauiContext MauiContext => _mauiContext;
|
||||
|
|
|
@ -7,14 +7,14 @@ using Microsoft.UI.Xaml.Controls;
|
|||
|
||||
namespace Microsoft.Maui
|
||||
{
|
||||
public class WindowManager
|
||||
public class NavigationRootManager
|
||||
{
|
||||
IMauiContext _mauiContext;
|
||||
MauiNavigationView _navigationView;
|
||||
IView? _content;
|
||||
IWindow? _window;
|
||||
|
||||
public WindowManager(IMauiContext mauiContext)
|
||||
public NavigationRootManager(IMauiContext mauiContext)
|
||||
{
|
||||
_mauiContext = mauiContext;
|
||||
_navigationView = new MauiNavigationView();
|
||||
|
@ -23,7 +23,7 @@ namespace Microsoft.Maui
|
|||
|
||||
void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
|
||||
{
|
||||
_window?.BackButtonPressed();
|
||||
_window?.BackButtonClicked();
|
||||
}
|
||||
|
||||
public FrameworkElement RootView => _navigationView;
|
|
@ -1,3 +1,4 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -11,10 +12,11 @@ using WImageSource = Microsoft.UI.Xaml.Media.ImageSource;
|
|||
using WVisibility = Microsoft.UI.Xaml.Visibility;
|
||||
using WGrid = Microsoft.UI.Xaml.Controls.Grid;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using WImage = Microsoft.UI.Xaml.Controls.Image;
|
||||
|
||||
namespace Microsoft.Maui
|
||||
{
|
||||
partial class WindowHeader
|
||||
public partial class WindowHeader
|
||||
{
|
||||
internal TranslateTransform? ClipGeometryTransform { get; private set; }
|
||||
internal RectangleGeometry? LayoutRootClip { get; private set; }
|
||||
|
@ -25,6 +27,8 @@ namespace Microsoft.Maui
|
|||
InitializeComponent();
|
||||
}
|
||||
|
||||
internal MauiNavigationView? NavigationView { get; set; }
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
@ -39,7 +43,12 @@ namespace Microsoft.Maui
|
|||
set => title.Text = value;
|
||||
}
|
||||
|
||||
internal WImageSource? TitleIcon
|
||||
internal WImage? TitleIconImage
|
||||
{
|
||||
get => titleIcon;
|
||||
}
|
||||
|
||||
internal WImageSource? TitleIconImageSource
|
||||
{
|
||||
get => titleIcon.Source;
|
||||
set => titleIcon.Source = value;
|
||||
|
|
|
@ -50,6 +50,6 @@ namespace Microsoft.Maui.Handlers.Benchmarks
|
|||
IsResumed = false;
|
||||
}
|
||||
|
||||
public bool BackButtonPressed() => true;
|
||||
public bool BackButtonClicked() => true;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace Microsoft.Maui.DeviceTests.Stubs
|
|||
IServiceProvider _services;
|
||||
IAnimationManager _manager;
|
||||
#if WINDOWS
|
||||
WindowManager _windowManager;
|
||||
NavigationRootManager _windowManager;
|
||||
#endif
|
||||
|
||||
public ContextStub(IServiceProvider services)
|
||||
|
@ -30,8 +30,8 @@ namespace Microsoft.Maui.DeviceTests.Stubs
|
|||
if (serviceType == typeof(UIKit.UIWindow))
|
||||
return UIKit.UIApplication.SharedApplication.GetKeyWindow();
|
||||
#elif WINDOWS
|
||||
if (serviceType == typeof(WindowManager))
|
||||
return _windowManager ??= new WindowManager(this);
|
||||
if (serviceType == typeof(NavigationRootManager))
|
||||
return _windowManager ??= new NavigationRootManager(this);
|
||||
#endif
|
||||
|
||||
return _services.GetService(serviceType);
|
||||
|
|
|
@ -51,6 +51,6 @@
|
|||
IsResumed = false;
|
||||
}
|
||||
|
||||
public bool BackButtonPressed() => true;
|
||||
public bool BackButtonClicked() => true;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче