зеркало из 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="AttachedStateEffectRenderer.cs" />
|
||||||
<Compile Include="BrokenImageSourceHandler.cs" />
|
<Compile Include="BrokenImageSourceHandler.cs" />
|
||||||
<Compile Include="BrokenNativeControl.cs" />
|
<Compile Include="BrokenNativeControl.cs" />
|
||||||
|
<Compile Include="SearchbarEffect.cs" />
|
||||||
<Compile Include="CustomRenderer40251.cs" />
|
<Compile Include="CustomRenderer40251.cs" />
|
||||||
<Compile Include="Main.cs" />
|
<Compile Include="Main.cs" />
|
||||||
<Compile Include="AppDelegate.cs" />
|
<Compile Include="AppDelegate.cs" />
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
||||||
using Xamarin.Forms.CustomAttributes;
|
using Xamarin.Forms.CustomAttributes;
|
||||||
using Xamarin.Forms.Internals;
|
using Xamarin.Forms.Internals;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
#if UITEST
|
#if UITEST
|
||||||
using Xamarin.UITest;
|
using Xamarin.UITest;
|
||||||
|
@ -43,7 +44,7 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
|
|
||||||
PerformanceViewModel ViewModel => BindingContext as PerformanceViewModel;
|
PerformanceViewModel ViewModel => BindingContext as PerformanceViewModel;
|
||||||
|
|
||||||
protected override async void Init()
|
protected override void Init()
|
||||||
{
|
{
|
||||||
_BuildInfo = GetBuildNumber();
|
_BuildInfo = GetBuildNumber();
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ namespace Xamarin.Forms.Controls.Issues
|
||||||
|
|
||||||
Content = new StackLayout { Children = { testRunRef, nextButton, _PerformanceTracker } };
|
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.IsEnabled = true;
|
||||||
nextButton.Text = Next;
|
nextButton.Text = Next;
|
||||||
|
|
|
@ -384,9 +384,10 @@ namespace Xamarin.Forms.Controls
|
||||||
_titleToPage = _pages.ToDictionary(o => o.Title);
|
_titleToPage = _pages.ToDictionary(o => o.Title);
|
||||||
|
|
||||||
// avoid NRE for root pages without NavigationBar
|
// 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));
|
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
|
namespace Xamarin.Forms.Controls
|
||||||
{
|
{
|
||||||
public class NavigationBarGallery : ContentPage
|
public class NavigationBarGallery : ContentPage
|
||||||
{
|
{
|
||||||
public NavigationBarGallery (NavigationPage rootNavPage)
|
NavigationPage _rootNavPage;
|
||||||
|
public NavigationBarGallery(NavigationPage rootNavPage)
|
||||||
{
|
{
|
||||||
|
_rootNavPage = rootNavPage;
|
||||||
|
|
||||||
int toggleBarTextColor = 0;
|
int toggleBarTextColor = 0;
|
||||||
int toggleBarBackgroundColor = 0;
|
int toggleBarBackgroundColor = 0;
|
||||||
|
|
||||||
Content = new StackLayout {
|
ToolbarItems.Add(new ToolbarItem { Text = "Save" });
|
||||||
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++;
|
|
||||||
|
|
||||||
})
|
NavigationPage.SetTitleIcon(this, "coffee.png");
|
||||||
},
|
|
||||||
new Button {
|
SearchBar searchBar = new SearchBar { HeightRequest = 44, WidthRequest = 100 };
|
||||||
Text = "Change Both to default",
|
|
||||||
Command = new Command (() => {
|
// Note: Large and complex controls, such as ListView and TableView, are not recommended.
|
||||||
rootNavPage.BarTextColor = Color.Default;
|
var controls = new List<View>
|
||||||
rootNavPage.BarBackgroundColor = Color.Default;
|
{
|
||||||
})
|
searchBar,
|
||||||
},
|
new ActivityIndicator{ IsRunning = true },
|
||||||
new Button {
|
new BoxView{ BackgroundColor = Color.Red },
|
||||||
Text = "Make sure Tint still works",
|
new Button{ Text = "Button!"},
|
||||||
Command = new Command (() => {
|
new DatePicker{},
|
||||||
#pragma warning disable 618
|
new Editor{ Text = "Editor"},
|
||||||
rootNavPage.Tint = Color.Red;
|
new Entry{ Placeholder = "Entry"},
|
||||||
#pragma warning restore 618
|
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 Button {
|
new ProgressBar{ Progress = 50 },
|
||||||
Text = "Black background, white text",
|
new Slider{},
|
||||||
Command = new Command (() => {
|
new Stepper{},
|
||||||
rootNavPage.BarTextColor = Color.White;
|
new Switch{},
|
||||||
rootNavPage.BarBackgroundColor = Color.Black;
|
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">
|
<Compile Update="GalleryPages\VisualStateManagerGalleries\OnPlatformExample.xaml.cs">
|
||||||
<DependentUpon>OnPlatformExample.xaml</DependentUpon>
|
<DependentUpon>OnPlatformExample.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<EmbeddedResource Update="GalleryPages\TitleView.xaml">
|
||||||
|
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Update="GalleryPages\VisualStateManagerGalleries\ButtonDisabledStatesGallery.xaml">
|
<EmbeddedResource Update="GalleryPages\VisualStateManagerGalleries\ButtonDisabledStatesGallery.xaml">
|
||||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||||
</EmbeddedResource>
|
</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]
|
[Test]
|
||||||
public async Task NavigationChangedEventArgs ()
|
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 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);
|
static readonly BindablePropertyKey CurrentPagePropertyKey = BindableProperty.CreateReadOnly("CurrentPage", typeof(Page), typeof(NavigationPage), null);
|
||||||
public static readonly BindableProperty CurrentPageProperty = CurrentPagePropertyKey.BindableProperty;
|
public static readonly BindableProperty CurrentPageProperty = CurrentPagePropertyKey.BindableProperty;
|
||||||
|
|
||||||
|
@ -103,6 +105,24 @@ namespace Xamarin.Forms
|
||||||
private set { SetValue(RootPagePropertyKey, value); }
|
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)
|
public static string GetBackButtonTitle(BindableObject page)
|
||||||
{
|
{
|
||||||
return (string)page.GetValue(BackButtonTitleProperty);
|
return (string)page.GetValue(BackButtonTitleProperty);
|
||||||
|
@ -125,6 +145,11 @@ namespace Xamarin.Forms
|
||||||
return (FileImageSource)bindable.GetValue(TitleIconProperty);
|
return (FileImageSource)bindable.GetValue(TitleIconProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static View GetTitleView(BindableObject bindable)
|
||||||
|
{
|
||||||
|
return (View)bindable.GetValue(TitleViewProperty);
|
||||||
|
}
|
||||||
|
|
||||||
public Task<Page> PopAsync()
|
public Task<Page> PopAsync()
|
||||||
{
|
{
|
||||||
return PopAsync(true);
|
return PopAsync(true);
|
||||||
|
@ -222,6 +247,11 @@ namespace Xamarin.Forms
|
||||||
bindable.SetValue(TitleIconProperty, value);
|
bindable.SetValue(TitleIconProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetTitleView(BindableObject bindable, View value)
|
||||||
|
{
|
||||||
|
bindable.SetValue(TitleViewProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool OnBackButtonPressed()
|
protected override bool OnBackButtonPressed()
|
||||||
{
|
{
|
||||||
if (CurrentPage.SendBackButtonPressed())
|
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
|
#endregion
|
||||||
|
|
||||||
|
#region PrefersLargeTitles
|
||||||
public static readonly BindableProperty PrefersLargeTitlesProperty = BindableProperty.Create(nameof(PrefersLargeTitles), typeof(bool), typeof(Page), false);
|
public static readonly BindableProperty PrefersLargeTitlesProperty = BindableProperty.Create(nameof(PrefersLargeTitles), typeof(bool), typeof(Page), false);
|
||||||
|
|
||||||
public static bool GetPrefersLargeTitles(BindableObject element)
|
public static bool GetPrefersLargeTitles(BindableObject element)
|
||||||
|
@ -94,5 +95,31 @@ namespace Xamarin.Forms.PlatformConfiguration.iOSSpecific
|
||||||
{
|
{
|
||||||
return GetPrefersLargeTitles(config.Element);
|
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 FragmentManager = Android.Support.V4.App.FragmentManager;
|
||||||
using FragmentTransaction = Android.Support.V4.App.FragmentTransaction;
|
using FragmentTransaction = Android.Support.V4.App.FragmentTransaction;
|
||||||
using Object = Java.Lang.Object;
|
using Object = Java.Lang.Object;
|
||||||
|
using static Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat.NavigationPage;
|
||||||
using static Android.Views.View;
|
using static Android.Views.View;
|
||||||
|
using System.IO;
|
||||||
|
using Android.Widget;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Platform.Android.AppCompat
|
namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
{
|
{
|
||||||
|
@ -45,6 +48,10 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
DrawerLayout _drawerLayout;
|
DrawerLayout _drawerLayout;
|
||||||
MasterDetailPage _masterDetailPage;
|
MasterDetailPage _masterDetailPage;
|
||||||
bool _toolbarVisible;
|
bool _toolbarVisible;
|
||||||
|
IVisualElementRenderer _titleViewRenderer;
|
||||||
|
Container _titleView;
|
||||||
|
ImageView _titleIconView;
|
||||||
|
ImageSource _imageSource;
|
||||||
bool _isAttachedToWindow;
|
bool _isAttachedToWindow;
|
||||||
bool _didInitialPushPages;
|
bool _didInitialPushPages;
|
||||||
|
|
||||||
|
@ -135,6 +142,22 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
{
|
{
|
||||||
_disposed = true;
|
_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)
|
if (_toolbarTracker != null)
|
||||||
{
|
{
|
||||||
|
@ -312,6 +335,10 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
UpdateToolbar();
|
UpdateToolbar();
|
||||||
else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
|
else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
|
||||||
UpdateToolbar();
|
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)
|
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();
|
int barHeight = ActionBarHeight();
|
||||||
|
|
||||||
|
if (Element.IsSet(BarHeightProperty))
|
||||||
|
barHeight = Element.OnThisPlatform().GetBarHeight();
|
||||||
|
|
||||||
if (barHeight != _lastActionBarHeight && _lastActionBarHeight > 0)
|
if (barHeight != _lastActionBarHeight && _lastActionBarHeight > 0)
|
||||||
{
|
{
|
||||||
ResetToolbar();
|
ResetToolbar();
|
||||||
|
@ -476,6 +506,9 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
UpdateToolbar();
|
UpdateToolbar();
|
||||||
else if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName)
|
else if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName)
|
||||||
UpdateToolbar();
|
UpdateToolbar();
|
||||||
|
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName ||
|
||||||
|
e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||||
|
UpdateToolbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable 1998 // considered for removal
|
#pragma warning disable 1998 // considered for removal
|
||||||
|
@ -646,6 +679,20 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
{
|
{
|
||||||
AToolbar oldToolbar = _toolbar;
|
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.RemoveFromParent();
|
||||||
_toolbar.SetNavigationOnClickListener(null);
|
_toolbar.SetNavigationOnClickListener(null);
|
||||||
_toolbar = null;
|
_toolbar = null;
|
||||||
|
@ -852,6 +899,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
|
|
||||||
bool isNavigated = ((INavigationPageController)Element).StackDepth > 1;
|
bool isNavigated = ((INavigationPageController)Element).StackDepth > 1;
|
||||||
bar.NavigationIcon = null;
|
bar.NavigationIcon = null;
|
||||||
|
Page currentPage = Element.CurrentPage;
|
||||||
|
|
||||||
if (isNavigated)
|
if (isNavigated)
|
||||||
{
|
{
|
||||||
|
@ -861,7 +909,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
toggle.SyncState();
|
toggle.SyncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NavigationPage.GetHasBackButton(Element.CurrentPage))
|
if (NavigationPage.GetHasBackButton(currentPage))
|
||||||
{
|
{
|
||||||
var icon = new DrawerArrowDrawable(activity.SupportActionBar.ThemedContext);
|
var icon = new DrawerArrowDrawable(activity.SupportActionBar.ThemedContext);
|
||||||
icon.Progress = 1;
|
icon.Progress = 1;
|
||||||
|
@ -905,7 +953,112 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
||||||
if (!textColor.IsDefault)
|
if (!textColor.IsDefault)
|
||||||
bar.SetTitleTextColor(textColor.ToAndroid().ToArgb());
|
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)
|
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
|
class DrawerMultiplexedListener : Object, DrawerLayout.IDrawerListener
|
||||||
{
|
{
|
||||||
public List<DrawerLayout.IDrawerListener> Listeners { get; } = new List<DrawerLayout.IDrawerListener>(2);
|
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 Xamarin.Forms.Platform.Android.AppCompat;
|
||||||
using FragmentManager = Android.Support.V4.App.FragmentManager;
|
using FragmentManager = Android.Support.V4.App.FragmentManager;
|
||||||
using Xamarin.Forms.Internals;
|
using Xamarin.Forms.Internals;
|
||||||
|
using AView = Android.Views.View;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Platform.Android
|
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.");
|
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.")]
|
[Obsolete("CreateRenderer(VisualElement) is obsolete as of version 2.5. Please use CreateRendererWithContext(VisualElement, Context) instead.")]
|
||||||
public static IVisualElementRenderer CreateRenderer(VisualElement element)
|
public static IVisualElementRenderer CreateRenderer(VisualElement element)
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Xamarin.Forms.Platform.Android
|
||||||
{
|
{
|
||||||
if (_headerRenderer != null)
|
if (_headerRenderer != null)
|
||||||
{
|
{
|
||||||
ClearRenderer(_headerRenderer.View);
|
Platform.ClearRenderer(_headerRenderer.View);
|
||||||
_headerRenderer.Dispose();
|
_headerRenderer.Dispose();
|
||||||
_headerRenderer = null;
|
_headerRenderer = null;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ namespace Xamarin.Forms.Platform.Android
|
||||||
|
|
||||||
if (_footerRenderer != null)
|
if (_footerRenderer != null)
|
||||||
{
|
{
|
||||||
ClearRenderer(_footerRenderer.View);
|
Platform.ClearRenderer(_footerRenderer.View);
|
||||||
_footerRenderer.Dispose();
|
_footerRenderer.Dispose();
|
||||||
_footerRenderer = null;
|
_footerRenderer = null;
|
||||||
}
|
}
|
||||||
|
@ -286,23 +286,6 @@ namespace Xamarin.Forms.Platform.Android
|
||||||
Control.SetSelectionFromTop(realPositionWithHeader, y);
|
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()
|
void UpdateFooter()
|
||||||
{
|
{
|
||||||
var footer = (VisualElement)Controller.FooterElement;
|
var footer = (VisualElement)Controller.FooterElement;
|
||||||
|
@ -314,7 +297,7 @@ namespace Xamarin.Forms.Platform.Android
|
||||||
{
|
{
|
||||||
if (_footerView != null)
|
if (_footerView != null)
|
||||||
_footerView.Child = null;
|
_footerView.Child = null;
|
||||||
ClearRenderer(_footerRenderer.View);
|
Platform.ClearRenderer(_footerRenderer.View);
|
||||||
_footerRenderer.Dispose();
|
_footerRenderer.Dispose();
|
||||||
_footerRenderer = null;
|
_footerRenderer = null;
|
||||||
}
|
}
|
||||||
|
@ -346,7 +329,7 @@ namespace Xamarin.Forms.Platform.Android
|
||||||
{
|
{
|
||||||
if (_headerView != null)
|
if (_headerView != null)
|
||||||
_headerView.Child = null;
|
_headerView.Child = null;
|
||||||
ClearRenderer(_headerRenderer.View);
|
Platform.ClearRenderer(_headerRenderer.View);
|
||||||
_headerRenderer.Dispose();
|
_headerRenderer.Dispose();
|
||||||
_headerRenderer = null;
|
_headerRenderer = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Input;
|
using Windows.UI.Xaml.Input;
|
||||||
|
using Xamarin.Forms.Internals;
|
||||||
|
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Platform.UWP
|
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 });
|
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)
|
internal static InputScopeNameValue GetKeyboardButtonType(this ReturnType returnType)
|
||||||
{
|
{
|
||||||
switch (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.Controls;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
||||||
|
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Platform.UWP
|
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 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),
|
public static readonly DependencyProperty ToolbarForegroundProperty = DependencyProperty.Register("ToolbarForeground", typeof(Brush), typeof(MasterDetailControl),
|
||||||
new PropertyMetadata(default(Brush)));
|
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),
|
public static readonly DependencyProperty DetailTitleVisibilityProperty = DependencyProperty.Register("DetailTitleVisibility", typeof(Visibility), typeof(MasterDetailControl),
|
||||||
new PropertyMetadata(default(Visibility)));
|
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),
|
public static readonly DependencyProperty MasterToolbarVisibilityProperty = DependencyProperty.Register("MasterToolbarVisibility", typeof(Visibility), typeof(MasterDetailControl),
|
||||||
new PropertyMetadata(default(Visibility)));
|
new PropertyMetadata(default(Visibility)));
|
||||||
|
|
||||||
|
@ -66,6 +74,7 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
FrameworkElement _detailPresenter;
|
FrameworkElement _detailPresenter;
|
||||||
SplitView _split;
|
SplitView _split;
|
||||||
ToolbarPlacement _toolbarPlacement;
|
ToolbarPlacement _toolbarPlacement;
|
||||||
|
FrameworkElement _titleViewPresenter;
|
||||||
|
|
||||||
public MasterDetailControl()
|
public MasterDetailControl()
|
||||||
{
|
{
|
||||||
|
@ -110,12 +119,30 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
set { SetValue(DetailTitleProperty, value); }
|
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
|
public Visibility DetailTitleVisibility
|
||||||
{
|
{
|
||||||
get { return (Visibility)GetValue(DetailTitleVisibilityProperty); }
|
get { return (Visibility)GetValue(DetailTitleVisibilityProperty); }
|
||||||
set { SetValue(DetailTitleVisibilityProperty, value); }
|
set { SetValue(DetailTitleVisibilityProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Visibility DetailTitleViewVisibility
|
||||||
|
{
|
||||||
|
get { return (Visibility)GetValue(DetailTitleViewVisibilityProperty); }
|
||||||
|
set { SetValue(DetailTitleViewVisibilityProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsPaneOpen
|
public bool IsPaneOpen
|
||||||
{
|
{
|
||||||
get { return (bool)GetValue(IsPaneOpenProperty); }
|
get { return (bool)GetValue(IsPaneOpenProperty); }
|
||||||
|
@ -260,6 +287,7 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
_masterPresenter = GetTemplateChild("MasterPresenter") as FrameworkElement;
|
_masterPresenter = GetTemplateChild("MasterPresenter") as FrameworkElement;
|
||||||
_detailPresenter = GetTemplateChild("DetailPresenter") as FrameworkElement;
|
_detailPresenter = GetTemplateChild("DetailPresenter") as FrameworkElement;
|
||||||
|
_titleViewPresenter = GetTemplateChild("TitleViewPresenter") as FrameworkElement;
|
||||||
|
|
||||||
_commandBar = GetTemplateChild("CommandBar") as CommandBar;
|
_commandBar = GetTemplateChild("CommandBar") as CommandBar;
|
||||||
_toolbarPlacementHelper.Initialize(_commandBar, () => ToolbarPlacement, GetTemplateChild);
|
_toolbarPlacementHelper.Initialize(_commandBar, () => ToolbarPlacement, GetTemplateChild);
|
||||||
|
@ -285,11 +313,24 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
((MasterDetailControl)dependencyObject).UpdateMode();
|
((MasterDetailControl)dependencyObject).UpdateMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void OnTitleViewPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
((MasterDetailControl)dependencyObject).UpdateTitleViewPresenter();
|
||||||
|
}
|
||||||
|
|
||||||
void OnToggleClicked(object sender, RoutedEventArgs args)
|
void OnToggleClicked(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
IsPaneOpen = !IsPaneOpen;
|
IsPaneOpen = !IsPaneOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnTitleViewPresenterLoaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DetailTitleView == null || _titleViewPresenter == null || _commandBar == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_titleViewPresenter.Width = _commandBar.ActualWidth;
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateMode()
|
void UpdateMode()
|
||||||
{
|
{
|
||||||
if (_split == null)
|
if (_split == null)
|
||||||
|
@ -324,5 +365,23 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
_firstLoad = true;
|
_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>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Border x:Name="TopCommandBarArea" HorizontalAlignment="Stretch" Background="{TemplateBinding ToolbarBackground}">
|
<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>
|
<uwp:FormsCommandBar.Content>
|
||||||
<Border x:Name="TitleArea" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding DetailTitleVisibility}">
|
<Border x:Name="TitleArea" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding DetailTitleVisibility}" HorizontalAlignment="Stretch">
|
||||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Background="{TemplateBinding ToolbarBackground}" >
|
<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}" />
|
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}" />
|
<TextBlock Text="{TemplateBinding DetailTitle}" VerticalAlignment="Center" Margin="10,0,0,0" Foreground="{TemplateBinding ToolbarForeground}" Style="{ThemeResource TitleTextBlockStyle}" />
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
</StackPanel>
|
<ContentPresenter Grid.Column="3" Content="{Binding DetailTitleView, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource ViewToRenderer}}" Visibility="{TemplateBinding DetailTitleViewVisibility}" HorizontalAlignment="Stretch" />
|
||||||
|
|
||||||
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</uwp:FormsCommandBar.Content>
|
</uwp:FormsCommandBar.Content>
|
||||||
</uwp:FormsCommandBar>
|
</uwp:FormsCommandBar>
|
||||||
|
|
|
@ -7,10 +7,11 @@ using Windows.UI.Xaml.Data;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
||||||
using Specifics = Xamarin.Forms.PlatformConfiguration.WindowsSpecific.MasterDetailPage;
|
using Specifics = Xamarin.Forms.PlatformConfiguration.WindowsSpecific.MasterDetailPage;
|
||||||
|
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Platform.UWP
|
namespace Xamarin.Forms.Platform.UWP
|
||||||
{
|
{
|
||||||
public class MasterDetailPageRenderer : IVisualElementRenderer, IToolbarProvider, ITitleProvider, IToolBarForegroundBinder
|
public class MasterDetailPageRenderer : IVisualElementRenderer, IToolbarProvider, ITitleProvider, ITitleIconProvider, ITitleViewProvider, IToolBarForegroundBinder
|
||||||
{
|
{
|
||||||
Page _master;
|
Page _master;
|
||||||
Page _detail;
|
Page _detail;
|
||||||
|
@ -97,6 +98,27 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
get { return Element; }
|
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
|
#pragma warning disable 0067 // Revisit: Can't remove; required by interface
|
||||||
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
||||||
#pragma warning restore
|
#pragma warning restore
|
||||||
|
@ -176,6 +198,10 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
{
|
{
|
||||||
((ITitleProvider)this).ShowTitle = false;
|
((ITitleProvider)this).ShowTitle = false;
|
||||||
|
|
||||||
|
var titleView = ((ITitleViewProvider)this).TitleView;
|
||||||
|
titleView?.ClearValue(Platform.RendererProperty);
|
||||||
|
titleView = null;
|
||||||
|
|
||||||
if (_detail == null)
|
if (_detail == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -219,8 +245,18 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
void OnDetailPropertyChanged(object sender, PropertyChangedEventArgs e)
|
void OnDetailPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.PropertyName == Page.TitleProperty.PropertyName || e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
|
if (e.PropertyName == Page.TitleProperty.PropertyName)
|
||||||
UpdateDetailTitle();
|
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)
|
void OnIsPaneOpenChanged(DependencyObject sender, DependencyProperty dp)
|
||||||
|
@ -268,6 +304,8 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
Control.Detail = element;
|
Control.Detail = element;
|
||||||
UpdateDetailTitle();
|
UpdateDetailTitle();
|
||||||
|
UpdateDetailTitleIcon();
|
||||||
|
UpdateDetailTitleView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateDetailTitle()
|
void UpdateDetailTitle()
|
||||||
|
@ -279,6 +317,24 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
(this as ITitleProvider).ShowTitle = !string.IsNullOrEmpty(Control.DetailTitle);
|
(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()
|
void UpdateFlowDirection()
|
||||||
{
|
{
|
||||||
Control.UpdateFlowDirection(Element);
|
Control.UpdateFlowDirection(Element);
|
||||||
|
@ -317,6 +373,8 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
void UpdateMode()
|
void UpdateMode()
|
||||||
{
|
{
|
||||||
UpdateDetailTitle();
|
UpdateDetailTitle();
|
||||||
|
UpdateDetailTitleIcon();
|
||||||
|
UpdateDetailTitleView();
|
||||||
Control.CollapseStyle = Element.OnThisPlatform().GetCollapseStyle();
|
Control.CollapseStyle = Element.OnThisPlatform().GetCollapseStyle();
|
||||||
Control.CollapsedPaneWidth = Element.OnThisPlatform().CollapsedPaneWidth();
|
Control.CollapsedPaneWidth = Element.OnThisPlatform().CollapsedPaneWidth();
|
||||||
Control.ShouldShowSplitMode = Element.ShouldShowSplitMode;
|
Control.ShouldShowSplitMode = Element.ShouldShowSplitMode;
|
||||||
|
@ -352,4 +410,4 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath("Control.ToolbarForeground"), Source = this, RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent } });
|
new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath("Control.ToolbarForeground"), Source = this, RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,14 @@ using Windows.UI.Xaml.Input;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
using Windows.UI.Xaml.Media.Animation;
|
using Windows.UI.Xaml.Media.Animation;
|
||||||
using Xamarin.Forms.Internals;
|
using Xamarin.Forms.Internals;
|
||||||
|
using static Xamarin.Forms.PlatformConfiguration.WindowsSpecific.Page;
|
||||||
|
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||||
|
|
||||||
|
|
||||||
using Windows.UI.Core;
|
using Windows.UI.Core;
|
||||||
namespace Xamarin.Forms.Platform.UWP
|
namespace Xamarin.Forms.Platform.UWP
|
||||||
{
|
{
|
||||||
public partial class NavigationPageRenderer : IVisualElementRenderer, ITitleProvider, IToolbarProvider
|
public partial class NavigationPageRenderer : IVisualElementRenderer, ITitleProvider, ITitleIconProvider, ITitleViewProvider, IToolbarProvider
|
||||||
{
|
{
|
||||||
PageControl _container;
|
PageControl _container;
|
||||||
Page _currentPage;
|
Page _currentPage;
|
||||||
|
@ -27,6 +29,7 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
MasterDetailPage _parentMasterDetailPage;
|
MasterDetailPage _parentMasterDetailPage;
|
||||||
TabbedPage _parentTabbedPage;
|
TabbedPage _parentTabbedPage;
|
||||||
bool _showTitle = true;
|
bool _showTitle = true;
|
||||||
|
WImageSource _titleIcon;
|
||||||
VisualElementTracker<Page, PageControl> _tracker;
|
VisualElementTracker<Page, PageControl> _tracker;
|
||||||
EntranceThemeTransition _transition;
|
EntranceThemeTransition _transition;
|
||||||
|
|
||||||
|
@ -88,7 +91,25 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
{
|
{
|
||||||
get { return _currentPage?.Title; }
|
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()
|
Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
|
||||||
|
@ -175,6 +196,8 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
UpdateTitleColor();
|
UpdateTitleColor();
|
||||||
UpdateNavigationBarBackground();
|
UpdateNavigationBarBackground();
|
||||||
UpdateToolbarPlacement();
|
UpdateToolbarPlacement();
|
||||||
|
UpdateTitleIcon();
|
||||||
|
UpdateTitleView();
|
||||||
|
|
||||||
// Enforce consistency rules on toolbar (show toolbar if top-level page is Navigation Page)
|
// Enforce consistency rules on toolbar (show toolbar if top-level page is Navigation Page)
|
||||||
_container.ShouldShowToolbar = _parentMasterDetailPage == null && _parentTabbedPage == null;
|
_container.ShouldShowToolbar = _parentMasterDetailPage == null && _parentTabbedPage == null;
|
||||||
|
@ -283,12 +306,20 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
UpdateShowTitle();
|
UpdateShowTitle();
|
||||||
|
|
||||||
UpdateTitleOnParents();
|
UpdateTitleOnParents();
|
||||||
|
|
||||||
|
UpdateTitleIcon();
|
||||||
|
|
||||||
|
UpdateTitleView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiPagePropertyChanged(object sender, PropertyChangedEventArgs e)
|
void MultiPagePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.PropertyName == "CurrentPage" || e.PropertyName == "Detail")
|
if (e.PropertyName == "CurrentPage" || e.PropertyName == "Detail")
|
||||||
|
{
|
||||||
UpdateTitleOnParents();
|
UpdateTitleOnParents();
|
||||||
|
UpdateTitleIcon();
|
||||||
|
UpdateTitleView();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async void OnBackClicked(object sender, RoutedEventArgs e)
|
async void OnBackClicked(object sender, RoutedEventArgs e)
|
||||||
|
@ -311,6 +342,10 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
UpdateTitleVisible();
|
UpdateTitleVisible();
|
||||||
else if (e.PropertyName == Page.TitleProperty.PropertyName)
|
else if (e.PropertyName == Page.TitleProperty.PropertyName)
|
||||||
UpdateTitleOnParents();
|
UpdateTitleOnParents();
|
||||||
|
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName)
|
||||||
|
UpdateTitleIcon();
|
||||||
|
else if (e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||||
|
UpdateTitleView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnElementAppearing(object sender, EventArgs e)
|
void OnElementAppearing(object sender, EventArgs e)
|
||||||
|
@ -327,9 +362,12 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
UpdateNavigationBarBackground();
|
UpdateNavigationBarBackground();
|
||||||
else if (e.PropertyName == Page.PaddingProperty.PropertyName)
|
else if (e.PropertyName == Page.PaddingProperty.PropertyName)
|
||||||
UpdatePadding();
|
UpdatePadding();
|
||||||
|
else if (e.PropertyName == ToolbarPlacementProperty.PropertyName)
|
||||||
else if (e.PropertyName == PlatformConfiguration.WindowsSpecific.Page.ToolbarPlacementProperty.PropertyName)
|
|
||||||
UpdateToolbarPlacement();
|
UpdateToolbarPlacement();
|
||||||
|
else if (e.PropertyName == NavigationPage.TitleIconProperty.PropertyName)
|
||||||
|
UpdateTitleIcon();
|
||||||
|
else if (e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
|
||||||
|
UpdateTitleView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnLoaded(object sender, RoutedEventArgs args)
|
void OnLoaded(object sender, RoutedEventArgs args)
|
||||||
|
@ -424,6 +462,8 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
UpdateTitleVisible();
|
UpdateTitleVisible();
|
||||||
UpdateTitleOnParents();
|
UpdateTitleOnParents();
|
||||||
|
UpdateTitleIcon();
|
||||||
|
UpdateTitleView();
|
||||||
|
|
||||||
if (isAnimated && _transition == null)
|
if (isAnimated && _transition == null)
|
||||||
{
|
{
|
||||||
|
@ -484,5 +524,34 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
{
|
{
|
||||||
(this as ITitleProvider).BarForegroundBrush = GetBarForegroundBrush();
|
(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;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
|
||||||
|
using WImageSource = Windows.UI.Xaml.Media.ImageSource;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Platform.UWP
|
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),
|
public static readonly DependencyProperty ContentMarginProperty = DependencyProperty.Register("ContentMargin", typeof(Windows.UI.Xaml.Thickness), typeof(PageControl),
|
||||||
new PropertyMetadata(default(Windows.UI.Xaml.Thickness)));
|
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 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));
|
public static readonly DependencyProperty TitleBrushProperty = DependencyProperty.Register("TitleBrush", typeof(Brush), typeof(PageControl), new PropertyMetadata(null));
|
||||||
|
|
||||||
AppBarButton _backButton;
|
AppBarButton _backButton;
|
||||||
CommandBar _commandBar;
|
CommandBar _commandBar;
|
||||||
|
FrameworkElement _titleViewPresenter;
|
||||||
|
|
||||||
ToolbarPlacement _toolbarPlacement;
|
ToolbarPlacement _toolbarPlacement;
|
||||||
readonly ToolbarPlacementHelper _toolbarPlacementHelper = new ToolbarPlacementHelper();
|
readonly ToolbarPlacementHelper _toolbarPlacementHelper = new ToolbarPlacementHelper();
|
||||||
|
@ -40,6 +48,18 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
set { _toolbarPlacementHelper.ShouldShowToolBar = value; }
|
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;
|
TaskCompletionSource<CommandBar> _commandBarTcs;
|
||||||
Windows.UI.Xaml.Controls.ContentPresenter _presenter;
|
Windows.UI.Xaml.Controls.ContentPresenter _presenter;
|
||||||
|
|
||||||
|
@ -105,6 +125,12 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
set { SetValue(TitleVisibilityProperty, value); }
|
set { SetValue(TitleVisibilityProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Visibility TitleViewVisibility
|
||||||
|
{
|
||||||
|
get { return (Visibility)GetValue(TitleViewVisibilityProperty); }
|
||||||
|
set { SetValue(TitleViewVisibilityProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
public Brush TitleBrush
|
public Brush TitleBrush
|
||||||
{
|
{
|
||||||
get { return (Brush)GetValue(TitleBrushProperty); }
|
get { return (Brush)GetValue(TitleBrushProperty); }
|
||||||
|
@ -139,6 +165,8 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
_presenter = GetTemplateChild("presenter") as Windows.UI.Xaml.Controls.ContentPresenter;
|
_presenter = GetTemplateChild("presenter") as Windows.UI.Xaml.Controls.ContentPresenter;
|
||||||
|
|
||||||
|
_titleViewPresenter = GetTemplateChild("TitleViewPresenter") as FrameworkElement;
|
||||||
|
|
||||||
_commandBar = GetTemplateChild("CommandBar") as CommandBar;
|
_commandBar = GetTemplateChild("CommandBar") as CommandBar;
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,6 +193,19 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
((PageControl)dependencyObject).UpdateBackButton();
|
((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()
|
void UpdateBackButton()
|
||||||
{
|
{
|
||||||
if (_backButton == null)
|
if (_backButton == null)
|
||||||
|
@ -177,5 +218,23 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
|
|
||||||
_backButton.Opacity = ShowBackButton ? 1 : 0;
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,22 +9,38 @@
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate TargetType="uwp:PageControl">
|
<ControlTemplate TargetType="uwp:PageControl">
|
||||||
<Grid Background="{TemplateBinding Background}">
|
<Grid Background="{TemplateBinding Background}">
|
||||||
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Border x:Name="TopCommandBarArea" HorizontalAlignment="Stretch" Background="{TemplateBinding ToolbarBackground}">
|
<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>
|
<uwp:FormsCommandBar.Content>
|
||||||
<Border x:Name="TitleArea" Visibility="{TemplateBinding TitleVisibility}" Height="{ThemeResource TitleBarHeight}">
|
<Border x:Name="TitleArea" Height="{ThemeResource TitleBarHeight}" Visibility="{TemplateBinding TitleVisibility}" HorizontalAlignment="Stretch">
|
||||||
<TextBlock Text="{Binding Title}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="10,0,0,0" Foreground="{TemplateBinding TitleBrush}" Style="{ThemeResource TitleTextBlockStyle}" />
|
<Grid x:Name="TitleViewPresenter" VerticalAlignment="Center" Background="{TemplateBinding ToolbarBackground}" HorizontalAlignment="Stretch">
|
||||||
</Border>
|
|
||||||
</uwp:FormsCommandBar.Content>
|
<Grid.ColumnDefinitions>
|
||||||
</uwp:FormsCommandBar>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Border>
|
<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" />
|
<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;
|
_view.IsInNativeLayout = true;
|
||||||
Layout.LayoutChildIntoBoundingRegion(_view, new Rectangle(0, 0, finalSize.Width, finalSize.Height));
|
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;
|
_view.IsInNativeLayout = false;
|
||||||
|
|
||||||
FrameworkElement?.Arrange(new Rect(_view.X, _view.Y, _view.Width, _view.Height));
|
|
||||||
return finalSize;
|
return finalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ namespace Xamarin.Forms.Platform.UWP
|
||||||
result = new Windows.Foundation.Size(request.Width, request.Height);
|
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);
|
FrameworkElement?.Measure(availableSize);
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,9 @@
|
||||||
<Compile Include="FormsComboBox.cs" />
|
<Compile Include="FormsComboBox.cs" />
|
||||||
<Compile Include="InterceptVisualStateManager.cs" />
|
<Compile Include="InterceptVisualStateManager.cs" />
|
||||||
<Compile Include="HorizontalTextAlignmentConverter.cs" />
|
<Compile Include="HorizontalTextAlignmentConverter.cs" />
|
||||||
|
<Compile Include="ITitleIconProvider.cs" />
|
||||||
<Compile Include="ITitleProvider.cs" />
|
<Compile Include="ITitleProvider.cs" />
|
||||||
|
<Compile Include="ITitleViewProvider.cs" />
|
||||||
<Compile Include="IToolbarProvider.cs" />
|
<Compile Include="IToolbarProvider.cs" />
|
||||||
<Compile Include="NativeBindingExtensions.cs" />
|
<Compile Include="NativeBindingExtensions.cs" />
|
||||||
<Compile Include="NativeEventWrapper.cs" />
|
<Compile Include="NativeEventWrapper.cs" />
|
||||||
|
|
|
@ -13,6 +13,7 @@ using static Xamarin.Forms.PlatformConfiguration.iOSSpecific.NavigationPage;
|
||||||
using PageUIStatusBarAnimation = Xamarin.Forms.PlatformConfiguration.iOSSpecific.UIStatusBarAnimation;
|
using PageUIStatusBarAnimation = Xamarin.Forms.PlatformConfiguration.iOSSpecific.UIStatusBarAnimation;
|
||||||
using PointF = CoreGraphics.CGPoint;
|
using PointF = CoreGraphics.CGPoint;
|
||||||
using RectangleF = CoreGraphics.CGRect;
|
using RectangleF = CoreGraphics.CGRect;
|
||||||
|
using SizeF = CoreGraphics.CGSize;
|
||||||
|
|
||||||
namespace Xamarin.Forms.Platform.iOS
|
namespace Xamarin.Forms.Platform.iOS
|
||||||
{
|
{
|
||||||
|
@ -29,6 +30,8 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
VisualElementTracker _tracker;
|
VisualElementTracker _tracker;
|
||||||
nfloat _navigationBottom = 0;
|
nfloat _navigationBottom = 0;
|
||||||
bool _hasNavigationBar;
|
bool _hasNavigationBar;
|
||||||
|
UIImage _defaultNavBarShadowImage;
|
||||||
|
UIImage _defaultNavBarBackImage;
|
||||||
|
|
||||||
public NavigationRenderer()
|
public NavigationRenderer()
|
||||||
{
|
{
|
||||||
|
@ -45,6 +48,8 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
|
|
||||||
IPageController PageController => Element as IPageController;
|
IPageController PageController => Element as IPageController;
|
||||||
|
|
||||||
|
NavigationPage NavPage => Element as NavigationPage;
|
||||||
|
|
||||||
public VisualElement Element { get; private set; }
|
public VisualElement Element { get; private set; }
|
||||||
|
|
||||||
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
||||||
|
@ -62,7 +67,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
public void SetElement(VisualElement element)
|
public void SetElement(VisualElement element)
|
||||||
{
|
{
|
||||||
var oldElement = Element;
|
var oldElement = Element;
|
||||||
Element = (NavigationPage)element;
|
Element = element;
|
||||||
OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
|
OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
|
||||||
|
|
||||||
if (element != null)
|
if (element != null)
|
||||||
|
@ -84,6 +89,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
get { return this; }
|
get { return this; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: this was deprecated in iOS8.0 and is not called in 9.0+
|
||||||
public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
|
public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
|
||||||
{
|
{
|
||||||
base.DidRotate(fromInterfaceOrientation);
|
base.DidRotate(fromInterfaceOrientation);
|
||||||
|
@ -205,7 +211,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
|
|
||||||
FindParentMasterDetail();
|
FindParentMasterDetail();
|
||||||
|
|
||||||
var navPage = (NavigationPage)Element;
|
var navPage = NavPage;
|
||||||
|
|
||||||
if (navPage.CurrentPage == null)
|
if (navPage.CurrentPage == null)
|
||||||
{
|
{
|
||||||
|
@ -223,6 +229,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
UpdateBarBackgroundColor();
|
UpdateBarBackgroundColor();
|
||||||
UpdateBarTextColor();
|
UpdateBarTextColor();
|
||||||
UpdateUseLargeTitles();
|
UpdateUseLargeTitles();
|
||||||
|
UpdateHideNavigationBarSeparator();
|
||||||
|
|
||||||
// If there is already stuff on the stack we need to push it
|
// If there is already stuff on the stack we need to push it
|
||||||
navPage.Pages.ForEach(async p => await PushPageAsync(p, false));
|
navPage.Pages.ForEach(async p => await PushPageAsync(p, false));
|
||||||
|
@ -255,7 +262,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
_parentMasterDetailPage = null;
|
_parentMasterDetailPage = null;
|
||||||
Current = null; // unhooks events
|
Current = null; // unhooks events
|
||||||
|
|
||||||
var navPage = (NavigationPage)Element;
|
var navPage = NavPage;
|
||||||
navPage.PropertyChanged -= HandlePropertyChanged;
|
navPage.PropertyChanged -= HandlePropertyChanged;
|
||||||
|
|
||||||
navPage.PushRequested -= OnPushRequested;
|
navPage.PushRequested -= OnPushRequested;
|
||||||
|
@ -348,32 +355,8 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
// must pack into container so padding can work
|
// must pack into container so padding can work
|
||||||
// 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 };
|
||||||
if (!string.IsNullOrWhiteSpace(page.Title))
|
|
||||||
pack.NavigationItem.Title = page.Title;
|
|
||||||
|
|
||||||
// First page and we have a master detail to contend with
|
UpdateTitleArea(pack, page);
|
||||||
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 };
|
|
||||||
}
|
|
||||||
|
|
||||||
var pageRenderer = Platform.GetRenderer(page);
|
var pageRenderer = Platform.GetRenderer(page);
|
||||||
pack.View.AddSubview(pageRenderer.ViewController.View);
|
pack.View.AddSubview(pageRenderer.ViewController.View);
|
||||||
|
@ -383,17 +366,11 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
return pack;
|
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()
|
void FindParentMasterDetail()
|
||||||
{
|
{
|
||||||
var parentPages = ((Page)Element).GetParentPages();
|
Page page = Element as Page;
|
||||||
|
|
||||||
|
var parentPages = page.GetParentPages();
|
||||||
var masterDetail = parentPages.OfType<MasterDetailPage>().FirstOrDefault();
|
var masterDetail = parentPages.OfType<MasterDetailPage>().FirstOrDefault();
|
||||||
|
|
||||||
if (masterDetail != null && parentPages.Append((Page)Element).Contains(masterDetail.Detail))
|
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
|
#pragma warning disable 0618 //retaining legacy call to obsolete code
|
||||||
if (e.PropertyName == NavigationPage.TintProperty.PropertyName)
|
if (e.PropertyName == NavigationPage.TintProperty.PropertyName)
|
||||||
#pragma warning restore 0618
|
#pragma warning restore 0618
|
||||||
|
{
|
||||||
UpdateTint();
|
UpdateTint();
|
||||||
if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
|
}
|
||||||
|
else if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
|
||||||
|
{
|
||||||
UpdateBarBackgroundColor();
|
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();
|
UpdateBarTextColor();
|
||||||
SetStatusBarStyle();
|
SetStatusBarStyle();
|
||||||
}
|
}
|
||||||
else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
|
else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
|
||||||
|
{
|
||||||
UpdateBackgroundColor();
|
UpdateBackgroundColor();
|
||||||
|
}
|
||||||
else if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
|
else if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
|
||||||
{
|
{
|
||||||
Current = ((NavigationPage)Element).CurrentPage;
|
Current = NavPage?.CurrentPage;
|
||||||
ValidateNavbarExists(Current);
|
ValidateNavbarExists(Current);
|
||||||
}
|
}
|
||||||
|
else if (e.PropertyName == IsNavigationBarTranslucentProperty.PropertyName)
|
||||||
else if (e.PropertyName == PlatformConfiguration.iOSSpecific.NavigationPage.IsNavigationBarTranslucentProperty.PropertyName)
|
{
|
||||||
UpdateTranslucent();
|
UpdateTranslucent();
|
||||||
|
}
|
||||||
else if (e.PropertyName == PreferredStatusBarUpdateAnimationProperty.PropertyName)
|
else if (e.PropertyName == PreferredStatusBarUpdateAnimationProperty.PropertyName)
|
||||||
|
{
|
||||||
UpdateCurrentPagePreferredStatusBarUpdateAnimation();
|
UpdateCurrentPagePreferredStatusBarUpdateAnimation();
|
||||||
|
}
|
||||||
else if (e.PropertyName == PrefersLargeTitlesProperty.PropertyName)
|
else if (e.PropertyName == PrefersLargeTitlesProperty.PropertyName)
|
||||||
|
{
|
||||||
UpdateUseLargeTitles();
|
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)
|
void ValidateNavbarExists(Page newCurrentPage)
|
||||||
|
@ -468,6 +466,33 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
ViewDidLayoutSubviews();
|
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()
|
void UpdateCurrentPagePreferredStatusBarUpdateAnimation()
|
||||||
{
|
{
|
||||||
// Not using the extension method syntax here because for some reason it confuses the mono compiler
|
// 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()
|
void UpdateUseLargeTitles()
|
||||||
{
|
{
|
||||||
var navPage = (Element as NavigationPage);
|
if (Forms.IsiOS11OrNewer && NavPage != null)
|
||||||
if (Forms.IsiOS11OrNewer && navPage != null)
|
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 = ((NavigationPage)Element).OnThisPlatform().IsNavigationBarTranslucent();
|
NavigationBar.Translucent = NavPage.OnThisPlatform().IsNavigationBarTranslucent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertPageBefore(Page page, Page before)
|
void InsertPageBefore(Page page, Page before)
|
||||||
|
@ -591,7 +727,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
|
|
||||||
void UpdateBarBackgroundColor()
|
void UpdateBarBackgroundColor()
|
||||||
{
|
{
|
||||||
var barBackgroundColor = ((NavigationPage)Element).BarBackgroundColor;
|
var barBackgroundColor = NavPage.BarBackgroundColor;
|
||||||
// Set navigation bar background color
|
// Set navigation bar background color
|
||||||
NavigationBar.BarTintColor = barBackgroundColor == Color.Default
|
NavigationBar.BarTintColor = barBackgroundColor == Color.Default
|
||||||
? UINavigationBar.Appearance.BarTintColor
|
? UINavigationBar.Appearance.BarTintColor
|
||||||
|
@ -600,7 +736,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
|
|
||||||
void UpdateBarTextColor()
|
void UpdateBarTextColor()
|
||||||
{
|
{
|
||||||
var barTextColor = ((NavigationPage)Element).BarTextColor;
|
var barTextColor = NavPage.BarTextColor;
|
||||||
|
|
||||||
var globalAttributes = UINavigationBar.Appearance.GetTitleTextAttributes();
|
var globalAttributes = UINavigationBar.Appearance.GetTitleTextAttributes();
|
||||||
|
|
||||||
|
@ -626,14 +762,14 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
NavigationBar.TitleTextAttributes = titleAttributes;
|
NavigationBar.TitleTextAttributes = titleAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Forms.IsiOS11OrNewer)
|
if (Forms.IsiOS11OrNewer)
|
||||||
{
|
{
|
||||||
var globalLargeTitleAttributes = UINavigationBar.Appearance.LargeTitleTextAttributes;
|
var globalLargeTitleAttributes = UINavigationBar.Appearance.LargeTitleTextAttributes;
|
||||||
if(globalLargeTitleAttributes == null)
|
if (globalLargeTitleAttributes == null)
|
||||||
NavigationBar.LargeTitleTextAttributes = NavigationBar.TitleTextAttributes;
|
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)
|
// set Tint color (i. e. Back Button arrow and Text)
|
||||||
NavigationBar.TintColor = barTextColor == Color.Default || statusBarColorMode == StatusBarTextColorMode.DoNotAdjust
|
NavigationBar.TintColor = barTextColor == Color.Default || statusBarColorMode == StatusBarTextColorMode.DoNotAdjust
|
||||||
|
@ -643,8 +779,8 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
|
|
||||||
void SetStatusBarStyle()
|
void SetStatusBarStyle()
|
||||||
{
|
{
|
||||||
var barTextColor = ((NavigationPage)Element).BarTextColor;
|
var barTextColor = NavPage.BarTextColor;
|
||||||
var statusBarColorMode = (Element as NavigationPage).OnThisPlatform().GetStatusBarTextColorMode();
|
var statusBarColorMode = NavPage.OnThisPlatform().GetStatusBarTextColorMode();
|
||||||
|
|
||||||
if (statusBarColorMode == StatusBarTextColorMode.DoNotAdjust || barTextColor.Luminosity <= 0.5)
|
if (statusBarColorMode == StatusBarTextColorMode.DoNotAdjust || barTextColor.Luminosity <= 0.5)
|
||||||
{
|
{
|
||||||
|
@ -663,7 +799,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
if (containerController == null)
|
if (containerController == null)
|
||||||
return;
|
return;
|
||||||
var currentChild = containerController.Child;
|
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)
|
if ((firstPage != pageBeingRemoved && currentChild != firstPage && NavigationPage.GetHasBackButton(currentChild)) || _parentMasterDetailPage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -673,7 +809,7 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
void UpdateTint()
|
void UpdateTint()
|
||||||
{
|
{
|
||||||
#pragma warning disable 0618 //retaining legacy call to obsolete code
|
#pragma warning disable 0618 //retaining legacy call to obsolete code
|
||||||
var tintColor = ((NavigationPage)Element).Tint;
|
var tintColor = NavPage.Tint;
|
||||||
#pragma warning restore 0618
|
#pragma warning restore 0618
|
||||||
NavigationBar.BarTintColor = tintColor == Color.Default
|
NavigationBar.BarTintColor = tintColor == Color.Default
|
||||||
? UINavigationBar.Appearance.BarTintColor
|
? UINavigationBar.Appearance.BarTintColor
|
||||||
|
@ -698,16 +834,18 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
_secondaryToolbar.Hidden = true;
|
_secondaryToolbar.Hidden = true;
|
||||||
//secondaryToolbar.Items = null;
|
//secondaryToolbar.Items = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TopViewController?.NavigationItem?.TitleView?.SizeToFit();
|
||||||
|
TopViewController?.NavigationItem?.TitleView?.LayoutSubviews();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task UpdateFormsInnerNavigation(Page pageBeingRemoved)
|
internal async Task UpdateFormsInnerNavigation(Page pageBeingRemoved)
|
||||||
{
|
{
|
||||||
var navPage = Element as NavigationPage;
|
if (NavPage == null)
|
||||||
if (navPage == null)
|
|
||||||
return;
|
return;
|
||||||
_ignorePopCall = true;
|
_ignorePopCall = true;
|
||||||
if (Element.Navigation.NavigationStack.Contains(pageBeingRemoved))
|
if (Element.Navigation.NavigationStack.Contains(pageBeingRemoved))
|
||||||
await (navPage as INavigationPageController)?.RemoveAsyncInner(pageBeingRemoved, false, true);
|
await (NavPage as INavigationPageController)?.RemoveAsyncInner(pageBeingRemoved, false, true);
|
||||||
_ignorePopCall = false;
|
_ignorePopCall = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -968,6 +1106,13 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
UpdatePrefersStatusBarHidden();
|
UpdatePrefersStatusBarHidden();
|
||||||
else if (e.PropertyName == LargeTitleDisplayProperty.PropertyName)
|
else if (e.PropertyName == LargeTitleDisplayProperty.PropertyName)
|
||||||
UpdateLargeTitles();
|
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()
|
void UpdatePrefersStatusBarHidden()
|
||||||
|
@ -1116,5 +1261,102 @@ namespace Xamarin.Forms.Platform.iOS
|
||||||
{
|
{
|
||||||
VisualElementRenderer<VisualElement>.RegisterEffect(effect, View);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Загрузка…
Ссылка в новой задаче