зеркало из https://github.com/DeGsoft/maui-linux.git
TitleView (#2586)
* Stop crashing when I accidentally click on the Perf gallery * [Core] Add TitleView to NavigationPage - also add unit tests - fixes #1716 * [Android] Add ClearRenderer static method to Platform * [Android] Use Platform.ClearRenderer it's a straight extract from this class * [Android] Implement TitleView and TitleIcon on AppCompat backend using lessons (and some duplicated code) from ListView header/footer views. * [iOS] Implement TitleView * [UWP] Implement TitleIcon and TitleView * [Core] Add NavigationPage.BarHeight * [Android] Use BarHeight * NavigationBarGallery updates * [Core] Add iOS HideNavigationBarSeparator Platform Specific * [iOS] Implement HideNavigationBarSeparator Platform Specific * sample search page * Convert BarHeight to Android platform specific * Reset BarHeight when leaving the gallery * Add a sample TitleView xaml page * VisualElement >> View * Fix comment * Improved SearchTitle sample page * [Core] Set TitleView Parent on Changing instead of Changed Changing is too late for the iOS layout * [iOS] Fix layouts in iOS10 * [iOS] Stop content clipping * Expanded test page * [iOS] Fix HideNavigationBarSeparator for iOS<11 * [iOS] Layout TitleView with margins * More tweaks to test page * [UWP] Fix OnDetailPropertyChanged if/else * [UWP] Comment empty setters * Convert commented code to more useful comment. * Adjust performance test async call
This commit is contained in:
Родитель
40bee5c012
Коммит
4d5a1f5482
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using UIKit;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.ControlGallery.iOS;
|
||||
using Xamarin.Forms.Platform.iOS;
|
||||
|
||||
[assembly: ExportEffect(typeof(SearchbarEffect), "SearchbarEffect")]
|
||||
namespace Xamarin.Forms.ControlGallery.iOS
|
||||
{
|
||||
public class SearchbarEffect : PlatformEffect
|
||||
{
|
||||
UIColor _defaultBackColor;
|
||||
UIColor _defaultTintColor;
|
||||
UIImage _defaultBackImage;
|
||||
protected override void OnAttached()
|
||||
{
|
||||
if (_defaultBackColor == null)
|
||||
_defaultBackColor = Control.BackgroundColor;
|
||||
|
||||
Control.BackgroundColor = Color.Cornsilk.ToUIColor();
|
||||
|
||||
if (Control is UISearchBar searchBar)
|
||||
{
|
||||
if (_defaultTintColor == null)
|
||||
_defaultTintColor = searchBar.BarTintColor;
|
||||
|
||||
if (_defaultBackImage == null)
|
||||
_defaultBackImage = searchBar.BackgroundImage;
|
||||
|
||||
searchBar.BarTintColor = Color.Goldenrod.ToUIColor();
|
||||
searchBar.BackgroundImage = new UIImage();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetached()
|
||||
{
|
||||
Control.BackgroundColor = _defaultBackColor;
|
||||
|
||||
if (Control is UISearchBar searchBar)
|
||||
{
|
||||
searchBar.BarTintColor = _defaultTintColor;
|
||||
searchBar.BackgroundImage = _defaultBackImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,6 +104,7 @@
|
|||
<Compile Include="AttachedStateEffectRenderer.cs" />
|
||||
<Compile Include="BrokenImageSourceHandler.cs" />
|
||||
<Compile Include="BrokenNativeControl.cs" />
|
||||
<Compile Include="SearchbarEffect.cs" />
|
||||
<Compile Include="CustomRenderer40251.cs" />
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="AppDelegate.cs" />
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
|||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.UITest;
|
||||
|
@ -43,7 +44,7 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
|
||||
PerformanceViewModel ViewModel => BindingContext as PerformanceViewModel;
|
||||
|
||||
protected override async void Init()
|
||||
protected override void Init()
|
||||
{
|
||||
_BuildInfo = GetBuildNumber();
|
||||
|
||||
|
@ -82,7 +83,7 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
|
||||
Content = new StackLayout { Children = { testRunRef, nextButton, _PerformanceTracker } };
|
||||
|
||||
ViewModel.BenchmarkResults = await PerformanceDataManager.GetScenarioResults(_DeviceIdentifier);
|
||||
ViewModel.BenchmarkResults = Task.Run(() => PerformanceDataManager.GetScenarioResults(_DeviceIdentifier)).GetAwaiter().GetResult();
|
||||
|
||||
nextButton.IsEnabled = true;
|
||||
nextButton.Text = Next;
|
||||
|
|
|
@ -384,9 +384,10 @@ namespace Xamarin.Forms.Controls
|
|||
_titleToPage = _pages.ToDictionary(o => o.Title);
|
||||
|
||||
// avoid NRE for root pages without NavigationBar
|
||||
if (navigationBehavior == NavigationBehavior.PushAsync && rootPage.GetType() == typeof(CoreNavigationPage))
|
||||
if (navigationBehavior == NavigationBehavior.PushAsync && rootPage.GetType () == typeof (CoreNavigationPage))
|
||||
{
|
||||
_pages.Add(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"));
|
||||
}
|
||||
|
||||
var template = new DataTemplate(typeof(TextCell));
|
||||
|
|
|
@ -1,64 +1,326 @@
|
|||
using System.Diagnostics;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms.PlatformConfiguration;
|
||||
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
|
||||
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat;
|
||||
using static Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage;
|
||||
namespace Xamarin.Forms.Controls
|
||||
{
|
||||
public class NavigationBarGallery : ContentPage
|
||||
{
|
||||
public NavigationBarGallery (NavigationPage rootNavPage)
|
||||
NavigationPage _rootNavPage;
|
||||
public NavigationBarGallery(NavigationPage rootNavPage)
|
||||
{
|
||||
_rootNavPage = rootNavPage;
|
||||
|
||||
int toggleBarTextColor = 0;
|
||||
int toggleBarBackgroundColor = 0;
|
||||
|
||||
Content = new StackLayout {
|
||||
Children = {
|
||||
new Button {
|
||||
Text = "Change BarTextColor",
|
||||
Command = new Command (() => {
|
||||
if (toggleBarTextColor % 2 == 0) {
|
||||
rootNavPage.BarTextColor = Color.Teal;
|
||||
} else {
|
||||
rootNavPage.BarTextColor = Color.Default;
|
||||
}
|
||||
toggleBarTextColor++;
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Change BarBackgroundColor",
|
||||
Command = new Command (() => {
|
||||
if (toggleBarBackgroundColor % 2 == 0) {
|
||||
rootNavPage.BarBackgroundColor = Color.Navy;
|
||||
} else {
|
||||
rootNavPage.BarBackgroundColor = Color.Default;
|
||||
}
|
||||
toggleBarBackgroundColor++;
|
||||
ToolbarItems.Add(new ToolbarItem { Text = "Save" });
|
||||
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Change Both to default",
|
||||
Command = new Command (() => {
|
||||
rootNavPage.BarTextColor = Color.Default;
|
||||
rootNavPage.BarBackgroundColor = Color.Default;
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Make sure Tint still works",
|
||||
Command = new Command (() => {
|
||||
#pragma warning disable 618
|
||||
rootNavPage.Tint = Color.Red;
|
||||
#pragma warning restore 618
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Black background, white text",
|
||||
Command = new Command (() => {
|
||||
rootNavPage.BarTextColor = Color.White;
|
||||
rootNavPage.BarBackgroundColor = Color.Black;
|
||||
})
|
||||
NavigationPage.SetTitleIcon(this, "coffee.png");
|
||||
|
||||
SearchBar searchBar = new SearchBar { HeightRequest = 44, WidthRequest = 100 };
|
||||
|
||||
// Note: Large and complex controls, such as ListView and TableView, are not recommended.
|
||||
var controls = new List<View>
|
||||
{
|
||||
searchBar,
|
||||
new ActivityIndicator{ IsRunning = true },
|
||||
new BoxView{ BackgroundColor = Color.Red },
|
||||
new Button{ Text = "Button!"},
|
||||
new DatePicker{},
|
||||
new Editor{ Text = "Editor"},
|
||||
new Entry{ Placeholder = "Entry"},
|
||||
new Image{ Source = "crimson.jpg", HeightRequest = 44 },
|
||||
new Label{ Text = "Title View Label!" },
|
||||
new Picker{ ItemsSource = Enumerable.Range(0,10).Select(i => $"Item {i}").ToList(), Title = "Picker" },
|
||||
new ProgressBar{ Progress = 50 },
|
||||
new Slider{},
|
||||
new Stepper{},
|
||||
new Switch{},
|
||||
new TimePicker{}
|
||||
};
|
||||
|
||||
int idx = 0;
|
||||
|
||||
NavigationPage.SetTitleView(this, CreateTitleView(controls[idx]));
|
||||
|
||||
rootNavPage.On<Android>().SetBarHeight(450);
|
||||
rootNavPage.On<iOS>().SetPrefersLargeTitles(false);
|
||||
|
||||
Content = new ScrollView
|
||||
{
|
||||
Content =
|
||||
new StackLayout
|
||||
{
|
||||
Children = {
|
||||
new Button {
|
||||
Text = "Go to SearchBarTitlePage",
|
||||
Command = new Command (() => {
|
||||
rootNavPage.PushAsync(new SearchBarTitlePage(rootNavPage));
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Change BarTextColor",
|
||||
Command = new Command (() => {
|
||||
if (toggleBarTextColor % 2 == 0) {
|
||||
rootNavPage.BarTextColor = Color.Teal;
|
||||
} else {
|
||||
rootNavPage.BarTextColor = Color.Default;
|
||||
}
|
||||
toggleBarTextColor++;
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Change BarBackgroundColor",
|
||||
Command = new Command (() => {
|
||||
if (toggleBarBackgroundColor % 2 == 0) {
|
||||
rootNavPage.BarBackgroundColor = Color.Navy;
|
||||
} else {
|
||||
rootNavPage.BarBackgroundColor = Color.Default;
|
||||
}
|
||||
toggleBarBackgroundColor++;
|
||||
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Change Both to default",
|
||||
Command = new Command (() => {
|
||||
rootNavPage.BarTextColor = Color.Default;
|
||||
rootNavPage.BarBackgroundColor = Color.Default;
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Make sure Tint still works",
|
||||
Command = new Command (() => {
|
||||
#pragma warning disable 618
|
||||
rootNavPage.Tint = Color.Red;
|
||||
#pragma warning restore 618
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Black background, white text",
|
||||
Command = new Command (() => {
|
||||
rootNavPage.BarTextColor = Color.White;
|
||||
rootNavPage.BarBackgroundColor = Color.Black;
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Toggle TitleIcon",
|
||||
Command = new Command (() => {
|
||||
|
||||
var titleIcon = NavigationPage.GetTitleIcon(this);
|
||||
|
||||
if (titleIcon == null)
|
||||
titleIcon = "coffee.png";
|
||||
else
|
||||
titleIcon = null;
|
||||
|
||||
NavigationPage.SetTitleIcon(this, titleIcon);
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Toggle TitleView",
|
||||
Command = new Command (() => {
|
||||
|
||||
var titleView = NavigationPage.GetTitleView(this);
|
||||
|
||||
if (titleView == null)
|
||||
titleView = CreateTitleView(controls[idx]);
|
||||
else
|
||||
titleView = null;
|
||||
|
||||
NavigationPage.SetTitleView(this, titleView);
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Next TitleView",
|
||||
Command = new Command (() => {
|
||||
|
||||
idx++;
|
||||
if(idx >=controls.Count)
|
||||
idx = 0;
|
||||
|
||||
var titleView = CreateTitleView(controls[idx]);
|
||||
|
||||
NavigationPage.SetTitleView(this, titleView);
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Toggle Back Title",
|
||||
Command = new Command (() => {
|
||||
|
||||
var backTitle = NavigationPage.GetBackButtonTitle(rootNavPage);
|
||||
|
||||
if (backTitle == null)
|
||||
backTitle= "Go back home";
|
||||
else
|
||||
backTitle = null;
|
||||
|
||||
NavigationPage.SetBackButtonTitle(rootNavPage, backTitle);
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Toggle Toolbar Item",
|
||||
Command = new Command (() => {
|
||||
|
||||
if (ToolbarItems.Count > 0)
|
||||
ToolbarItems.Clear();
|
||||
else
|
||||
ToolbarItems.Add(new ToolbarItem { Text = "Save" });
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Toggle Title",
|
||||
Command = new Command (() => {
|
||||
|
||||
if (Title == null)
|
||||
Title = "NavigationBar Gallery - Legacy";
|
||||
else
|
||||
Title = null;
|
||||
})
|
||||
},
|
||||
new Button {
|
||||
Text = "Toggle BarHeight",
|
||||
Command = new Command (() => {
|
||||
|
||||
if (rootNavPage.On<Android>().GetBarHeight() == -1)
|
||||
rootNavPage.On<Android>().SetBarHeight(450);
|
||||
else
|
||||
rootNavPage.ClearValue(BarHeightProperty);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
base.OnDisappearing();
|
||||
_rootNavPage.ClearValue(BarHeightProperty);
|
||||
}
|
||||
|
||||
static View CreateTitleView(View control)
|
||||
{
|
||||
control.HorizontalOptions = LayoutOptions.Fill;
|
||||
control.VerticalOptions = LayoutOptions.CenterAndExpand;
|
||||
|
||||
var titleView = new StackLayout
|
||||
{
|
||||
Children = { control },
|
||||
BackgroundColor = Color.FromHex("#ccc"),
|
||||
Margin = new Thickness(15, 0),
|
||||
};
|
||||
return titleView;
|
||||
}
|
||||
|
||||
class SearchBarTitlePage : ContentPage
|
||||
{
|
||||
bool _extended = false;
|
||||
List<string> items = new List<string> { "The Ocean at the End of the Lane", "So Long, and Thanks for All the Fish", "Twenty Thousand Leagues Under the Sea", "Rosencrantz and Guildenstern Are Dead" };
|
||||
ObservableCollection<string> filtereditems;
|
||||
SearchBar search;
|
||||
Button button;
|
||||
ListView list;
|
||||
public SearchBarTitlePage(NavigationPage parent)
|
||||
{
|
||||
filtereditems = new ObservableCollection<string>(items);
|
||||
|
||||
search = new SearchBar { BackgroundColor = Color.Cornsilk, HorizontalOptions = LayoutOptions.FillAndExpand, Margin = new Thickness(10, 0) };
|
||||
search.Effects.Add(Effect.Resolve($"{Issues.Effects.ResolutionGroupName}.SearchbarEffect"));
|
||||
search.TextChanged += Search_TextChanged;
|
||||
|
||||
list = new ListView
|
||||
{
|
||||
ItemsSource = filtereditems
|
||||
};
|
||||
|
||||
parent.BarBackgroundColor = Color.Cornsilk;
|
||||
parent.BarTextColor = Color.Orange;
|
||||
NavigationPage.SetBackButtonTitle(parent, "");
|
||||
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
|
||||
button = new Button();
|
||||
|
||||
button.Clicked += (s, e) =>
|
||||
{
|
||||
ToggleContent(parent);
|
||||
};
|
||||
|
||||
ToggleContent(parent);
|
||||
break;
|
||||
|
||||
default:
|
||||
NavigationPage.SetTitleView(this, search);
|
||||
Content = list;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleContent(NavigationPage parent)
|
||||
{
|
||||
StackLayout topStack = new StackLayout { Children = { button }, BackgroundColor = Color.Cornsilk };
|
||||
StackLayout layout = new StackLayout { Children = { topStack, list } };
|
||||
|
||||
if (_extended)
|
||||
{
|
||||
parent.On<iOS>().SetPrefersLargeTitles(false)
|
||||
.SetHideNavigationBarSeparator(false);
|
||||
|
||||
NavigationPage.SetTitleView(this, new StackLayout { Children = { search }, HorizontalOptions = LayoutOptions.Fill });
|
||||
NavigationPage.SetHasBackButton(this, false);
|
||||
|
||||
button.Text = "Expand";
|
||||
Title = "Small Titles";
|
||||
}
|
||||
else
|
||||
{
|
||||
topStack.Children.Insert(0, search);
|
||||
|
||||
parent.On<iOS>().SetPrefersLargeTitles(true)
|
||||
.SetHideNavigationBarSeparator(true);
|
||||
|
||||
ClearValue(NavigationPage.TitleViewProperty);
|
||||
NavigationPage.SetHasBackButton(this, true);
|
||||
|
||||
button.Text = "Collapse";
|
||||
Title = "Large Titles";
|
||||
}
|
||||
|
||||
_extended = !_extended;
|
||||
Content = layout;
|
||||
}
|
||||
|
||||
void Search_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
for (int i = 0; i < filtereditems.Count; i++)
|
||||
{
|
||||
filtereditems.RemoveAt(0);
|
||||
}
|
||||
|
||||
if (search.Text?.Length >= 3)
|
||||
{
|
||||
foreach (var item in items.Where(i => i.ToLower().Contains(search.Text.ToLower())))
|
||||
{
|
||||
if (!filtereditems.Contains(item))
|
||||
filtereditems.Add(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
else
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (!filtereditems.Contains(item))
|
||||
filtereditems.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Xamarin.Forms.Controls.GalleryPages.TitleView">
|
||||
|
||||
<NavigationPage.TitleView>
|
||||
<StackLayout>
|
||||
<Label Text="This is my TitleView" />
|
||||
<Label Text="I can be a subtitle" />
|
||||
</StackLayout>
|
||||
</NavigationPage.TitleView>
|
||||
|
||||
<StackLayout>
|
||||
<Label Text="Welcome to Xamarin.Forms!"
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="CenterAndExpand" />
|
||||
</StackLayout>
|
||||
|
||||
</ContentPage>
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace Xamarin.Forms.Controls.GalleryPages
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class TitleView : ContentPage
|
||||
{
|
||||
public TitleView ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,9 @@
|
|||
<Compile Update="GalleryPages\VisualStateManagerGalleries\OnPlatformExample.xaml.cs">
|
||||
<DependentUpon>OnPlatformExample.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Update="GalleryPages\TitleView.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="GalleryPages\VisualStateManagerGalleries\ButtonDisabledStatesGallery.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
|
|
|
@ -338,6 +338,49 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TitleViewSetProperty()
|
||||
{
|
||||
var root = new ContentPage();
|
||||
var nav = new NavigationPage(root);
|
||||
|
||||
View target = new View();
|
||||
|
||||
NavigationPage.SetTitleView(root, target);
|
||||
|
||||
var result = NavigationPage.GetTitleView(root);
|
||||
|
||||
Assert.AreSame(result, target);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TitleViewSetsParentWhenAdded()
|
||||
{
|
||||
var root = new ContentPage();
|
||||
var nav = new NavigationPage(root);
|
||||
|
||||
View target = new View();
|
||||
|
||||
NavigationPage.SetTitleView(root, target);
|
||||
|
||||
Assert.AreSame(root, target.Parent);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TitleViewClearsParentWhenRemoved()
|
||||
{
|
||||
var root = new ContentPage();
|
||||
var nav = new NavigationPage(root);
|
||||
|
||||
View target = new View();
|
||||
|
||||
NavigationPage.SetTitleView(root, target);
|
||||
|
||||
NavigationPage.SetTitleView(root, null);
|
||||
|
||||
Assert.IsNull(target.Parent);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task NavigationChangedEventArgs ()
|
||||
{
|
||||
|
|
|
@ -27,6 +27,8 @@ namespace Xamarin.Forms
|
|||
|
||||
public static readonly BindableProperty TitleIconProperty = BindableProperty.CreateAttached("TitleIcon", typeof(FileImageSource), typeof(NavigationPage), default(FileImageSource));
|
||||
|
||||
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);
|
||||
public static readonly BindableProperty CurrentPageProperty = CurrentPagePropertyKey.BindableProperty;
|
||||
|
||||
|
@ -103,6 +105,24 @@ namespace Xamarin.Forms
|
|||
private set { SetValue(RootPagePropertyKey, value); }
|
||||
}
|
||||
|
||||
static void TitleViewPropertyChanging(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (oldValue == newValue)
|
||||
return;
|
||||
|
||||
if (oldValue != null)
|
||||
{
|
||||
var oldElem = (View)oldValue;
|
||||
oldElem.Parent = null;
|
||||
}
|
||||
|
||||
if (newValue != null && bindable != null)
|
||||
{
|
||||
var newElem = (View)newValue;
|
||||
newElem.Parent = (Page)bindable;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetBackButtonTitle(BindableObject page)
|
||||
{
|
||||
return (string)page.GetValue(BackButtonTitleProperty);
|
||||
|
@ -125,6 +145,11 @@ namespace Xamarin.Forms
|
|||
return (FileImageSource)bindable.GetValue(TitleIconProperty);
|
||||
}
|
||||
|
||||
public static View GetTitleView(BindableObject bindable)
|
||||
{
|
||||
return (View)bindable.GetValue(TitleViewProperty);
|
||||
}
|
||||
|
||||
public Task<Page> PopAsync()
|
||||
{
|
||||
return PopAsync(true);
|
||||
|
@ -222,6 +247,11 @@ namespace Xamarin.Forms
|
|||
bindable.SetValue(TitleIconProperty, value);
|
||||
}
|
||||
|
||||
public static void SetTitleView(BindableObject bindable, View value)
|
||||
{
|
||||
bindable.SetValue(TitleViewProperty, value);
|
||||
}
|
||||
|
||||
protected override bool OnBackButtonPressed()
|
||||
{
|
||||
if (CurrentPage.SendBackButtonPressed())
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
namespace Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat
|
||||
{
|
||||
using FormsElement = Forms.NavigationPage;
|
||||
|
||||
public static class NavigationPage
|
||||
{
|
||||
public static readonly BindableProperty BarHeightProperty = BindableProperty.Create("BarHeight", typeof(int), typeof(NavigationPage), default(int));
|
||||
|
||||
public static int GetBarHeight(BindableObject element)
|
||||
{
|
||||
return (int)element.GetValue(BarHeightProperty);
|
||||
}
|
||||
|
||||
public static void SetBarHeight(BindableObject element, int value)
|
||||
{
|
||||
element.SetValue(BarHeightProperty, value);
|
||||
}
|
||||
|
||||
public static int GetBarHeight(this IPlatformElementConfiguration<Android, FormsElement> config)
|
||||
{
|
||||
return GetBarHeight(config.Element);
|
||||
}
|
||||
|
||||
public static IPlatformElementConfiguration<Android, FormsElement> SetBarHeight(this IPlatformElementConfiguration<Android, FormsElement> config, int value)
|
||||
{
|
||||
SetBarHeight(config.Element, value);
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -72,6 +72,7 @@ namespace Xamarin.Forms.PlatformConfiguration.iOSSpecific
|
|||
}
|
||||
#endregion
|
||||
|
||||
#region PrefersLargeTitles
|
||||
public static readonly BindableProperty PrefersLargeTitlesProperty = BindableProperty.Create(nameof(PrefersLargeTitles), typeof(bool), typeof(Page), false);
|
||||
|
||||
public static bool GetPrefersLargeTitles(BindableObject element)
|
||||
|
@ -94,5 +95,31 @@ namespace Xamarin.Forms.PlatformConfiguration.iOSSpecific
|
|||
{
|
||||
return GetPrefersLargeTitles(config.Element);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HideNavigationBarSeparator
|
||||
public static readonly BindableProperty HideNavigationBarSeparatorProperty = BindableProperty.Create(nameof(HideNavigationBarSeparator), typeof(bool), typeof(Page), false);
|
||||
|
||||
public static bool GetHideNavigationBarSeparator(BindableObject element)
|
||||
{
|
||||
return (bool)element.GetValue(HideNavigationBarSeparatorProperty);
|
||||
}
|
||||
|
||||
public static void SetHideNavigationBarSeparator(BindableObject element, bool value)
|
||||
{
|
||||
element.SetValue(HideNavigationBarSeparatorProperty, value);
|
||||
}
|
||||
|
||||
public static IPlatformElementConfiguration<iOS, FormsElement> SetHideNavigationBarSeparator(this IPlatformElementConfiguration<iOS, FormsElement> config, bool value)
|
||||
{
|
||||
SetHideNavigationBarSeparator(config.Element, value);
|
||||
return config;
|
||||
}
|
||||
|
||||
public static bool HideNavigationBarSeparator(this IPlatformElementConfiguration<iOS, FormsElement> config)
|
||||
{
|
||||
return GetHideNavigationBarSeparator(config.Element);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,10 @@ using Fragment = Android.Support.V4.App.Fragment;
|
|||
using FragmentManager = Android.Support.V4.App.FragmentManager;
|
||||
using FragmentTransaction = Android.Support.V4.App.FragmentTransaction;
|
||||
using Object = Java.Lang.Object;
|
||||
using static Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage;
|
||||
using static Android.Views.View;
|
||||
using System.IO;
|
||||
using Android.Widget;
|
||||
|
||||
namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||
{
|
||||
|
@ -45,6 +48,10 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
DrawerLayout _drawerLayout;
|
||||
MasterDetailPage _masterDetailPage;
|
||||
bool _toolbarVisible;
|
||||
IVisualElementRenderer _titleViewRenderer;
|
||||
Container _titleView;
|
||||
ImageView _titleIconView;
|
||||
ImageSource _imageSource;
|
||||
bool _isAttachedToWindow;
|
||||
bool _didInitialPushPages;
|
||||
|
||||
|
@ -135,6 +142,22 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
{
|
||||
_disposed = true;
|
||||
|
||||
if (_titleViewRenderer != null)
|
||||
{
|
||||
Android.Platform.ClearRenderer(_titleViewRenderer.View);
|
||||
_titleViewRenderer.Dispose();
|
||||
_titleViewRenderer = null;
|
||||
}
|
||||
|
||||
_toolbar.RemoveView(_titleView);
|
||||
_titleView?.Dispose();
|
||||
_titleView = null;
|
||||
|
||||
_toolbar.RemoveView(_titleIconView);
|
||||
_titleIconView?.Dispose();
|
||||
_titleIconView = null;
|
||||
|
||||
_imageSource = null;
|
||||
|
||||
if (_toolbarTracker != null)
|
||||
{
|
||||
|
@ -312,6 +335,10 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
UpdateToolbar();
|
||||
else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
|
||||
UpdateToolbar();
|
||||
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
|
||||
UpdateToolbar();
|
||||
else if (e.PropertyName == BarHeightProperty.PropertyName)
|
||||
UpdateToolbar();
|
||||
}
|
||||
|
||||
protected override void OnLayout(bool changed, int l, int t, int r, int b)
|
||||
|
@ -324,6 +351,9 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
|
||||
int barHeight = ActionBarHeight();
|
||||
|
||||
if (Element.IsSet(BarHeightProperty))
|
||||
barHeight = Element.OnThisPlatform().GetBarHeight();
|
||||
|
||||
if (barHeight != _lastActionBarHeight && _lastActionBarHeight > 0)
|
||||
{
|
||||
ResetToolbar();
|
||||
|
@ -476,6 +506,9 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
UpdateToolbar();
|
||||
else if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName)
|
||||
UpdateToolbar();
|
||||
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName ||
|
||||
e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||
UpdateToolbar();
|
||||
}
|
||||
|
||||
#pragma warning disable 1998 // considered for removal
|
||||
|
@ -646,6 +679,20 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
{
|
||||
AToolbar oldToolbar = _toolbar;
|
||||
|
||||
if (_titleViewRenderer != null)
|
||||
{
|
||||
Android.Platform.ClearRenderer(_titleViewRenderer.View);
|
||||
_titleViewRenderer = null;
|
||||
}
|
||||
|
||||
_toolbar.RemoveView(_titleView);
|
||||
_titleView = null;
|
||||
|
||||
_toolbar.RemoveView(_titleIconView);
|
||||
_titleIconView = null;
|
||||
|
||||
_imageSource = null;
|
||||
|
||||
_toolbar.RemoveFromParent();
|
||||
_toolbar.SetNavigationOnClickListener(null);
|
||||
_toolbar = null;
|
||||
|
@ -852,6 +899,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
|
||||
bool isNavigated = ((INavigationPageController)Element).StackDepth > 1;
|
||||
bar.NavigationIcon = null;
|
||||
Page currentPage = Element.CurrentPage;
|
||||
|
||||
if (isNavigated)
|
||||
{
|
||||
|
@ -861,7 +909,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
toggle.SyncState();
|
||||
}
|
||||
|
||||
if (NavigationPage.GetHasBackButton(Element.CurrentPage))
|
||||
if (NavigationPage.GetHasBackButton(currentPage))
|
||||
{
|
||||
var icon = new DrawerArrowDrawable(activity.SupportActionBar.ThemedContext);
|
||||
icon.Progress = 1;
|
||||
|
@ -905,7 +953,112 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
if (!textColor.IsDefault)
|
||||
bar.SetTitleTextColor(textColor.ToAndroid().ToArgb());
|
||||
|
||||
bar.Title = Element.CurrentPage.Title ?? "";
|
||||
bar.Title = currentPage.Title ?? "";
|
||||
|
||||
UpdateTitleIcon();
|
||||
|
||||
UpdateTitleView();
|
||||
}
|
||||
|
||||
void UpdateTitleIcon()
|
||||
{
|
||||
Page currentPage = Element.CurrentPage;
|
||||
var source = NavigationPage.GetTitleIcon(currentPage);
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
_toolbar.RemoveView(_titleIconView);
|
||||
_titleIconView?.Dispose();
|
||||
_titleIconView = null;
|
||||
_imageSource = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_titleIconView == null)
|
||||
{
|
||||
_titleIconView = new ImageView(Context);
|
||||
_toolbar.AddView(_titleIconView, 0);
|
||||
}
|
||||
|
||||
UpdateBitmap(source, _imageSource);
|
||||
_imageSource = source;
|
||||
}
|
||||
|
||||
async void UpdateBitmap(ImageSource source, ImageSource previousSource = null)
|
||||
{
|
||||
if (Equals(source, previousSource))
|
||||
return;
|
||||
|
||||
_titleIconView.SetImageResource(global::Android.Resource.Color.Transparent);
|
||||
|
||||
Bitmap bitmap = null;
|
||||
IImageSourceHandler handler;
|
||||
|
||||
if (source != null && (handler = Registrar.Registered.GetHandlerForObject<IImageSourceHandler>(source)) != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
bitmap = await handler.LoadImageAsync(source, Context);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Internals.Log.Warning("Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer", "Error updating bitmap: {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (bitmap == null && source is FileImageSource)
|
||||
_titleIconView.SetImageResource(ResourceManager.GetDrawableByName(((FileImageSource)source).File));
|
||||
else
|
||||
_titleIconView.SetImageBitmap(bitmap);
|
||||
|
||||
bitmap?.Dispose();
|
||||
}
|
||||
|
||||
void UpdateTitleView()
|
||||
{
|
||||
AToolbar bar = _toolbar;
|
||||
|
||||
if (bar == null)
|
||||
return;
|
||||
|
||||
Page currentPage = Element.CurrentPage;
|
||||
VisualElement titleView = NavigationPage.GetTitleView(currentPage);
|
||||
if (_titleViewRenderer != null)
|
||||
{
|
||||
var reflectableType = _titleViewRenderer as System.Reflection.IReflectableType;
|
||||
var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : _titleViewRenderer.GetType();
|
||||
if (titleView == null || Registrar.Registered.GetHandlerTypeForObject(titleView) != rendererType)
|
||||
{
|
||||
if (_titleView != null)
|
||||
_titleView.Child = null;
|
||||
Android.Platform.ClearRenderer(_titleViewRenderer.View);
|
||||
_titleViewRenderer.Dispose();
|
||||
_titleViewRenderer = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (titleView == null)
|
||||
return;
|
||||
|
||||
if (_titleViewRenderer != null)
|
||||
_titleViewRenderer.SetElement(titleView);
|
||||
else
|
||||
{
|
||||
_titleViewRenderer = Android.Platform.CreateRenderer(titleView, Context);
|
||||
|
||||
if (_titleView == null)
|
||||
{
|
||||
_titleView = new Container(Context);
|
||||
bar.AddView(_titleView);
|
||||
}
|
||||
|
||||
_titleView.Child = _titleViewRenderer;
|
||||
}
|
||||
|
||||
Android.Platform.SetRenderer(titleView, _titleViewRenderer);
|
||||
}
|
||||
|
||||
void AddTransitionTimer(TaskCompletionSource<bool> tcs, Fragment fragment, FragmentManager fragmentManager, IReadOnlyCollection<Fragment> fragmentsToRemove, int duration, bool shouldUpdateToolbar)
|
||||
|
@ -969,6 +1122,66 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
}
|
||||
}
|
||||
|
||||
internal class Container : ViewGroup
|
||||
{
|
||||
IVisualElementRenderer _child;
|
||||
|
||||
public Container(IntPtr p, global::Android.Runtime.JniHandleOwnership o) : base(p, o)
|
||||
{
|
||||
// Added default constructor to prevent crash in Dispose
|
||||
}
|
||||
|
||||
public Container(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public IVisualElementRenderer Child
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_child != null)
|
||||
RemoveView(_child.View);
|
||||
|
||||
_child = value;
|
||||
|
||||
if (value != null)
|
||||
AddView(value.View);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLayout(bool changed, int l, int t, int r, int b)
|
||||
{
|
||||
if (_child == null)
|
||||
return;
|
||||
|
||||
_child.UpdateLayout();
|
||||
}
|
||||
|
||||
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
if (_child == null)
|
||||
{
|
||||
SetMeasuredDimension(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
VisualElement element = _child.Element;
|
||||
|
||||
Context ctx = Context;
|
||||
|
||||
var width = (int)ctx.FromPixels(MeasureSpecFactory.GetSize(widthMeasureSpec));
|
||||
|
||||
SizeRequest request = _child.Element.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
|
||||
Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(_child.Element, new Rectangle(0, 0, width, request.Request.Height));
|
||||
|
||||
int widthSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(width), MeasureSpecMode.Exactly);
|
||||
int heightSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(request.Request.Height), MeasureSpecMode.Exactly);
|
||||
|
||||
_child.View.Measure(widthMeasureSpec, heightMeasureSpec);
|
||||
SetMeasuredDimension(widthSpec, heightSpec);
|
||||
}
|
||||
}
|
||||
|
||||
class DrawerMultiplexedListener : Object, DrawerLayout.IDrawerListener
|
||||
{
|
||||
public List<DrawerLayout.IDrawerListener> Listeners { get; } = new List<DrawerLayout.IDrawerListener>(2);
|
||||
|
|
|
@ -17,6 +17,7 @@ using Android.Widget;
|
|||
using Xamarin.Forms.Platform.Android.AppCompat;
|
||||
using FragmentManager = Android.Support.V4.App.FragmentManager;
|
||||
using Xamarin.Forms.Internals;
|
||||
using AView = Android.Views.View;
|
||||
|
||||
namespace Xamarin.Forms.Platform.Android
|
||||
{
|
||||
|
@ -298,6 +299,23 @@ namespace Xamarin.Forms.Platform.Android
|
|||
throw new InvalidOperationException("RemovePage is not supported globally on Android, please use a NavigationPage.");
|
||||
}
|
||||
|
||||
public static void ClearRenderer(AView renderedView)
|
||||
{
|
||||
var element = (renderedView as IVisualElementRenderer)?.Element;
|
||||
var view = element as View;
|
||||
if (view != null)
|
||||
{
|
||||
var renderer = GetRenderer(view);
|
||||
if (renderer == renderedView)
|
||||
element.ClearValue(RendererProperty);
|
||||
renderer?.Dispose();
|
||||
renderer = null;
|
||||
}
|
||||
var layout = view as IVisualElementRenderer;
|
||||
layout?.Dispose();
|
||||
layout = null;
|
||||
}
|
||||
|
||||
[Obsolete("CreateRenderer(VisualElement) is obsolete as of version 2.5. Please use CreateRendererWithContext(VisualElement, Context) instead.")]
|
||||
public static IVisualElementRenderer CreateRenderer(VisualElement element)
|
||||
{
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
{
|
||||
if (_headerRenderer != null)
|
||||
{
|
||||
ClearRenderer(_headerRenderer.View);
|
||||
Platform.ClearRenderer(_headerRenderer.View);
|
||||
_headerRenderer.Dispose();
|
||||
_headerRenderer = null;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
if (_footerRenderer != null)
|
||||
{
|
||||
ClearRenderer(_footerRenderer.View);
|
||||
Platform.ClearRenderer(_footerRenderer.View);
|
||||
_footerRenderer.Dispose();
|
||||
_footerRenderer = null;
|
||||
}
|
||||
|
@ -286,23 +286,6 @@ namespace Xamarin.Forms.Platform.Android
|
|||
Control.SetSelectionFromTop(realPositionWithHeader, y);
|
||||
}
|
||||
|
||||
void ClearRenderer(AView renderedView)
|
||||
{
|
||||
var element = (renderedView as IVisualElementRenderer)?.Element;
|
||||
var view = element as View;
|
||||
if (view != null)
|
||||
{
|
||||
var renderer = Platform.GetRenderer(view);
|
||||
if (renderer == renderedView)
|
||||
element.ClearValue(Platform.RendererProperty);
|
||||
renderer?.Dispose();
|
||||
renderer = null;
|
||||
}
|
||||
var layout = view as IVisualElementRenderer;
|
||||
layout?.Dispose();
|
||||
layout = null;
|
||||
}
|
||||
|
||||
void UpdateFooter()
|
||||
{
|
||||
var footer = (VisualElement)Controller.FooterElement;
|
||||
|
@ -314,7 +297,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
{
|
||||
if (_footerView != null)
|
||||
_footerView.Child = null;
|
||||
ClearRenderer(_footerRenderer.View);
|
||||
Platform.ClearRenderer(_footerRenderer.View);
|
||||
_footerRenderer.Dispose();
|
||||
_footerRenderer = null;
|
||||
}
|
||||
|
@ -346,7 +329,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
{
|
||||
if (_headerView != null)
|
||||
_headerView.Child = null;
|
||||
ClearRenderer(_headerRenderer.View);
|
||||
Platform.ClearRenderer(_headerRenderer.View);
|
||||
_headerRenderer.Dispose();
|
||||
_headerRenderer = null;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Xamarin.Forms.Internals;
|
||||
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||
|
||||
namespace Xamarin.Forms.Platform.UWP
|
||||
{
|
||||
|
@ -28,6 +31,27 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
self.SetBinding(property, new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath(path), Converter = converter });
|
||||
}
|
||||
|
||||
public static async Task<WImageSource> ToWindowsImageSource(this ImageSource source)
|
||||
{
|
||||
IImageSourceHandler handler;
|
||||
if (source != null && (handler = Registrar.Registered.GetHandlerForObject<IImageSourceHandler>(source)) != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await handler.LoadImageAsync(source);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static InputScopeNameValue GetKeyboardButtonType(this ReturnType returnType)
|
||||
{
|
||||
switch (returnType)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
namespace Xamarin.Forms.Platform.UWP
|
||||
{
|
||||
internal interface ITitleIconProvider
|
||||
{
|
||||
Windows.UI.Xaml.Media.ImageSource TitleIcon { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace Xamarin.Forms.Platform.UWP
|
||||
{
|
||||
internal interface ITitleViewProvider
|
||||
{
|
||||
View TitleView { get; set; }
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using Windows.UI.Xaml;
|
|||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
||||
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||
|
||||
namespace Xamarin.Forms.Platform.UWP
|
||||
{
|
||||
|
@ -33,6 +34,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
public static readonly DependencyProperty DetailTitleProperty = DependencyProperty.Register("DetailTitle", typeof(string), typeof(MasterDetailControl), new PropertyMetadata(default(string)));
|
||||
|
||||
public static readonly DependencyProperty DetailTitleIconProperty = DependencyProperty.Register(nameof(DetailTitleIcon), typeof(WImageSource), typeof(MasterDetailControl), new PropertyMetadata(default(WImageSource)));
|
||||
|
||||
public static readonly DependencyProperty DetailTitleViewProperty = DependencyProperty.Register(nameof(DetailTitleView), typeof(View), typeof(MasterDetailControl), new PropertyMetadata(default(View), OnTitleViewPropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty ToolbarForegroundProperty = DependencyProperty.Register("ToolbarForeground", typeof(Brush), typeof(MasterDetailControl),
|
||||
new PropertyMetadata(default(Brush)));
|
||||
|
||||
|
@ -45,6 +50,9 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
public static readonly DependencyProperty DetailTitleVisibilityProperty = DependencyProperty.Register("DetailTitleVisibility", typeof(Visibility), typeof(MasterDetailControl),
|
||||
new PropertyMetadata(default(Visibility)));
|
||||
|
||||
public static readonly DependencyProperty DetailTitleViewVisibilityProperty = DependencyProperty.Register(nameof(DetailTitleViewVisibility), typeof(Visibility), typeof(MasterDetailControl),
|
||||
new PropertyMetadata(default(Visibility)));
|
||||
|
||||
public static readonly DependencyProperty MasterToolbarVisibilityProperty = DependencyProperty.Register("MasterToolbarVisibility", typeof(Visibility), typeof(MasterDetailControl),
|
||||
new PropertyMetadata(default(Visibility)));
|
||||
|
||||
|
@ -66,6 +74,7 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
FrameworkElement _detailPresenter;
|
||||
SplitView _split;
|
||||
ToolbarPlacement _toolbarPlacement;
|
||||
FrameworkElement _titleViewPresenter;
|
||||
|
||||
public MasterDetailControl()
|
||||
{
|
||||
|
@ -110,12 +119,30 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
set { SetValue(DetailTitleProperty, value); }
|
||||
}
|
||||
|
||||
public WImageSource DetailTitleIcon
|
||||
{
|
||||
get { return (WImageSource)GetValue(DetailTitleIconProperty); }
|
||||
set { SetValue(DetailTitleIconProperty, value); }
|
||||
}
|
||||
|
||||
public View DetailTitleView
|
||||
{
|
||||
get { return (View)GetValue(DetailTitleViewProperty); }
|
||||
set { SetValue(DetailTitleViewProperty, value); }
|
||||
}
|
||||
|
||||
public Visibility DetailTitleVisibility
|
||||
{
|
||||
get { return (Visibility)GetValue(DetailTitleVisibilityProperty); }
|
||||
set { SetValue(DetailTitleVisibilityProperty, value); }
|
||||
}
|
||||
|
||||
public Visibility DetailTitleViewVisibility
|
||||
{
|
||||
get { return (Visibility)GetValue(DetailTitleViewVisibilityProperty); }
|
||||
set { SetValue(DetailTitleViewVisibilityProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsPaneOpen
|
||||
{
|
||||
get { return (bool)GetValue(IsPaneOpenProperty); }
|
||||
|
@ -260,6 +287,7 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
_masterPresenter = GetTemplateChild("MasterPresenter") as FrameworkElement;
|
||||
_detailPresenter = GetTemplateChild("DetailPresenter") as FrameworkElement;
|
||||
_titleViewPresenter = GetTemplateChild("TitleViewPresenter") as FrameworkElement;
|
||||
|
||||
_commandBar = GetTemplateChild("CommandBar") as CommandBar;
|
||||
_toolbarPlacementHelper.Initialize(_commandBar, () => ToolbarPlacement, GetTemplateChild);
|
||||
|
@ -285,11 +313,24 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
((MasterDetailControl)dependencyObject).UpdateMode();
|
||||
}
|
||||
|
||||
static void OnTitleViewPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((MasterDetailControl)dependencyObject).UpdateTitleViewPresenter();
|
||||
}
|
||||
|
||||
void OnToggleClicked(object sender, RoutedEventArgs args)
|
||||
{
|
||||
IsPaneOpen = !IsPaneOpen;
|
||||
}
|
||||
|
||||
void OnTitleViewPresenterLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DetailTitleView == null || _titleViewPresenter == null || _commandBar == null)
|
||||
return;
|
||||
|
||||
_titleViewPresenter.Width = _commandBar.ActualWidth;
|
||||
}
|
||||
|
||||
void UpdateMode()
|
||||
{
|
||||
if (_split == null)
|
||||
|
@ -324,5 +365,23 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
_firstLoad = true;
|
||||
}
|
||||
|
||||
void UpdateTitleViewPresenter()
|
||||
{
|
||||
if (DetailTitleView == null)
|
||||
{
|
||||
DetailTitleViewVisibility = Visibility.Collapsed;
|
||||
|
||||
if (_titleViewPresenter != null)
|
||||
_titleViewPresenter.Loaded -= OnTitleViewPresenterLoaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
DetailTitleViewVisibility = Visibility.Visible;
|
||||
|
||||
if (_titleViewPresenter != null)
|
||||
_titleViewPresenter.Loaded += OnTitleViewPresenterLoaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,19 +30,30 @@
|
|||
</Grid.RowDefinitions>
|
||||
|
||||
<Border x:Name="TopCommandBarArea" HorizontalAlignment="Stretch" Background="{TemplateBinding ToolbarBackground}">
|
||||
<uwp:FormsCommandBar x:Name="CommandBar" Background="{TemplateBinding ToolbarBackground}" MinHeight="{ThemeResource TitleBarHeight}">
|
||||
<uwp:FormsCommandBar x:Name="CommandBar" Background="{TemplateBinding ToolbarBackground}" MinHeight="{ThemeResource TitleBarHeight}" HorizontalAlignment="Stretch">
|
||||
<uwp:FormsCommandBar.Content>
|
||||
<Border x:Name="TitleArea" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding DetailTitleVisibility}">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Background="{TemplateBinding ToolbarBackground}" >
|
||||
<Border x:Name="TitleArea" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding DetailTitleVisibility}" HorizontalAlignment="Stretch">
|
||||
<Grid x:Name="TitleViewPresenter" VerticalAlignment="Center" Background="{TemplateBinding ToolbarBackground}" HorizontalAlignment="Stretch">
|
||||
|
||||
<Button Name="ContentTogglePane" Style="{ThemeResource PaneButton}" Foreground="{TemplateBinding ToolbarForeground}"
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="0" Name="ContentTogglePane" Style="{ThemeResource PaneButton}" Foreground="{TemplateBinding ToolbarForeground}"
|
||||
Visibility="{TemplateBinding ContentTogglePaneButtonVisibility}" />
|
||||
|
||||
<Border Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding DetailTitleVisibility}">
|
||||
<Image Grid.Column="1" Source="{TemplateBinding DetailTitleIcon}" />
|
||||
|
||||
<Border Grid.Column="2" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding DetailTitleVisibility}">
|
||||
<TextBlock Text="{TemplateBinding DetailTitle}" VerticalAlignment="Center" Margin="10,0,0,0" Foreground="{TemplateBinding ToolbarForeground}" Style="{ThemeResource TitleTextBlockStyle}" />
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
<ContentPresenter Grid.Column="3" Content="{Binding DetailTitleView, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource ViewToRenderer}}" Visibility="{TemplateBinding DetailTitleViewVisibility}" HorizontalAlignment="Stretch" />
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
</uwp:FormsCommandBar.Content>
|
||||
</uwp:FormsCommandBar>
|
||||
|
|
|
@ -7,10 +7,11 @@ using Windows.UI.Xaml.Data;
|
|||
using Windows.UI.Xaml.Media;
|
||||
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
||||
using Specifics = Xamarin.Forms.PlatformConfiguration.WindowsSpecific.MasterDetailPage;
|
||||
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||
|
||||
namespace Xamarin.Forms.Platform.UWP
|
||||
{
|
||||
public class MasterDetailPageRenderer : IVisualElementRenderer, IToolbarProvider, ITitleProvider, IToolBarForegroundBinder
|
||||
public class MasterDetailPageRenderer : IVisualElementRenderer, IToolbarProvider, ITitleProvider, ITitleIconProvider, ITitleViewProvider, IToolBarForegroundBinder
|
||||
{
|
||||
Page _master;
|
||||
Page _detail;
|
||||
|
@ -97,6 +98,27 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
get { return Element; }
|
||||
}
|
||||
|
||||
WImageSource ITitleIconProvider.TitleIcon
|
||||
{
|
||||
get { return Control?.DetailTitleIcon; }
|
||||
|
||||
set
|
||||
{
|
||||
if (Control != null)
|
||||
Control.DetailTitleIcon = value;
|
||||
}
|
||||
}
|
||||
|
||||
View ITitleViewProvider.TitleView
|
||||
{
|
||||
get => Control?.DetailTitleView;
|
||||
set
|
||||
{
|
||||
if (Control != null)
|
||||
Control.DetailTitleView = value;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable 0067 // Revisit: Can't remove; required by interface
|
||||
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
||||
#pragma warning restore
|
||||
|
@ -176,6 +198,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
((ITitleProvider)this).ShowTitle = false;
|
||||
|
||||
var titleView = ((ITitleViewProvider)this).TitleView;
|
||||
titleView?.ClearValue(Platform.RendererProperty);
|
||||
titleView = null;
|
||||
|
||||
if (_detail == null)
|
||||
return;
|
||||
|
||||
|
@ -219,8 +245,18 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
void OnDetailPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == Page.TitleProperty.PropertyName || e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
|
||||
if (e.PropertyName == Page.TitleProperty.PropertyName)
|
||||
UpdateDetailTitle();
|
||||
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName)
|
||||
UpdateDetailTitleIcon();
|
||||
else if (e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||
UpdateDetailTitleView();
|
||||
else if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
|
||||
{
|
||||
UpdateDetailTitle();
|
||||
UpdateDetailTitleIcon();
|
||||
UpdateDetailTitleView();
|
||||
}
|
||||
}
|
||||
|
||||
void OnIsPaneOpenChanged(DependencyObject sender, DependencyProperty dp)
|
||||
|
@ -268,6 +304,8 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
Control.Detail = element;
|
||||
UpdateDetailTitle();
|
||||
UpdateDetailTitleIcon();
|
||||
UpdateDetailTitleView();
|
||||
}
|
||||
|
||||
void UpdateDetailTitle()
|
||||
|
@ -279,6 +317,24 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
(this as ITitleProvider).ShowTitle = !string.IsNullOrEmpty(Control.DetailTitle);
|
||||
}
|
||||
|
||||
async void UpdateDetailTitleIcon()
|
||||
{
|
||||
if (_detail == null)
|
||||
return;
|
||||
|
||||
Control.DetailTitleIcon = await NavigationPage.GetTitleIcon(_detail).ToWindowsImageSource();
|
||||
Control.InvalidateMeasure();
|
||||
}
|
||||
|
||||
void UpdateDetailTitleView()
|
||||
{
|
||||
if (_detail == null)
|
||||
return;
|
||||
|
||||
Control.DetailTitleView = NavigationPage.GetTitleView(_detail) as View;
|
||||
Control.InvalidateMeasure();
|
||||
}
|
||||
|
||||
void UpdateFlowDirection()
|
||||
{
|
||||
Control.UpdateFlowDirection(Element);
|
||||
|
@ -317,6 +373,8 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
void UpdateMode()
|
||||
{
|
||||
UpdateDetailTitle();
|
||||
UpdateDetailTitleIcon();
|
||||
UpdateDetailTitleView();
|
||||
Control.CollapseStyle = Element.OnThisPlatform().GetCollapseStyle();
|
||||
Control.CollapsedPaneWidth = Element.OnThisPlatform().CollapsedPaneWidth();
|
||||
Control.ShouldShowSplitMode = Element.ShouldShowSplitMode;
|
||||
|
|
|
@ -11,12 +11,14 @@ using Windows.UI.Xaml.Input;
|
|||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
using Xamarin.Forms.Internals;
|
||||
using static Xamarin.Forms.PlatformConfiguration.WindowsSpecific.Page;
|
||||
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||
|
||||
|
||||
using Windows.UI.Core;
|
||||
namespace Xamarin.Forms.Platform.UWP
|
||||
{
|
||||
public partial class NavigationPageRenderer : IVisualElementRenderer, ITitleProvider, IToolbarProvider
|
||||
public partial class NavigationPageRenderer : IVisualElementRenderer, ITitleProvider, ITitleIconProvider, ITitleViewProvider, IToolbarProvider
|
||||
{
|
||||
PageControl _container;
|
||||
Page _currentPage;
|
||||
|
@ -27,6 +29,7 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
MasterDetailPage _parentMasterDetailPage;
|
||||
TabbedPage _parentTabbedPage;
|
||||
bool _showTitle = true;
|
||||
WImageSource _titleIcon;
|
||||
VisualElementTracker<Page, PageControl> _tracker;
|
||||
EntranceThemeTransition _transition;
|
||||
|
||||
|
@ -88,7 +91,25 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
get { return _currentPage?.Title; }
|
||||
|
||||
set { }
|
||||
set { /*Not implemented but required by interface*/ }
|
||||
}
|
||||
|
||||
public WImageSource TitleIcon
|
||||
{
|
||||
get => _titleIcon;
|
||||
set => _titleIcon = value;
|
||||
}
|
||||
|
||||
public View TitleView
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_currentPage == null)
|
||||
return null;
|
||||
|
||||
return NavigationPage.GetTitleView(_currentPage) as View;
|
||||
}
|
||||
set { /*Not implemented but required by interface*/ }
|
||||
}
|
||||
|
||||
Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
|
||||
|
@ -175,6 +196,8 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
UpdateTitleColor();
|
||||
UpdateNavigationBarBackground();
|
||||
UpdateToolbarPlacement();
|
||||
UpdateTitleIcon();
|
||||
UpdateTitleView();
|
||||
|
||||
// Enforce consistency rules on toolbar (show toolbar if top-level page is Navigation Page)
|
||||
_container.ShouldShowToolbar = _parentMasterDetailPage == null && _parentTabbedPage == null;
|
||||
|
@ -283,12 +306,20 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
UpdateShowTitle();
|
||||
|
||||
UpdateTitleOnParents();
|
||||
|
||||
UpdateTitleIcon();
|
||||
|
||||
UpdateTitleView();
|
||||
}
|
||||
|
||||
void MultiPagePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "CurrentPage" || e.PropertyName == "Detail")
|
||||
{
|
||||
UpdateTitleOnParents();
|
||||
UpdateTitleIcon();
|
||||
UpdateTitleView();
|
||||
}
|
||||
}
|
||||
|
||||
async void OnBackClicked(object sender, RoutedEventArgs e)
|
||||
|
@ -311,6 +342,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
UpdateTitleVisible();
|
||||
else if (e.PropertyName == Page.TitleProperty.PropertyName)
|
||||
UpdateTitleOnParents();
|
||||
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName)
|
||||
UpdateTitleIcon();
|
||||
else if (e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||
UpdateTitleView();
|
||||
}
|
||||
|
||||
void OnElementAppearing(object sender, EventArgs e)
|
||||
|
@ -327,9 +362,12 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
UpdateNavigationBarBackground();
|
||||
else if (e.PropertyName == Page.PaddingProperty.PropertyName)
|
||||
UpdatePadding();
|
||||
|
||||
else if (e.PropertyName == PlatformConfiguration.WindowsSpecific.Page.ToolbarPlacementProperty.PropertyName)
|
||||
else if (e.PropertyName == ToolbarPlacementProperty.PropertyName)
|
||||
UpdateToolbarPlacement();
|
||||
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName)
|
||||
UpdateTitleIcon();
|
||||
else if (e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||
UpdateTitleView();
|
||||
}
|
||||
|
||||
void OnLoaded(object sender, RoutedEventArgs args)
|
||||
|
@ -424,6 +462,8 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
UpdateTitleVisible();
|
||||
UpdateTitleOnParents();
|
||||
UpdateTitleIcon();
|
||||
UpdateTitleView();
|
||||
|
||||
if (isAnimated && _transition == null)
|
||||
{
|
||||
|
@ -484,5 +524,34 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
(this as ITitleProvider).BarForegroundBrush = GetBarForegroundBrush();
|
||||
}
|
||||
|
||||
async void UpdateTitleIcon()
|
||||
{
|
||||
if (_currentPage == null)
|
||||
return;
|
||||
|
||||
ImageSource source = NavigationPage.GetTitleIcon(_currentPage);
|
||||
|
||||
_titleIcon = await source.ToWindowsImageSource();
|
||||
|
||||
_container.TitleIcon = _titleIcon;
|
||||
|
||||
if (_parentMasterDetailPage != null && Platform.GetRenderer(_parentMasterDetailPage) is ITitleIconProvider parent)
|
||||
parent.TitleIcon = _titleIcon;
|
||||
|
||||
_container.UpdateLayout();
|
||||
UpdateContainerArea();
|
||||
}
|
||||
|
||||
void UpdateTitleView()
|
||||
{
|
||||
if (_currentPage == null)
|
||||
return;
|
||||
|
||||
_container.TitleView = TitleView;
|
||||
|
||||
if (_parentMasterDetailPage != null && Platform.GetRenderer(_parentMasterDetailPage) is ITitleViewProvider parent)
|
||||
parent.TitleView = TitleView;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
||||
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||
|
||||
namespace Xamarin.Forms.Platform.UWP
|
||||
{
|
||||
|
@ -24,12 +25,19 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
public static readonly DependencyProperty ContentMarginProperty = DependencyProperty.Register("ContentMargin", typeof(Windows.UI.Xaml.Thickness), typeof(PageControl),
|
||||
new PropertyMetadata(default(Windows.UI.Xaml.Thickness)));
|
||||
|
||||
public static readonly DependencyProperty TitleIconProperty = DependencyProperty.Register(nameof(TitleIcon), typeof(WImageSource), typeof(PageControl), new PropertyMetadata(default(WImageSource)));
|
||||
|
||||
public static readonly DependencyProperty TitleViewProperty = DependencyProperty.Register(nameof(TitleView), typeof(View), typeof(PageControl), new PropertyMetadata(default(View), OnTitleViewPropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty TitleViewVisibilityProperty = DependencyProperty.Register(nameof(TitleViewVisibility), typeof(Visibility), typeof(PageControl), new PropertyMetadata(Visibility.Collapsed));
|
||||
|
||||
public static readonly DependencyProperty TitleInsetProperty = DependencyProperty.Register("TitleInset", typeof(double), typeof(PageControl), new PropertyMetadata(default(double)));
|
||||
|
||||
public static readonly DependencyProperty TitleBrushProperty = DependencyProperty.Register("TitleBrush", typeof(Brush), typeof(PageControl), new PropertyMetadata(null));
|
||||
|
||||
AppBarButton _backButton;
|
||||
CommandBar _commandBar;
|
||||
FrameworkElement _titleViewPresenter;
|
||||
|
||||
ToolbarPlacement _toolbarPlacement;
|
||||
readonly ToolbarPlacementHelper _toolbarPlacementHelper = new ToolbarPlacementHelper();
|
||||
|
@ -40,6 +48,18 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
set { _toolbarPlacementHelper.ShouldShowToolBar = value; }
|
||||
}
|
||||
|
||||
public WImageSource TitleIcon
|
||||
{
|
||||
get { return (WImageSource)GetValue(TitleIconProperty); }
|
||||
set { SetValue(TitleIconProperty, value); }
|
||||
}
|
||||
|
||||
public View TitleView
|
||||
{
|
||||
get { return (View)GetValue(TitleViewProperty); }
|
||||
set { SetValue(TitleViewProperty, value); }
|
||||
}
|
||||
|
||||
TaskCompletionSource<CommandBar> _commandBarTcs;
|
||||
Windows.UI.Xaml.Controls.ContentPresenter _presenter;
|
||||
|
||||
|
@ -105,6 +125,12 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
set { SetValue(TitleVisibilityProperty, value); }
|
||||
}
|
||||
|
||||
public Visibility TitleViewVisibility
|
||||
{
|
||||
get { return (Visibility)GetValue(TitleViewVisibilityProperty); }
|
||||
set { SetValue(TitleViewVisibilityProperty, value); }
|
||||
}
|
||||
|
||||
public Brush TitleBrush
|
||||
{
|
||||
get { return (Brush)GetValue(TitleBrushProperty); }
|
||||
|
@ -139,6 +165,8 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
_presenter = GetTemplateChild("presenter") as Windows.UI.Xaml.Controls.ContentPresenter;
|
||||
|
||||
_titleViewPresenter = GetTemplateChild("TitleViewPresenter") as FrameworkElement;
|
||||
|
||||
_commandBar = GetTemplateChild("CommandBar") as CommandBar;
|
||||
|
||||
|
||||
|
@ -165,6 +193,19 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
((PageControl)dependencyObject).UpdateBackButton();
|
||||
}
|
||||
|
||||
static void OnTitleViewPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((PageControl)dependencyObject).UpdateTitleViewPresenter();
|
||||
}
|
||||
|
||||
void OnTitleViewPresenterLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (TitleView == null || _titleViewPresenter == null || _commandBar == null)
|
||||
return;
|
||||
|
||||
_titleViewPresenter.Width = _commandBar.ActualWidth;
|
||||
}
|
||||
|
||||
void UpdateBackButton()
|
||||
{
|
||||
if (_backButton == null)
|
||||
|
@ -177,5 +218,23 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
_backButton.Opacity = ShowBackButton ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateTitleViewPresenter()
|
||||
{
|
||||
if (TitleView == null)
|
||||
{
|
||||
TitleViewVisibility = Visibility.Collapsed;
|
||||
|
||||
if (_titleViewPresenter != null)
|
||||
_titleViewPresenter.Loaded -= OnTitleViewPresenterLoaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
TitleViewVisibility = Visibility.Visible;
|
||||
|
||||
if (_titleViewPresenter != null)
|
||||
_titleViewPresenter.Loaded += OnTitleViewPresenterLoaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,15 +16,31 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border x:Name="TopCommandBarArea" HorizontalAlignment="Stretch" Background="{TemplateBinding ToolbarBackground}">
|
||||
<uwp:FormsCommandBar x:Name="CommandBar" Background="{TemplateBinding ToolbarBackground}" MinHeight="{ThemeResource TitleBarHeight}">
|
||||
<uwp:FormsCommandBar.Content>
|
||||
<Border x:Name="TitleArea" Visibility="{TemplateBinding TitleVisibility}" Height="{ThemeResource TitleBarHeight}">
|
||||
<TextBlock Text="{Binding Title}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="10,0,0,0" Foreground="{TemplateBinding TitleBrush}" Style="{ThemeResource TitleTextBlockStyle}" />
|
||||
</Border>
|
||||
</uwp:FormsCommandBar.Content>
|
||||
</uwp:FormsCommandBar>
|
||||
</Border>
|
||||
<Border x:Name="TopCommandBarArea" HorizontalAlignment="Stretch" Background="{TemplateBinding ToolbarBackground}">
|
||||
<uwp:FormsCommandBar x:Name="CommandBar" Background="{TemplateBinding ToolbarBackground}" MinHeight="{ThemeResource TitleBarHeight}" HorizontalAlignment="Stretch">
|
||||
<uwp:FormsCommandBar.Content>
|
||||
<Border x:Name="TitleArea" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding TitleVisibility}" HorizontalAlignment="Stretch">
|
||||
<Grid x:Name="TitleViewPresenter" VerticalAlignment="Center" Background="{TemplateBinding ToolbarBackground}" HorizontalAlignment="Stretch">
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image Grid.Column="0" Source="{TemplateBinding TitleIcon}" />
|
||||
|
||||
<Border Grid.Column="1" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding TitleVisibility}">
|
||||
<TextBlock Text="{Binding Title}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="10,0,0,0" Foreground="{TemplateBinding TitleBrush}" Style="{ThemeResource TitleTextBlockStyle}" />
|
||||
</Border>
|
||||
|
||||
<ContentPresenter Grid.Column="2" Content="{Binding TitleView, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource ViewToRenderer}}" Visibility="{TemplateBinding TitleViewVisibility}" HorizontalAlignment="Stretch" />
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
</uwp:FormsCommandBar.Content>
|
||||
</uwp:FormsCommandBar>
|
||||
</Border>
|
||||
|
||||
<uwp:FormsPresenter Margin="{TemplateBinding ContentMargin}" ContentTransitions="{TemplateBinding ContentTransitions}" x:Name="presenter" Grid.Row="1" />
|
||||
|
||||
|
|
|
@ -68,9 +68,9 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
_view.IsInNativeLayout = true;
|
||||
Layout.LayoutChildIntoBoundingRegion(_view, new Rectangle(0, 0, finalSize.Width, finalSize.Height));
|
||||
FrameworkElement?.Arrange(new Rect(_view.X, _view.Y, _view.Width, _view.Height));
|
||||
_view.IsInNativeLayout = false;
|
||||
|
||||
FrameworkElement?.Arrange(new Rect(_view.X, _view.Y, _view.Width, _view.Height));
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
result = new Windows.Foundation.Size(request.Width, request.Height);
|
||||
}
|
||||
|
||||
_view.Layout(new Rectangle(0, 0, result.Width, result.Height));
|
||||
Layout.LayoutChildIntoBoundingRegion(_view, new Rectangle(0, 0, result.Width, result.Height));
|
||||
|
||||
FrameworkElement?.Measure(availableSize);
|
||||
|
||||
|
|
|
@ -56,7 +56,9 @@
|
|||
<Compile Include="FormsComboBox.cs" />
|
||||
<Compile Include="InterceptVisualStateManager.cs" />
|
||||
<Compile Include="HorizontalTextAlignmentConverter.cs" />
|
||||
<Compile Include="ITitleIconProvider.cs" />
|
||||
<Compile Include="ITitleProvider.cs" />
|
||||
<Compile Include="ITitleViewProvider.cs" />
|
||||
<Compile Include="IToolbarProvider.cs" />
|
||||
<Compile Include="NativeBindingExtensions.cs" />
|
||||
<Compile Include="NativeEventWrapper.cs" />
|
||||
|
|
|
@ -13,6 +13,7 @@ using static Xamarin.Forms.PlatformConfiguration.iOSSpecific.NavigationPage;
|
|||
using PageUIStatusBarAnimation = Xamarin.Forms.PlatformConfiguration.iOSSpecific.UIStatusBarAnimation;
|
||||
using PointF = CoreGraphics.CGPoint;
|
||||
using RectangleF = CoreGraphics.CGRect;
|
||||
using SizeF = CoreGraphics.CGSize;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
|
@ -29,6 +30,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
VisualElementTracker _tracker;
|
||||
nfloat _navigationBottom = 0;
|
||||
bool _hasNavigationBar;
|
||||
UIImage _defaultNavBarShadowImage;
|
||||
UIImage _defaultNavBarBackImage;
|
||||
|
||||
public NavigationRenderer()
|
||||
{
|
||||
|
@ -45,6 +48,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
IPageController PageController => Element as IPageController;
|
||||
|
||||
NavigationPage NavPage => Element as NavigationPage;
|
||||
|
||||
public VisualElement Element { get; private set; }
|
||||
|
||||
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
||||
|
@ -62,7 +67,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
public void SetElement(VisualElement element)
|
||||
{
|
||||
var oldElement = Element;
|
||||
Element = (NavigationPage)element;
|
||||
Element = element;
|
||||
OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
|
||||
|
||||
if (element != null)
|
||||
|
@ -84,6 +89,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
get { return this; }
|
||||
}
|
||||
|
||||
//TODO: this was deprecated in iOS8.0 and is not called in 9.0+
|
||||
public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
|
||||
{
|
||||
base.DidRotate(fromInterfaceOrientation);
|
||||
|
@ -205,7 +211,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
FindParentMasterDetail();
|
||||
|
||||
var navPage = (NavigationPage)Element;
|
||||
var navPage = NavPage;
|
||||
|
||||
if (navPage.CurrentPage == null)
|
||||
{
|
||||
|
@ -223,6 +229,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
UpdateBarBackgroundColor();
|
||||
UpdateBarTextColor();
|
||||
UpdateUseLargeTitles();
|
||||
UpdateHideNavigationBarSeparator();
|
||||
|
||||
// If there is already stuff on the stack we need to push it
|
||||
navPage.Pages.ForEach(async p => await PushPageAsync(p, false));
|
||||
|
@ -255,7 +262,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
_parentMasterDetailPage = null;
|
||||
Current = null; // unhooks events
|
||||
|
||||
var navPage = (NavigationPage)Element;
|
||||
var navPage = NavPage;
|
||||
navPage.PropertyChanged -= HandlePropertyChanged;
|
||||
|
||||
navPage.PushRequested -= OnPushRequested;
|
||||
|
@ -348,32 +355,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
// must pack into container so padding can work
|
||||
// otherwise the view controller is forced to 0,0
|
||||
var pack = new ParentingViewController(this) { Child = page };
|
||||
if (!string.IsNullOrWhiteSpace(page.Title))
|
||||
pack.NavigationItem.Title = page.Title;
|
||||
|
||||
// First page and we have a master detail to contend with
|
||||
UpdateLeftBarButtonItem(pack);
|
||||
|
||||
//var pack = Platform.GetRenderer (view).ViewController;
|
||||
|
||||
var titleIcon = NavigationPage.GetTitleIcon(page);
|
||||
if (!string.IsNullOrEmpty(titleIcon?.File))
|
||||
{
|
||||
try
|
||||
{
|
||||
SetTitleImage(pack, titleIcon);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
UpdateTitleArea(pack, page);
|
||||
|
||||
var pageRenderer = Platform.GetRenderer(page);
|
||||
pack.View.AddSubview(pageRenderer.ViewController.View);
|
||||
|
@ -383,17 +366,11 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
return pack;
|
||||
}
|
||||
|
||||
async void SetTitleImage(ParentingViewController pack, FileImageSource titleIcon)
|
||||
{
|
||||
var source = Internals.Registrar.Registered.GetHandlerForObject<IImageSourceHandler>(titleIcon);
|
||||
var image = await source.LoadImageAsync(titleIcon);
|
||||
//UIImage ctor throws on file not found if MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure is true;
|
||||
pack.NavigationItem.TitleView = new UIImageView(image);
|
||||
}
|
||||
|
||||
void FindParentMasterDetail()
|
||||
{
|
||||
var parentPages = ((Page)Element).GetParentPages();
|
||||
Page page = Element as Page;
|
||||
|
||||
var parentPages = page.GetParentPages();
|
||||
var masterDetail = parentPages.OfType<MasterDetailPage>().FirstOrDefault();
|
||||
|
||||
if (masterDetail != null && parentPages.Append((Page)Element).Contains(masterDetail.Detail))
|
||||
|
@ -436,28 +413,49 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
#pragma warning disable 0618 //retaining legacy call to obsolete code
|
||||
if (e.PropertyName == NavigationPage.TintProperty.PropertyName)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
UpdateTint();
|
||||
if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
|
||||
}
|
||||
else if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
|
||||
{
|
||||
UpdateBarBackgroundColor();
|
||||
else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName || e.PropertyName == PlatformConfiguration.iOSSpecific.NavigationPage.StatusBarTextColorModeProperty.PropertyName)
|
||||
}
|
||||
else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName
|
||||
|| e.PropertyName == StatusBarTextColorModeProperty.PropertyName)
|
||||
{
|
||||
UpdateBarTextColor();
|
||||
SetStatusBarStyle();
|
||||
}
|
||||
else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
|
||||
{
|
||||
UpdateBackgroundColor();
|
||||
}
|
||||
else if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
|
||||
{
|
||||
Current = ((NavigationPage)Element).CurrentPage;
|
||||
Current = NavPage?.CurrentPage;
|
||||
ValidateNavbarExists(Current);
|
||||
}
|
||||
|
||||
else if (e.PropertyName == PlatformConfiguration.iOSSpecific.NavigationPage.IsNavigationBarTranslucentProperty.PropertyName)
|
||||
else if (e.PropertyName == IsNavigationBarTranslucentProperty.PropertyName)
|
||||
{
|
||||
UpdateTranslucent();
|
||||
}
|
||||
else if (e.PropertyName == PreferredStatusBarUpdateAnimationProperty.PropertyName)
|
||||
{
|
||||
UpdateCurrentPagePreferredStatusBarUpdateAnimation();
|
||||
}
|
||||
else if (e.PropertyName == PrefersLargeTitlesProperty.PropertyName)
|
||||
{
|
||||
UpdateUseLargeTitles();
|
||||
}
|
||||
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
|
||||
{
|
||||
var pack = (ParentingViewController)TopViewController;
|
||||
UpdateTitleArea(pack, pack.Child);
|
||||
}
|
||||
else if (e.PropertyName == HideNavigationBarSeparatorProperty.PropertyName)
|
||||
{
|
||||
UpdateHideNavigationBarSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateNavbarExists(Page newCurrentPage)
|
||||
|
@ -468,6 +466,33 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
ViewDidLayoutSubviews();
|
||||
}
|
||||
|
||||
void UpdateHideNavigationBarSeparator()
|
||||
{
|
||||
bool shouldHide = NavPage.OnThisPlatform().HideNavigationBarSeparator();
|
||||
|
||||
// Just setting the ShadowImage is good for iOS11
|
||||
if (_defaultNavBarShadowImage == null)
|
||||
_defaultNavBarShadowImage = NavigationBar.ShadowImage;
|
||||
|
||||
if (shouldHide)
|
||||
NavigationBar.ShadowImage = new UIImage();
|
||||
else
|
||||
NavigationBar.ShadowImage = _defaultNavBarShadowImage;
|
||||
|
||||
if (!Forms.IsiOS11OrNewer)
|
||||
{
|
||||
// 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 (_defaultNavBarBackImage == null)
|
||||
_defaultNavBarBackImage = NavigationBar.GetBackgroundImage(UIBarMetrics.Default);
|
||||
|
||||
if (shouldHide)
|
||||
NavigationBar.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
|
||||
else
|
||||
NavigationBar.SetBackgroundImage(_defaultNavBarBackImage, UIBarMetrics.Default);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCurrentPagePreferredStatusBarUpdateAnimation()
|
||||
{
|
||||
// Not using the extension method syntax here because for some reason it confuses the mono compiler
|
||||
|
@ -478,14 +503,125 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void UpdateUseLargeTitles()
|
||||
{
|
||||
var navPage = (Element as NavigationPage);
|
||||
if (Forms.IsiOS11OrNewer && navPage != null)
|
||||
NavigationBar.PrefersLargeTitles = navPage.OnThisPlatform().PrefersLargeTitles();
|
||||
if (Forms.IsiOS11OrNewer && NavPage != null)
|
||||
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()
|
||||
{
|
||||
NavigationBar.Translucent = ((NavigationPage)Element).OnThisPlatform().IsNavigationBarTranslucent();
|
||||
NavigationBar.Translucent = NavPage.OnThisPlatform().IsNavigationBarTranslucent();
|
||||
}
|
||||
|
||||
void InsertPageBefore(Page page, Page before)
|
||||
|
@ -591,7 +727,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void UpdateBarBackgroundColor()
|
||||
{
|
||||
var barBackgroundColor = ((NavigationPage)Element).BarBackgroundColor;
|
||||
var barBackgroundColor = NavPage.BarBackgroundColor;
|
||||
// Set navigation bar background color
|
||||
NavigationBar.BarTintColor = barBackgroundColor == Color.Default
|
||||
? UINavigationBar.Appearance.BarTintColor
|
||||
|
@ -600,7 +736,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void UpdateBarTextColor()
|
||||
{
|
||||
var barTextColor = ((NavigationPage)Element).BarTextColor;
|
||||
var barTextColor = NavPage.BarTextColor;
|
||||
|
||||
var globalAttributes = UINavigationBar.Appearance.GetTitleTextAttributes();
|
||||
|
||||
|
@ -626,14 +762,14 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
NavigationBar.TitleTextAttributes = titleAttributes;
|
||||
}
|
||||
|
||||
if(Forms.IsiOS11OrNewer)
|
||||
if (Forms.IsiOS11OrNewer)
|
||||
{
|
||||
var globalLargeTitleAttributes = UINavigationBar.Appearance.LargeTitleTextAttributes;
|
||||
if(globalLargeTitleAttributes == null)
|
||||
if (globalLargeTitleAttributes == null)
|
||||
NavigationBar.LargeTitleTextAttributes = NavigationBar.TitleTextAttributes;
|
||||
}
|
||||
|
||||
var statusBarColorMode = (Element as NavigationPage).OnThisPlatform().GetStatusBarTextColorMode();
|
||||
var statusBarColorMode = NavPage.OnThisPlatform().GetStatusBarTextColorMode();
|
||||
|
||||
// set Tint color (i. e. Back Button arrow and Text)
|
||||
NavigationBar.TintColor = barTextColor == Color.Default || statusBarColorMode == StatusBarTextColorMode.DoNotAdjust
|
||||
|
@ -643,8 +779,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void SetStatusBarStyle()
|
||||
{
|
||||
var barTextColor = ((NavigationPage)Element).BarTextColor;
|
||||
var statusBarColorMode = (Element as NavigationPage).OnThisPlatform().GetStatusBarTextColorMode();
|
||||
var barTextColor = NavPage.BarTextColor;
|
||||
var statusBarColorMode = NavPage.OnThisPlatform().GetStatusBarTextColorMode();
|
||||
|
||||
if (statusBarColorMode == StatusBarTextColorMode.DoNotAdjust || barTextColor.Luminosity <= 0.5)
|
||||
{
|
||||
|
@ -663,7 +799,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (containerController == null)
|
||||
return;
|
||||
var currentChild = containerController.Child;
|
||||
var firstPage = ((NavigationPage)Element).Pages.FirstOrDefault();
|
||||
var firstPage = NavPage.Pages.FirstOrDefault();
|
||||
if ((firstPage != pageBeingRemoved && currentChild != firstPage && NavigationPage.GetHasBackButton(currentChild)) || _parentMasterDetailPage == null)
|
||||
return;
|
||||
|
||||
|
@ -673,7 +809,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
void UpdateTint()
|
||||
{
|
||||
#pragma warning disable 0618 //retaining legacy call to obsolete code
|
||||
var tintColor = ((NavigationPage)Element).Tint;
|
||||
var tintColor = NavPage.Tint;
|
||||
#pragma warning restore 0618
|
||||
NavigationBar.BarTintColor = tintColor == Color.Default
|
||||
? UINavigationBar.Appearance.BarTintColor
|
||||
|
@ -698,16 +834,18 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
_secondaryToolbar.Hidden = true;
|
||||
//secondaryToolbar.Items = null;
|
||||
}
|
||||
|
||||
TopViewController?.NavigationItem?.TitleView?.SizeToFit();
|
||||
TopViewController?.NavigationItem?.TitleView?.LayoutSubviews();
|
||||
}
|
||||
|
||||
internal async Task UpdateFormsInnerNavigation(Page pageBeingRemoved)
|
||||
{
|
||||
var navPage = Element as NavigationPage;
|
||||
if (navPage == null)
|
||||
if (NavPage == null)
|
||||
return;
|
||||
_ignorePopCall = true;
|
||||
if (Element.Navigation.NavigationStack.Contains(pageBeingRemoved))
|
||||
await (navPage as INavigationPageController)?.RemoveAsyncInner(pageBeingRemoved, false, true);
|
||||
await (NavPage as INavigationPageController)?.RemoveAsyncInner(pageBeingRemoved, false, true);
|
||||
_ignorePopCall = false;
|
||||
|
||||
}
|
||||
|
@ -968,6 +1106,13 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
UpdatePrefersStatusBarHidden();
|
||||
else if (e.PropertyName == LargeTitleDisplayProperty.PropertyName)
|
||||
UpdateLargeTitles();
|
||||
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName ||
|
||||
e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||
{
|
||||
NavigationRenderer n;
|
||||
if (_navigation.TryGetTarget(out n))
|
||||
n.UpdateTitleArea(this, Child);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePrefersStatusBarHidden()
|
||||
|
@ -1116,5 +1261,102 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
VisualElementRenderer<VisualElement>.RegisterEffect(effect, View);
|
||||
}
|
||||
|
||||
class Container : UIView
|
||||
{
|
||||
IVisualElementRenderer _child;
|
||||
UIImageView _icon;
|
||||
|
||||
nfloat IconHeight => _icon?.Frame.Height ?? 0;
|
||||
|
||||
nfloat IconWidth => _icon?.Frame.Width ?? 0;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
DisposeChild();
|
||||
|
||||
_icon?.Dispose();
|
||||
_icon = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public UIImageView Icon
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_icon != null)
|
||||
_icon.RemoveFromSuperview();
|
||||
|
||||
_icon = value;
|
||||
|
||||
if (_icon != null)
|
||||
AddSubview(_icon);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
IVisualElementRenderer renderer = _child;
|
||||
|
||||
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()
|
||||
{
|
||||
base.LayoutSubviews();
|
||||
|
||||
// Navigation bar will not stretch past these values. Prevent content clipping.
|
||||
// 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);
|
||||
|
||||
Frame = new RectangleF(Frame.X, Frame.Y, Bounds.Width, height);
|
||||
|
||||
if (_icon != null)
|
||||
_icon.Frame = new RectangleF(0, 0, IconWidth, Math.Min(toolbarHeight, IconHeight));
|
||||
|
||||
if (_child.Element != null)
|
||||
Layout.LayoutChildIntoBoundingRegion(_child.Element, new Rectangle(IconWidth, 0, Bounds.Width - IconWidth, height));
|
||||
}
|
||||
|
||||
public void DisposeChild()
|
||||
{
|
||||
if (_child == null)
|
||||
return;
|
||||
|
||||
if (_child.Element.Platform is Platform platform)
|
||||
platform.DisposeModelAndChildrenRenderers(_child.Element);
|
||||
|
||||
_child.NativeView.RemoveFromSuperview();
|
||||
_child.Dispose();
|
||||
_child = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче