Merge branch '4.8.0' into 5.0.0
This commit is contained in:
Коммит
d825f18ef8
|
@ -0,0 +1,51 @@
|
|||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
using Xamarin.UITest;
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
#if UITEST
|
||||
[Category(UITestCategories.ManualReview)]
|
||||
#endif
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 12153, "Setting FontFamily to pre-installed fonts on UWP crashes", PlatformAffected.UWP)]
|
||||
public class Issue12153 : TestContentPage // or TestMasterDetailPage, etc ...
|
||||
{
|
||||
protected override void Init()
|
||||
{
|
||||
Content = new StackLayout()
|
||||
{
|
||||
Children =
|
||||
{
|
||||
// Setting the font family to "Tahoma" or any other built-in Windows font would crash on UWP
|
||||
new Label() { Text = "Four bell icons should be visible below and it shouldn't crash on UWP", FontFamily = "Tahoma", Margin = new Thickness(10), AutomationId = "Success"},
|
||||
|
||||
new Label { FontFamily = "FontAwesome", FontSize = 50, TextColor = Color.Black, Text = "\xf0f3" },
|
||||
new Label { FontFamily = "fa-regular-400.ttf", FontSize = 50, TextColor = Color.Black, Text = "\xf0f3" },
|
||||
new Image() { Source = new FontImageSource() { FontFamily = "FontAwesome", Glyph = "\xf0f3", Color = Color.Black, Size = 50}, HorizontalOptions = LayoutOptions.Start},
|
||||
new Image() { Source = new FontImageSource() { FontFamily = "fa-regular-400.ttf", Glyph = "\xf0f3", Color = Color.Black, Size = 50}, HorizontalOptions = LayoutOptions.Start},
|
||||
|
||||
new Label() { Text = "This text should be shown using the Lobster font, which is included as an asset", FontFamily = "Lobster-Regular", Margin = new Thickness(10)},
|
||||
|
||||
|
||||
new Label() { Text = "Below a PLAY icon should be visible (if the \"Segoe MDL2 Assets\" font is installed)", Margin = new Thickness(10)},
|
||||
|
||||
new Image() { Source = new FontImageSource{Glyph = "\xe102",FontFamily = "Segoe MDL2 Assets", Size = 50, Color = Color.Green}, HorizontalOptions = LayoutOptions.Start },
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if UITEST
|
||||
[Test]
|
||||
public void InvalidFontDoesntCauseAppToCrash()
|
||||
{
|
||||
RunningApp.WaitForElement("Success");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewGroupTypeIssue.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue12153.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue10324.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Github9536.xaml.cs">
|
||||
<DependentUpon>Github9536.xaml</DependentUpon>
|
||||
|
|
|
@ -109,12 +109,27 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
static string FindFontFamilyName(string fontFile)
|
||||
{
|
||||
using (var fontSet = new CanvasFontSet(new Uri(fontFile)))
|
||||
try
|
||||
{
|
||||
if (fontSet.Fonts.Count == 0)
|
||||
return null;
|
||||
var fontUri = new Uri(fontFile, UriKind.RelativeOrAbsolute);
|
||||
|
||||
return fontSet.GetPropertyValues(CanvasFontPropertyIdentifier.FamilyName).FirstOrDefault().Value;
|
||||
// CanvasFontSet only supports ms-appx:// and ms-appdata:// font URIs
|
||||
if (fontUri.IsAbsoluteUri && (fontUri.Scheme == "ms-appx" || fontUri.Scheme == "ms-appdata"))
|
||||
{
|
||||
using (var fontSet = new CanvasFontSet(fontUri))
|
||||
{
|
||||
if (fontSet.Fonts.Count != 0)
|
||||
return fontSet.GetPropertyValues(CanvasFontPropertyIdentifier.FamilyName).FirstOrDefault().Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
// the CanvasFontSet constructor can throw an exception in case something's wrong with the font. It should not crash the app
|
||||
Internals.Log.Warning("Font",$"Error loading font {fontFile}: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,19 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
var device = CanvasDevice.GetSharedDevice();
|
||||
var dpi = Math.Max(_minimumDpi, Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi);
|
||||
|
||||
// There's really no perfect solution to handle font families with fallbacks (comma-separated)
|
||||
// So if the font family has fallbacks, only the first one is taken, because CanvasTextFormat
|
||||
// only supports one font family
|
||||
|
||||
var fontFamily = fontsource.FontFamily.ToFontFamily();
|
||||
var allFamilies = fontFamily.Source.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (allFamilies.Length < 1)
|
||||
return null;
|
||||
|
||||
var textFormat = new CanvasTextFormat
|
||||
{
|
||||
FontFamily = fontsource.FontFamily.ToFontFamily().Source,
|
||||
FontFamily = allFamilies[0],
|
||||
FontSize = (float)fontsource.Size,
|
||||
HorizontalAlignment = CanvasHorizontalAlignment.Center,
|
||||
VerticalAlignment = CanvasVerticalAlignment.Center,
|
||||
|
@ -44,7 +54,7 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
// offset by 1 as we added a 1 inset
|
||||
var x = (float)layout.DrawBounds.X * -1;
|
||||
|
||||
|
||||
ds.DrawTextLayout(layout, x, 1f, iconcolor);
|
||||
}
|
||||
|
||||
|
@ -65,10 +75,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
Foreground = fontImageSource.Color.ToBrush()
|
||||
};
|
||||
|
||||
var uwpFontFamily = fontImageSource.FontFamily.ToFontFamily().Source;
|
||||
var uwpFontFamily = fontImageSource.FontFamily.ToFontFamily();
|
||||
|
||||
if (!string.IsNullOrEmpty(uwpFontFamily))
|
||||
((WFontIconSource)image).FontFamily = new FontFamily(uwpFontFamily);
|
||||
if (!string.IsNullOrEmpty(uwpFontFamily.Source))
|
||||
((WFontIconSource)image).FontFamily = uwpFontFamily;
|
||||
}
|
||||
|
||||
return Task.FromResult(image);
|
||||
|
@ -87,10 +97,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
Foreground = fontImageSource.Color.ToBrush()
|
||||
};
|
||||
|
||||
var uwpFontFamily = fontImageSource.FontFamily.ToFontFamily().Source;
|
||||
var uwpFontFamily = fontImageSource.FontFamily.ToFontFamily();
|
||||
|
||||
if (!string.IsNullOrEmpty(uwpFontFamily))
|
||||
((FontIcon)image).FontFamily = new FontFamily(uwpFontFamily);
|
||||
if (!string.IsNullOrEmpty(uwpFontFamily.Source))
|
||||
((FontIcon)image).FontFamily = uwpFontFamily;
|
||||
}
|
||||
|
||||
return Task.FromResult(image);
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
using System;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
namespace Xamarin.Forms.Platform.iOS
|
||||
{
|
||||
internal class PageLifecycleManager : IDisposable, IDisconnectable
|
||||
{
|
||||
NSObject _activateObserver;
|
||||
NSObject _resignObserver;
|
||||
bool _disposed;
|
||||
bool _appeared;
|
||||
IPageController _pageController;
|
||||
|
||||
public PageLifecycleManager(IPageController pageController)
|
||||
{
|
||||
_pageController = pageController ?? throw new ArgumentNullException("You need to provide a Page Element");
|
||||
|
||||
_activateObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidBecomeActiveNotification, n =>
|
||||
{
|
||||
if (CheckIfWeAreTheCurrentPage())
|
||||
HandlePageAppearing();
|
||||
});
|
||||
|
||||
_resignObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillResignActiveNotification, n =>
|
||||
{
|
||||
if (CheckIfWeAreTheCurrentPage())
|
||||
HandlePageDisappearing();
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
(this as IDisconnectable).Disconnect();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
void IDisconnectable.Disconnect()
|
||||
{
|
||||
if (_activateObserver != null)
|
||||
{
|
||||
NSNotificationCenter.DefaultCenter.RemoveObserver(_activateObserver);
|
||||
_activateObserver = null;
|
||||
}
|
||||
|
||||
if (_resignObserver != null)
|
||||
{
|
||||
NSNotificationCenter.DefaultCenter.RemoveObserver(_resignObserver);
|
||||
_resignObserver = null;
|
||||
}
|
||||
|
||||
HandlePageDisappearing();
|
||||
|
||||
_pageController = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void HandlePageAppearing()
|
||||
{
|
||||
if (_appeared)
|
||||
return;
|
||||
|
||||
_appeared = true;
|
||||
_pageController?.SendAppearing();
|
||||
|
||||
}
|
||||
|
||||
public void HandlePageDisappearing()
|
||||
{
|
||||
if (!_appeared || _pageController == null)
|
||||
return;
|
||||
|
||||
_appeared = false;
|
||||
_pageController.SendDisappearing();
|
||||
}
|
||||
|
||||
public bool Appeared => _appeared;
|
||||
|
||||
bool CheckIfWeAreTheCurrentPage()
|
||||
{
|
||||
if (_pageController == null)
|
||||
return false;
|
||||
|
||||
if (_pageController.RealParent is IPageContainer<Page> multipage)
|
||||
return multipage.CurrentPage == _pageController;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ using System.ComponentModel;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CoreGraphics;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
|
||||
|
@ -20,6 +19,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
public class NavigationRenderer : UINavigationController, IVisualElementRenderer, IEffectControlProvider
|
||||
{
|
||||
internal const string UpdateToolbarButtons = "Xamarin.UpdateToolbarButtons";
|
||||
bool _appeared;
|
||||
bool _ignorePopCall;
|
||||
bool _loaded;
|
||||
FlyoutPage _parentFlyoutPage;
|
||||
|
@ -32,9 +32,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
UIImage _defaultNavBarShadowImage;
|
||||
UIImage _defaultNavBarBackImage;
|
||||
bool _disposed;
|
||||
PageLifecycleManager _pageLifecycleManager;
|
||||
|
||||
[Internals.Preserve(Conditional = true)]
|
||||
[Preserve(Conditional = true)]
|
||||
public NavigationRenderer() : base(typeof(FormsNavigationBar), null)
|
||||
{
|
||||
MessagingCenter.Subscribe<IVisualElementRenderer>(this, UpdateToolbarButtons, sender =>
|
||||
|
@ -72,9 +71,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
Element = element;
|
||||
OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
|
||||
|
||||
_pageLifecycleManager = new PageLifecycleManager(Element as IPageController);
|
||||
|
||||
element?.SendViewInitialized(NativeView);
|
||||
if (element != null)
|
||||
element.SendViewInitialized(NativeView);
|
||||
|
||||
EffectUtilities.RegisterEffectControlProvider(this, oldElement, element);
|
||||
}
|
||||
|
@ -134,7 +132,11 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
public override void ViewDidAppear(bool animated)
|
||||
{
|
||||
_pageLifecycleManager?.HandlePageAppearing();
|
||||
if (!_appeared)
|
||||
{
|
||||
_appeared = true;
|
||||
PageController?.SendAppearing();
|
||||
}
|
||||
|
||||
base.ViewDidAppear(animated);
|
||||
|
||||
|
@ -152,7 +154,11 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
base.ViewDidDisappear(animated);
|
||||
|
||||
_pageLifecycleManager?.HandlePageDisappearing();
|
||||
if (!_appeared || Element == null)
|
||||
return;
|
||||
|
||||
_appeared = false;
|
||||
PageController.SendDisappearing();
|
||||
}
|
||||
|
||||
public override void ViewDidLayoutSubviews()
|
||||
|
@ -275,12 +281,16 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
navPage.PopToRootRequested -= OnPopToRootRequested;
|
||||
navPage.RemovePageRequested -= OnRemovedPageRequested;
|
||||
navPage.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
|
||||
|
||||
_pageLifecycleManager?.Dispose();
|
||||
_pageLifecycleManager = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing && _appeared)
|
||||
{
|
||||
PageController.SendDisappearing();
|
||||
|
||||
_appeared = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
|
||||
|
@ -357,6 +367,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
UpdateBackgroundColor();
|
||||
}
|
||||
|
||||
|
||||
ParentingViewController CreateViewControllerForPage(Page page)
|
||||
{
|
||||
if (Platform.GetRenderer(page) == null)
|
||||
|
|
|
@ -11,11 +11,11 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
public class PageRenderer : UIViewController, IVisualElementRenderer, IEffectControlProvider, IAccessibilityElementsController, IShellContentInsetObserver, IDisconnectable
|
||||
{
|
||||
bool _appeared;
|
||||
bool _disposed;
|
||||
EventTracker _events;
|
||||
VisualElementPackager _packager;
|
||||
VisualElementTracker _tracker;
|
||||
PageLifecycleManager _pageLifecycleManager;
|
||||
|
||||
// storing this into a local variable causes it to not get collected. Do not delete this please
|
||||
PageContainer _pageContainer;
|
||||
|
@ -111,8 +111,6 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
|
||||
|
||||
_pageLifecycleManager = new PageLifecycleManager(Element as IPageController);
|
||||
|
||||
if (element != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(element.AutomationId))
|
||||
|
@ -189,31 +187,33 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
base.ViewDidAppear(animated);
|
||||
|
||||
if (_disposed || Element == null)
|
||||
if (_appeared || _disposed || Element == null)
|
||||
return;
|
||||
|
||||
_appeared = true;
|
||||
UpdateStatusBarPrefersHidden();
|
||||
|
||||
if (Forms.RespondsToSetNeedsUpdateOfHomeIndicatorAutoHidden)
|
||||
SetNeedsUpdateOfHomeIndicatorAutoHidden();
|
||||
|
||||
if (Element.Parent is CarouselPage)
|
||||
return;
|
||||
|
||||
_pageLifecycleManager?.HandlePageAppearing();
|
||||
Page.SendAppearing();
|
||||
}
|
||||
|
||||
public override void ViewDidDisappear(bool animated)
|
||||
{
|
||||
base.ViewDidDisappear(animated);
|
||||
|
||||
if (_disposed || Element == null)
|
||||
if (!_appeared || _disposed || Element == null)
|
||||
return;
|
||||
|
||||
_appeared = false;
|
||||
|
||||
if (Element.Parent is CarouselPage)
|
||||
return;
|
||||
|
||||
_pageLifecycleManager?.HandlePageDisappearing();
|
||||
Page.SendDisappearing();
|
||||
}
|
||||
|
||||
public override void ViewDidLoad()
|
||||
|
@ -264,10 +264,13 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
Element.PropertyChanged -= OnHandlePropertyChanged;
|
||||
Platform.SetRenderer(Element, null);
|
||||
|
||||
if (_appeared)
|
||||
Page.SendDisappearing();
|
||||
|
||||
Element = null;
|
||||
}
|
||||
|
||||
(_pageLifecycleManager as IDisconnectable)?.Disconnect();
|
||||
|
||||
_events?.Disconnect();
|
||||
_packager?.Disconnect();
|
||||
_tracker?.Disconnect();
|
||||
|
@ -282,14 +285,12 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
(this as IDisconnectable).Disconnect();
|
||||
|
||||
_pageLifecycleManager?.Dispose();
|
||||
_events?.Dispose();
|
||||
_packager?.Dispose();
|
||||
_tracker?.Dispose();
|
||||
_events = null;
|
||||
_packager = null;
|
||||
_tracker = null;
|
||||
_pageLifecycleManager = null;
|
||||
|
||||
Element = null;
|
||||
Container?.Dispose();
|
||||
|
@ -377,7 +378,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void UpdateUseSafeArea()
|
||||
{
|
||||
if (Element == null || _pageLifecycleManager == null)
|
||||
if (Element == null)
|
||||
return;
|
||||
|
||||
if (_userOverriddenSafeArea)
|
||||
|
|
|
@ -23,7 +23,6 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
bool? _defaultBarTranslucent;
|
||||
bool _loaded;
|
||||
Size _queuedSize;
|
||||
PageLifecycleManager _pageLifecycleManager;
|
||||
|
||||
Page Page => Element as Page;
|
||||
|
||||
|
@ -73,8 +72,6 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
|
||||
|
||||
_pageLifecycleManager = new PageLifecycleManager(Element as IPageController);
|
||||
|
||||
OnPagesChanged(null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
|
||||
if (element != null)
|
||||
|
@ -114,15 +111,14 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
public override void ViewDidAppear(bool animated)
|
||||
{
|
||||
_pageLifecycleManager?.HandlePageAppearing();
|
||||
Page.SendAppearing();
|
||||
base.ViewDidAppear(animated);
|
||||
}
|
||||
|
||||
public override void ViewDidDisappear(bool animated)
|
||||
{
|
||||
base.ViewDidDisappear(animated);
|
||||
_pageLifecycleManager?.HandlePageDisappearing();
|
||||
|
||||
Page.SendDisappearing();
|
||||
}
|
||||
|
||||
public override void ViewDidLayoutSubviews()
|
||||
|
@ -157,8 +153,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
{
|
||||
if (disposing)
|
||||
{
|
||||
_pageLifecycleManager?.Dispose();
|
||||
_pageLifecycleManager = null;
|
||||
Page.SendDisappearing();
|
||||
Tabbed.PropertyChanged -= OnPropertyChanged;
|
||||
Tabbed.PagesChanged -= OnPagesChanged;
|
||||
FinishedCustomizingViewControllers -= HandleFinishedCustomizingViewControllers;
|
||||
|
|
|
@ -303,8 +303,12 @@ namespace Xamarin.Forms.Platform.MacOS
|
|||
{
|
||||
if (Control == null)
|
||||
return;
|
||||
|
||||
|
||||
#if __MOBILE__
|
||||
focusRequestArgs.Result = focusRequestArgs.Focus ? Control.BecomeFirstResponder() : Control.ResignFirstResponder();
|
||||
#else
|
||||
focusRequestArgs.Result = focusRequestArgs.Focus ? Control.Window.MakeFirstResponder(Control) : Control.Window.MakeFirstResponder(null);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,7 +173,6 @@
|
|||
<Compile Include="IOSDeviceInfo.cs" />
|
||||
<Compile Include="LinkerSafeAttribute.cs" />
|
||||
<Compile Include="ModalWrapper.cs" />
|
||||
<Compile Include="PageLifecycleManager.cs" />
|
||||
<Compile Include="Renderers\FormsCAKeyFrameAnimation.cs" />
|
||||
<Compile Include="Renderers\FormsCheckBox.cs" />
|
||||
<Compile Include="Renderers\FormsUIImageView.cs" />
|
||||
|
@ -326,4 +325,4 @@
|
|||
<Name>Xamarin.Forms.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
Загрузка…
Ссылка в новой задаче