зеркало из https://github.com/DeGsoft/maui-linux.git
[iOS] fix full width issues for TitleView (#3939)
* [iOS] fix full width issues for TitleView * [iOS] simplified iOS 10 fixes #3881 fixes #3679
This commit is contained in:
Родитель
16a4e91aac
Коммит
379adeb380
|
@ -387,7 +387,7 @@ namespace Xamarin.Forms.Controls
|
||||||
if (navigationBehavior == NavigationBehavior.PushAsync && rootPage.GetType () == typeof (CoreNavigationPage))
|
if (navigationBehavior == NavigationBehavior.PushAsync && rootPage.GetType () == typeof (CoreNavigationPage))
|
||||||
{
|
{
|
||||||
_pages.Insert (0, new GalleryPageFactory(() => new NavigationBarGallery((NavigationPage)rootPage), "NavigationBar Gallery - Legacy"));
|
_pages.Insert (0, new GalleryPageFactory(() => new NavigationBarGallery((NavigationPage)rootPage), "NavigationBar Gallery - Legacy"));
|
||||||
_pages.Insert(1, new GalleryPageFactory(() => new TitleView(), "TitleView"));
|
_pages.Insert(1, new GalleryPageFactory(() => new TitleView(true), "TitleView"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var template = new DataTemplate(typeof(TextCell));
|
var template = new DataTemplate(typeof(TextCell));
|
||||||
|
|
|
@ -1,19 +1,29 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="Xamarin.Forms.Controls.GalleryPages.TitleView">
|
x:Class="Xamarin.Forms.Controls.GalleryPages.TitleView">
|
||||||
|
|
||||||
<NavigationPage.TitleView>
|
<NavigationPage.TitleView>
|
||||||
<StackLayout>
|
<StackLayout BackgroundColor="Pink">
|
||||||
<Label Text="This is my TitleView" />
|
<Label Text="This is my TitleView" />
|
||||||
<Label Text="I can be a subtitle" />
|
<Label Text="I can be a subtitle" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</NavigationPage.TitleView>
|
</NavigationPage.TitleView>
|
||||||
|
|
||||||
<StackLayout>
|
<ScrollView>
|
||||||
<Label Text="Welcome to Xamarin.Forms!"
|
<StackLayout BackgroundColor="Pink">
|
||||||
VerticalOptions="CenterAndExpand"
|
<Button Clicked="masterDetailsPage_Clicked" Text="Master Details Page"></Button>
|
||||||
HorizontalOptions="CenterAndExpand" />
|
<Button Clicked="masterDetailsPageIcon_Clicked" Text="Toggle MDP Icon"></Button>
|
||||||
</StackLayout>
|
<Button Clicked="tabbedPage_Clicked" Text="Tabbed Page"></Button>
|
||||||
|
<Button Clicked="navigationPage_Clicked" Text="Navigation Page"></Button>
|
||||||
|
<Button Clicked="nextPage_Clicked" Text="Push a Page"></Button>
|
||||||
|
<Button Clicked="titleIcon_Clicked" Text="Toggle Title Icon"></Button>
|
||||||
|
<Button Clicked="toggleToolBarItem_Clicked" Text="Toggle Tool Bar Item" ></Button>
|
||||||
|
<Button Clicked="toggleSecondaryToolBarItem_Clicked" Text="Toggle Secondary Tool Bar Item" ></Button>
|
||||||
|
<Button Clicked="toggleLargeTitles_Clicked" Text="Toggle Large Titles" ></Button>
|
||||||
|
<Button Clicked="changeTitleView_Clicked" Text="Toggle Different Title Views"></Button>
|
||||||
|
<Button x:Name="btnToggleBackButtonTitle" Clicked="toggleBackButtonText_Clicked" Text="Toggle Back Button Title Text"></Button>
|
||||||
|
<Button Clicked="backToGallery_Clicked" Text="Back to Gallery"></Button>
|
||||||
|
</StackLayout>
|
||||||
|
</ScrollView>
|
||||||
</ContentPage>
|
</ContentPage>
|
|
@ -5,6 +5,8 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
using Xamarin.Forms.PlatformConfiguration;
|
||||||
|
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
|
||||||
using Xamarin.Forms.Xaml;
|
using Xamarin.Forms.Xaml;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Controls.GalleryPages
|
namespace Xamarin.Forms.Controls.GalleryPages
|
||||||
|
@ -12,9 +14,216 @@ namespace Xamarin.Forms.Controls.GalleryPages
|
||||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||||
public partial class TitleView : ContentPage
|
public partial class TitleView : ContentPage
|
||||||
{
|
{
|
||||||
public TitleView ()
|
public TitleView(bool initialLoad)
|
||||||
{
|
{
|
||||||
InitializeComponent ();
|
InitializeComponent();
|
||||||
|
|
||||||
|
if (initialLoad)
|
||||||
|
{
|
||||||
|
Device.BeginInvokeOnMainThread(() => masterDetailsPage_Clicked(this, EventArgs.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigationPage CreateNavigationPage()
|
||||||
|
{
|
||||||
|
return new NavigationPage(new TitleView(false) { Title = "Nav Title" });
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page GetPage()
|
||||||
|
{
|
||||||
|
return new MasterDetailPage()
|
||||||
|
{
|
||||||
|
Detail = CreateNavigationPage(),
|
||||||
|
Master = new ContentPage() { Title = "Master" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void masterDetailsPage_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
App.Current.MainPage =
|
||||||
|
new MasterDetailPage()
|
||||||
|
{
|
||||||
|
Detail = CreateNavigationPage(),
|
||||||
|
Master = new ContentPage() { Title = "Master" },
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleBackButtonText_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var page = Navigation.NavigationStack.First();
|
||||||
|
var titleText = NavigationPage.GetBackButtonTitle(page);
|
||||||
|
|
||||||
|
if (titleText == null)
|
||||||
|
titleText = "Custom Text";
|
||||||
|
else if (titleText == "Custom Text")
|
||||||
|
titleText = "";
|
||||||
|
else
|
||||||
|
titleText = null;
|
||||||
|
|
||||||
|
NavigationPage.SetBackButtonTitle(page, titleText);
|
||||||
|
changeTitleView_Clicked(this, EventArgs.Empty);
|
||||||
|
|
||||||
|
string result = (titleText == null) ? "<null>" : titleText;
|
||||||
|
btnToggleBackButtonTitle.Text = $"Toggle Back Button Title Text: {result}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void tabbedPage_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
var page = new ContentPage() { Title = "other title page" };
|
||||||
|
NavigationPage.SetTitleView(page, createGrid());
|
||||||
|
|
||||||
|
App.Current.MainPage =
|
||||||
|
new TabbedPage()
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
CreateNavigationPage(),
|
||||||
|
new ContentPage(){ Title = "no title Page"},
|
||||||
|
new NavigationPage(page),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void navigationPage_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
App.Current.MainPage = CreateNavigationPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nextPage_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
ContentPage page = null;
|
||||||
|
page = new ContentPage()
|
||||||
|
{
|
||||||
|
Title = "second page",
|
||||||
|
Content = new StackLayout()
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Button()
|
||||||
|
{
|
||||||
|
Text = "Toggle Back Button",
|
||||||
|
Command = new Command(()=>
|
||||||
|
{
|
||||||
|
NavigationPage.SetHasBackButton(page, !NavigationPage.GetHasBackButton(page));
|
||||||
|
})
|
||||||
|
},
|
||||||
|
new Button()
|
||||||
|
{
|
||||||
|
Text = "Toggle Title View",
|
||||||
|
Command = new Command(()=>
|
||||||
|
{
|
||||||
|
changeTitleView_Clicked(page, EventArgs.Empty);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NavigationPage.SetTitleView(page, createGrid());
|
||||||
|
Navigation.PushAsync(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
View createSearchBarView()
|
||||||
|
{
|
||||||
|
return new SearchBar { BackgroundColor = Color.Cornsilk, HorizontalOptions = LayoutOptions.FillAndExpand, Margin = new Thickness(10, 0) };
|
||||||
|
}
|
||||||
|
|
||||||
|
View createGrid()
|
||||||
|
{
|
||||||
|
var grid = new Grid
|
||||||
|
{
|
||||||
|
BackgroundColor = Color.LightGray
|
||||||
|
};
|
||||||
|
|
||||||
|
grid.RowDefinitions.Add(new RowDefinition());
|
||||||
|
grid.RowDefinitions.Add(new RowDefinition());
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition());
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
|
||||||
|
|
||||||
|
var label = new Label { Text = "hello", HorizontalOptions = LayoutOptions.Start, BackgroundColor = Color.Yellow };
|
||||||
|
var label2 = new Label { Text = "hello 2", HorizontalOptions = LayoutOptions.Start, BackgroundColor = Color.Yellow };
|
||||||
|
grid.Children.Add(label);
|
||||||
|
grid.Children.Add(label2);
|
||||||
|
Grid.SetRow(label2, 1);
|
||||||
|
|
||||||
|
var label3 = new Label { Text = "right aligned", HorizontalTextAlignment = TextAlignment.End };
|
||||||
|
Grid.SetColumn(label3, 1);
|
||||||
|
grid.Children.Add(label3);
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void titleIcon_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var titleIcon = NavigationPage.GetTitleIcon(this);
|
||||||
|
|
||||||
|
if (titleIcon == null)
|
||||||
|
NavigationPage.SetTitleIcon(this, "coffee.png");
|
||||||
|
else
|
||||||
|
NavigationPage.SetTitleIcon(this, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void masterDetailsPageIcon_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (App.Current.MainPage is MasterDetailPage mdp)
|
||||||
|
{
|
||||||
|
if (String.IsNullOrWhiteSpace(mdp.Master.Icon))
|
||||||
|
mdp.Master.Icon = "menuIcon";
|
||||||
|
else
|
||||||
|
mdp.Master.Icon = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleLargeTitles_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var navPage = (NavigationPage)Navigation.NavigationStack.Last().Parent;
|
||||||
|
navPage.On<iOS>().SetPrefersLargeTitles(!navPage.On<iOS>().PrefersLargeTitles());
|
||||||
|
}
|
||||||
|
|
||||||
|
void backToGallery_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
(App.Current as App).Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleToolBarItem_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var page = Navigation.NavigationStack.Last();
|
||||||
|
var items = page.ToolbarItems.Where(x => x.Order == ToolbarItemOrder.Primary).ToList();
|
||||||
|
|
||||||
|
if (items.Any())
|
||||||
|
foreach (var item in items)
|
||||||
|
page.ToolbarItems.Remove(item);
|
||||||
|
else
|
||||||
|
page.ToolbarItems.Add(new ToolbarItem() { Text = "Save", Order = ToolbarItemOrder.Primary });
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleSecondaryToolBarItem_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var page = Navigation.NavigationStack.Last();
|
||||||
|
var items = page.ToolbarItems.Where(x => x.Order == ToolbarItemOrder.Secondary).ToList();
|
||||||
|
|
||||||
|
if (items.Any())
|
||||||
|
foreach (var item in items)
|
||||||
|
page.ToolbarItems.Remove(item);
|
||||||
|
else
|
||||||
|
page.ToolbarItems.Add(new ToolbarItem() { Text = "Save", Order = ToolbarItemOrder.Secondary });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void changeTitleView_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var currentView = NavigationPage.GetTitleView(Navigation.NavigationStack.Last());
|
||||||
|
|
||||||
|
if (currentView is Grid)
|
||||||
|
NavigationPage.SetTitleView(Navigation.NavigationStack.Last(), createSearchBarView());
|
||||||
|
else if (currentView is SearchBar)
|
||||||
|
NavigationPage.SetTitleView(Navigation.NavigationStack.Last(), null);
|
||||||
|
else
|
||||||
|
NavigationPage.SetTitleView(Navigation.NavigationStack.Last(), createGrid());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,14 +33,14 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
UIImage _defaultNavBarShadowImage;
|
UIImage _defaultNavBarShadowImage;
|
||||||
UIImage _defaultNavBarBackImage;
|
UIImage _defaultNavBarBackImage;
|
||||||
|
|
||||||
public NavigationRenderer()
|
public NavigationRenderer() : base(typeof(FormsNavigationBar), null)
|
||||||
{
|
{
|
||||||
MessagingCenter.Subscribe<IVisualElementRenderer>(this, UpdateToolbarButtons, sender =>
|
MessagingCenter.Subscribe<IVisualElementRenderer>(this, UpdateToolbarButtons, sender =>
|
||||||
{
|
{
|
||||||
if (!ViewControllers.Any())
|
if (!ViewControllers.Any())
|
||||||
return;
|
return;
|
||||||
var parentingViewController = (ParentingViewController)ViewControllers.Last();
|
var parentingViewController = (ParentingViewController)ViewControllers.Last();
|
||||||
UpdateLeftBarButtonItem(parentingViewController);
|
parentingViewController?.UpdateLeftBarButtonItem();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
View.SetNeedsLayout();
|
View.SetNeedsLayout();
|
||||||
|
|
||||||
var parentingViewController = (ParentingViewController)ViewControllers.Last();
|
var parentingViewController = (ParentingViewController)ViewControllers.Last();
|
||||||
UpdateLeftBarButtonItem(parentingViewController);
|
parentingViewController?.UpdateLeftBarButtonItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> PopToRootAsync(Page page, bool animated = true)
|
public Task<bool> PopToRootAsync(Page page, bool animated = true)
|
||||||
|
@ -180,7 +180,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
|
|
||||||
double trueBottom = toolbar.Hidden ? toolbarY : toolbar.Frame.Bottom;
|
double trueBottom = toolbar.Hidden ? toolbarY : toolbar.Frame.Bottom;
|
||||||
var modelSize = _queuedSize.IsZero ? Element.Bounds.Size : _queuedSize;
|
var modelSize = _queuedSize.IsZero ? Element.Bounds.Size : _queuedSize;
|
||||||
PageController.ContainerArea =
|
PageController.ContainerArea =
|
||||||
new Rectangle(0, toolbar.Hidden ? 0 : toolbar.Frame.Height, modelSize.Width, modelSize.Height - trueBottom);
|
new Rectangle(0, toolbar.Hidden ? 0 : toolbar.Frame.Height, modelSize.Width, modelSize.Height - trueBottom);
|
||||||
|
|
||||||
if (!_queuedSize.IsZero)
|
if (!_queuedSize.IsZero)
|
||||||
|
@ -356,7 +356,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
// otherwise the view controller is forced to 0,0
|
// otherwise the view controller is forced to 0,0
|
||||||
var pack = new ParentingViewController(this) { Child = page };
|
var pack = new ParentingViewController(this) { Child = page };
|
||||||
|
|
||||||
UpdateTitleArea(pack, page);
|
pack.UpdateTitleArea(page);
|
||||||
|
|
||||||
var pageRenderer = Platform.GetRenderer(page);
|
var pageRenderer = Platform.GetRenderer(page);
|
||||||
pack.View.AddSubview(pageRenderer.ViewController.View);
|
pack.View.AddSubview(pageRenderer.ViewController.View);
|
||||||
|
@ -450,7 +450,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
|
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
|
||||||
{
|
{
|
||||||
var pack = (ParentingViewController)TopViewController;
|
var pack = (ParentingViewController)TopViewController;
|
||||||
UpdateTitleArea(pack, pack.Child);
|
pack?.UpdateTitleArea(pack.Child);
|
||||||
}
|
}
|
||||||
else if (e.PropertyName == HideNavigationBarSeparatorProperty.PropertyName)
|
else if (e.PropertyName == HideNavigationBarSeparatorProperty.PropertyName)
|
||||||
{
|
{
|
||||||
|
@ -462,7 +462,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
{
|
{
|
||||||
//if the last time we did ViewDidLayoutSubviews we had other value for _hasNavigationBar
|
//if the last time we did ViewDidLayoutSubviews we had other value for _hasNavigationBar
|
||||||
//we will need to relayout. This is because Current is updated async of the layout happening
|
//we will need to relayout. This is because Current is updated async of the layout happening
|
||||||
if(_hasNavigationBar != NavigationPage.GetHasNavigationBar(newCurrentPage))
|
if (_hasNavigationBar != NavigationPage.GetHasNavigationBar(newCurrentPage))
|
||||||
ViewDidLayoutSubviews();
|
ViewDidLayoutSubviews();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
NavigationBar.ShadowImage = _defaultNavBarShadowImage;
|
NavigationBar.ShadowImage = _defaultNavBarShadowImage;
|
||||||
|
|
||||||
if (!Forms.IsiOS11OrNewer)
|
if (!Forms.IsiOS11OrNewer)
|
||||||
{
|
{
|
||||||
// For iOS 10 and lower, you need to set the background image.
|
// For iOS 10 and lower, you need to set the background image.
|
||||||
// If you set this for iOS11, you'll remove the background color.
|
// If you set this for iOS11, you'll remove the background color.
|
||||||
if (_defaultNavBarBackImage == null)
|
if (_defaultNavBarBackImage == null)
|
||||||
|
@ -507,118 +507,6 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
NavigationBar.PrefersLargeTitles = NavPage.OnThisPlatform().PrefersLargeTitles();
|
NavigationBar.PrefersLargeTitles = NavPage.OnThisPlatform().PrefersLargeTitles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateTitleArea(ParentingViewController pack, Page page)
|
|
||||||
{
|
|
||||||
if (pack == null || page == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(page.Title))
|
|
||||||
pack.NavigationItem.Title = page.Title;
|
|
||||||
|
|
||||||
// First page and we have a master detail to contend with
|
|
||||||
UpdateLeftBarButtonItem(pack);
|
|
||||||
|
|
||||||
var titleText = NavigationPage.GetBackButtonTitle(page);
|
|
||||||
if (titleText != null)
|
|
||||||
{
|
|
||||||
// adding a custom event handler to UIBarButtonItem for navigating back seems to be ignored.
|
|
||||||
pack.NavigationItem.BackBarButtonItem = new UIBarButtonItem { Title = titleText, Style = UIBarButtonItemStyle.Plain };
|
|
||||||
}
|
|
||||||
|
|
||||||
FileImageSource titleIcon = NavigationPage.GetTitleIcon(page);
|
|
||||||
VisualElement titleView = NavigationPage.GetTitleView(page);
|
|
||||||
|
|
||||||
ClearTitleViewContainer(pack);
|
|
||||||
|
|
||||||
bool needContainer = titleView != null || titleIcon != null;
|
|
||||||
|
|
||||||
if (needContainer)
|
|
||||||
{
|
|
||||||
Container titleViewContainer = new Container();
|
|
||||||
|
|
||||||
pack.NavigationItem.TitleView = titleViewContainer;
|
|
||||||
|
|
||||||
UpdateTitleImage(titleViewContainer, titleIcon);
|
|
||||||
UpdateTitleView(titleViewContainer, titleView);
|
|
||||||
|
|
||||||
// Need to call this for iOS10 to properly frame the renderer
|
|
||||||
TopViewController?.NavigationItem?.TitleView?.SizeToFit();
|
|
||||||
TopViewController?.NavigationItem?.TitleView?.LayoutSubviews();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async void UpdateTitleImage(Container titleViewContainer, FileImageSource titleIcon)
|
|
||||||
{
|
|
||||||
if (titleViewContainer == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(titleIcon))
|
|
||||||
{
|
|
||||||
titleViewContainer.Icon = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var source = Internals.Registrar.Registered.GetHandlerForObject<IImageSourceHandler>(titleIcon);
|
|
||||||
var image = await source.LoadImageAsync(titleIcon);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
titleViewContainer.Icon = new UIImageView(image) { };
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
//UIImage ctor throws on file not found if MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure is true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearTitleViewContainer(UIViewController pack)
|
|
||||||
{
|
|
||||||
if (pack == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (pack.NavigationItem.TitleView != null && pack.NavigationItem.TitleView is Container titleViewContainer)
|
|
||||||
{
|
|
||||||
titleViewContainer.Dispose();
|
|
||||||
titleViewContainer = null;
|
|
||||||
pack.NavigationItem.TitleView = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateTitleView(Container titleViewContainer, VisualElement titleView)
|
|
||||||
{
|
|
||||||
if (titleViewContainer == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var titleViewRenderer = titleViewContainer.Child;
|
|
||||||
|
|
||||||
if (titleView != null)
|
|
||||||
{
|
|
||||||
if (titleViewRenderer != null)
|
|
||||||
{
|
|
||||||
var rendererType = titleViewRenderer is System.Reflection.IReflectableType reflectableType
|
|
||||||
? reflectableType.GetTypeInfo().AsType()
|
|
||||||
: titleViewRenderer.GetType();
|
|
||||||
|
|
||||||
if (titleView != null && rendererType == Internals.Registrar.Registered.GetHandlerTypeForObject(titleView))
|
|
||||||
{
|
|
||||||
if (titleViewContainer != null)
|
|
||||||
titleViewContainer.Child = null;
|
|
||||||
titleViewRenderer.SetElement(titleView);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
titleViewContainer?.DisposeChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
titleViewRenderer = Platform.CreateRenderer(titleView);
|
|
||||||
titleViewContainer.Child = titleViewRenderer;
|
|
||||||
}
|
|
||||||
else if (titleViewRenderer != null)
|
|
||||||
{
|
|
||||||
titleViewContainer?.DisposeChild();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateTranslucent()
|
void UpdateTranslucent()
|
||||||
{
|
{
|
||||||
NavigationBar.Translucent = NavPage.OnThisPlatform().IsNavigationBarTranslucent();
|
NavigationBar.Translucent = NavPage.OnThisPlatform().IsNavigationBarTranslucent();
|
||||||
|
@ -695,7 +583,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
ViewControllers = _removeControllers;
|
ViewControllers = _removeControllers;
|
||||||
}
|
}
|
||||||
var parentingViewController = ViewControllers.Last() as ParentingViewController;
|
var parentingViewController = ViewControllers.Last() as ParentingViewController;
|
||||||
UpdateLeftBarButtonItem(parentingViewController, page);
|
parentingViewController?.UpdateLeftBarButtonItem(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveViewControllers(bool animated)
|
void RemoveViewControllers(bool animated)
|
||||||
|
@ -794,17 +682,6 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateLeftBarButtonItem(ParentingViewController containerController, Page pageBeingRemoved = null)
|
|
||||||
{
|
|
||||||
if (containerController == null)
|
|
||||||
return;
|
|
||||||
var currentChild = containerController.Child;
|
|
||||||
var firstPage = NavPage.Pages.FirstOrDefault();
|
|
||||||
if ((firstPage != pageBeingRemoved && currentChild != firstPage && NavigationPage.GetHasBackButton(currentChild)) || _parentMasterDetailPage == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetMasterLeftBarButton(containerController, _parentMasterDetailPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateTint()
|
void UpdateTint()
|
||||||
{
|
{
|
||||||
|
@ -1103,10 +980,117 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
UpdateLargeTitles();
|
UpdateLargeTitles();
|
||||||
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName ||
|
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName ||
|
||||||
e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||||
|
UpdateTitleArea(Child);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal void UpdateLeftBarButtonItem(Page pageBeingRemoved = null)
|
||||||
|
{
|
||||||
|
NavigationRenderer n;
|
||||||
|
if (!_navigation.TryGetTarget(out n))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentChild = this.Child;
|
||||||
|
var firstPage = n.NavPage.Pages.FirstOrDefault();
|
||||||
|
|
||||||
|
|
||||||
|
if (n._parentMasterDetailPage == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (firstPage != pageBeingRemoved && currentChild != firstPage && NavigationPage.GetHasBackButton(currentChild))
|
||||||
|
{
|
||||||
|
NavigationItem.LeftBarButtonItem = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMasterLeftBarButton(this, n._parentMasterDetailPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool NeedsTitleViewContainer(Page page) => NavigationPage.GetTitleIcon(page) != null || NavigationPage.GetTitleView(page) != null;
|
||||||
|
|
||||||
|
internal void UpdateBackButtonTitle(Page page) => UpdateBackButtonTitle(page.Title, NavigationPage.GetBackButtonTitle(page));
|
||||||
|
|
||||||
|
internal void UpdateBackButtonTitle(string title, string backButtonTitle)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(title))
|
||||||
|
NavigationItem.Title = title;
|
||||||
|
|
||||||
|
if (backButtonTitle != null)
|
||||||
|
// adding a custom event handler to UIBarButtonItem for navigating back seems to be ignored.
|
||||||
|
NavigationItem.BackBarButtonItem = new UIBarButtonItem { Title = backButtonTitle, Style = UIBarButtonItemStyle.Plain };
|
||||||
|
else
|
||||||
|
NavigationItem.BackBarButtonItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UpdateTitleArea(Page page)
|
||||||
|
{
|
||||||
|
if (page == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FileImageSource titleIcon = NavigationPage.GetTitleIcon(page);
|
||||||
|
View titleView = NavigationPage.GetTitleView(page);
|
||||||
|
bool needContainer = titleView != null || titleIcon != null;
|
||||||
|
|
||||||
|
string backButtonText = NavigationPage.GetBackButtonTitle(page);
|
||||||
|
bool isBackButtonTextSet = page.IsSet(NavigationPage.BackButtonTitleProperty);
|
||||||
|
|
||||||
|
// on iOS 10 if the user hasn't set the back button text
|
||||||
|
// we set it to an empty string so it's consistent with iOS 11
|
||||||
|
if (!Forms.IsiOS11OrNewer && !isBackButtonTextSet)
|
||||||
|
backButtonText = "";
|
||||||
|
|
||||||
|
// First page and we have a master detail to contend with
|
||||||
|
UpdateLeftBarButtonItem();
|
||||||
|
UpdateBackButtonTitle(page.Title, backButtonText);
|
||||||
|
|
||||||
|
//var hadTitleView = NavigationItem.TitleView != null;
|
||||||
|
ClearTitleViewContainer();
|
||||||
|
if (needContainer)
|
||||||
{
|
{
|
||||||
NavigationRenderer n;
|
NavigationRenderer n;
|
||||||
if (_navigation.TryGetTarget(out n))
|
if (!_navigation.TryGetTarget(out n))
|
||||||
n.UpdateTitleArea(this, Child);
|
return;
|
||||||
|
|
||||||
|
Container titleViewContainer = new Container(titleView, n.NavigationBar);
|
||||||
|
|
||||||
|
UpdateTitleImage(titleViewContainer, titleIcon);
|
||||||
|
NavigationItem.TitleView = titleViewContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async void UpdateTitleImage(Container titleViewContainer, FileImageSource titleIcon)
|
||||||
|
{
|
||||||
|
if (titleViewContainer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(titleIcon))
|
||||||
|
{
|
||||||
|
titleViewContainer.Icon = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var source = Internals.Registrar.Registered.GetHandlerForObject<IImageSourceHandler>(titleIcon);
|
||||||
|
var image = await source.LoadImageAsync(titleIcon);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
titleViewContainer.Icon = new UIImageView(image) { };
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//UIImage ctor throws on file not found if MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure is true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearTitleViewContainer()
|
||||||
|
{
|
||||||
|
if (NavigationItem.TitleView != null && NavigationItem.TitleView is Container titleViewContainer)
|
||||||
|
{
|
||||||
|
titleViewContainer.Dispose();
|
||||||
|
titleViewContainer = null;
|
||||||
|
NavigationItem.TitleView = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,10 +1107,17 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
|
|
||||||
void UpdateHasBackButton()
|
void UpdateHasBackButton()
|
||||||
{
|
{
|
||||||
if (Child == null)
|
if (Child == null || NavigationItem.HidesBackButton == !NavigationPage.GetHasBackButton(Child))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NavigationItem.HidesBackButton = !NavigationPage.GetHasBackButton(Child);
|
NavigationItem.HidesBackButton = !NavigationPage.GetHasBackButton(Child);
|
||||||
|
|
||||||
|
NavigationRenderer n;
|
||||||
|
if (!_navigation.TryGetTarget(out n))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!Forms.IsiOS11OrNewer || n._parentMasterDetailPage != null)
|
||||||
|
UpdateTitleArea(Child);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateNavigationBarVisibility(bool animated)
|
void UpdateNavigationBarVisibility(bool animated)
|
||||||
|
@ -1257,25 +1248,136 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
VisualElementRenderer<VisualElement>.RegisterEffect(effect, View);
|
VisualElementRenderer<VisualElement>.RegisterEffect(effect, View);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class FormsNavigationBar : UINavigationBar
|
||||||
|
{
|
||||||
|
public FormsNavigationBar() : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormsNavigationBar(Foundation.NSCoder coder) : base(coder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FormsNavigationBar(Foundation.NSObjectFlag t) : base(t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal FormsNavigationBar(IntPtr handle) : base(handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormsNavigationBar(RectangleF frame) : base(frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public RectangleF BackButtonFrameSize { get; private set; }
|
||||||
|
public UILabel NavBarLabel { get; private set; }
|
||||||
|
|
||||||
|
public override void LayoutSubviews()
|
||||||
|
{
|
||||||
|
if (!Forms.IsiOS11OrNewer)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < this.Subviews.Length; i++)
|
||||||
|
{
|
||||||
|
if (Subviews[i] is UIView view)
|
||||||
|
{
|
||||||
|
if (view.Class.Name == "_UINavigationBarBackIndicatorView")
|
||||||
|
{
|
||||||
|
if (view.Alpha == 0)
|
||||||
|
BackButtonFrameSize = CGRect.Empty;
|
||||||
|
else
|
||||||
|
BackButtonFrameSize = view.Frame;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(view.Class.Name == "UINavigationItemButtonView")
|
||||||
|
{
|
||||||
|
if (view.Subviews.Length == 0)
|
||||||
|
NavBarLabel = null;
|
||||||
|
else if (view.Subviews[0] is UILabel titleLabel)
|
||||||
|
NavBarLabel = titleLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.LayoutSubviews();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Container : UIView
|
class Container : UIView
|
||||||
{
|
{
|
||||||
|
View _view;
|
||||||
|
FormsNavigationBar _bar;
|
||||||
IVisualElementRenderer _child;
|
IVisualElementRenderer _child;
|
||||||
UIImageView _icon;
|
UIImageView _icon;
|
||||||
|
|
||||||
nfloat IconHeight => _icon?.Frame.Height ?? 0;
|
public Container(View view, UINavigationBar bar) : base(bar.Bounds)
|
||||||
|
{
|
||||||
|
if (Forms.IsiOS11OrNewer)
|
||||||
|
{
|
||||||
|
TranslatesAutoresizingMaskIntoConstraints = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TranslatesAutoresizingMaskIntoConstraints = true;
|
||||||
|
AutoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
_bar = bar as FormsNavigationBar;
|
||||||
|
if (view != null)
|
||||||
|
{
|
||||||
|
_view = view;
|
||||||
|
_child = Platform.CreateRenderer(view);
|
||||||
|
Platform.SetRenderer(view, _child);
|
||||||
|
AddSubview(_child.NativeView);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipsToBounds = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override CGSize IntrinsicContentSize => UILayoutFittingExpandedSize;
|
||||||
|
|
||||||
|
nfloat IconHeight => _icon?.Frame.Height ?? 0;
|
||||||
nfloat IconWidth => _icon?.Frame.Width ?? 0;
|
nfloat IconWidth => _icon?.Frame.Width ?? 0;
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
// Navigation bar will not stretch past these values. Prevent content clipping.
|
||||||
|
// iOS11 does this for us automatically, but apparently iOS10 doesn't.
|
||||||
|
nfloat ToolbarHeight
|
||||||
{
|
{
|
||||||
if (disposing)
|
get
|
||||||
{
|
{
|
||||||
DisposeChild();
|
if (Superview?.Bounds.Height > 0)
|
||||||
|
return Superview.Bounds.Height;
|
||||||
|
|
||||||
_icon?.Dispose();
|
return (Device.Idiom == TargetIdiom.Phone && Device.Info.CurrentOrientation.IsLandscape()) ? 32 : 44;
|
||||||
_icon = null;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override CGRect Frame
|
||||||
|
{
|
||||||
|
get => base.Frame;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Superview != null)
|
||||||
|
{
|
||||||
|
if (!Forms.IsiOS11OrNewer)
|
||||||
|
{
|
||||||
|
value.Y = Superview.Bounds.Y;
|
||||||
|
|
||||||
|
if (_bar != null && String.IsNullOrWhiteSpace(_bar.NavBarLabel?.Text) && _bar.BackButtonFrameSize != RectangleF.Empty)
|
||||||
|
{
|
||||||
|
var xSpace = _bar.BackButtonFrameSize.Width + (_bar.BackButtonFrameSize.X * 2);
|
||||||
|
value.Width = (value.X - xSpace) + value.Width;
|
||||||
|
value.X = xSpace;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
value.Height = ToolbarHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Frame = value;
|
||||||
}
|
}
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UIImageView Icon
|
public UIImageView Icon
|
||||||
|
@ -1292,65 +1394,53 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IVisualElementRenderer Child
|
|
||||||
{
|
|
||||||
get { return _child; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_child != null)
|
|
||||||
DisposeChild();
|
|
||||||
|
|
||||||
_child = value;
|
|
||||||
|
|
||||||
if (value != null)
|
|
||||||
AddSubview(value.NativeView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override SizeF SizeThatFits(SizeF size)
|
public override SizeF SizeThatFits(SizeF size)
|
||||||
{
|
{
|
||||||
IVisualElementRenderer renderer = _child;
|
return new SizeF(size.Width, ToolbarHeight);
|
||||||
|
|
||||||
if (renderer == null || renderer.Element == null || renderer.Element.Parent == null)
|
|
||||||
return new SizeF(IconWidth, IconHeight);
|
|
||||||
|
|
||||||
var result = renderer.Element.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
|
|
||||||
|
|
||||||
return new SizeF(result.Request.Width + IconWidth, Math.Max(IconHeight, result.Request.Height));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LayoutSubviews()
|
public override void LayoutSubviews()
|
||||||
{
|
{
|
||||||
base.LayoutSubviews();
|
base.LayoutSubviews();
|
||||||
|
if (Frame == CGRect.Empty || Frame.Width >= 10000 || Frame.Height >= 10000)
|
||||||
|
return;
|
||||||
|
|
||||||
// Navigation bar will not stretch past these values. Prevent content clipping.
|
nfloat toolbarHeight = ToolbarHeight;
|
||||||
// iOS11 does this for us automatically, but apparently iOS10 doesn't.
|
|
||||||
int toolbarHeight = 44;
|
|
||||||
if (Device.Idiom == TargetIdiom.Phone && Device.Info.CurrentOrientation.IsLandscape())
|
|
||||||
toolbarHeight = 32;
|
|
||||||
|
|
||||||
double height = Math.Min(toolbarHeight, Bounds.Height);
|
double height = Math.Min(toolbarHeight, Bounds.Height);
|
||||||
|
|
||||||
Frame = new RectangleF(Frame.X, Frame.Y, Bounds.Width, height);
|
|
||||||
|
|
||||||
if (_icon != null)
|
if (_icon != null)
|
||||||
_icon.Frame = new RectangleF(0, 0, IconWidth, Math.Min(toolbarHeight, IconHeight));
|
_icon.Frame = new RectangleF(0, 0, IconWidth, Math.Min(toolbarHeight, IconHeight));
|
||||||
|
|
||||||
if (_child?.Element != null)
|
if (_child?.Element != null)
|
||||||
Layout.LayoutChildIntoBoundingRegion(_child.Element, new Rectangle(IconWidth, 0, Bounds.Width - IconWidth, height));
|
{
|
||||||
|
var layoutBounds = new Rectangle(IconWidth, 0, Bounds.Width - IconWidth, height);
|
||||||
|
if (_child.Element.Bounds != layoutBounds)
|
||||||
|
Layout.LayoutChildIntoBoundingRegion(_child.Element, layoutBounds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeChild()
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (_child == null)
|
if (disposing)
|
||||||
return;
|
{
|
||||||
|
|
||||||
if (_child.Element.Platform is Platform platform)
|
if (_child != null)
|
||||||
platform.DisposeModelAndChildrenRenderers(_child.Element);
|
{
|
||||||
|
if (_child.Element.Platform is Platform platform)
|
||||||
|
platform.DisposeModelAndChildrenRenderers(_child.Element);
|
||||||
|
|
||||||
_child.NativeView.RemoveFromSuperview();
|
_child.NativeView.RemoveFromSuperview();
|
||||||
_child.Dispose();
|
_child.Dispose();
|
||||||
_child = null;
|
_child = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_view = null;
|
||||||
|
|
||||||
|
_icon?.Dispose();
|
||||||
|
_icon = null;
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче