From 520ff4a227d599a2ef68ed13478cff1bd3308bb3 Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Thu, 26 Jan 2017 11:51:28 -0700 Subject: [PATCH] Use a prototype TextBlock to resolve theme resources on Windows (#703) * Use a prototype TextBlock to resolve theme resources on Windows * Move textblock declaration to beginning of class * Don't retain prototype TextBlock in memory --- .../Bugzilla43783.cs | 30 ++++++ .../Xamarin.Forms.Controls.Issues.Shared.projitems | 1 + .../WindowsPhoneResourcesProvider.cs | 108 ++++++--------------- .../WindowsResourcesProvider.cs | 67 ++++++------- 4 files changed, 87 insertions(+), 119 deletions(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43783.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43783.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43783.cs new file mode 100644 index 0000000..99d4fca --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43783.cs @@ -0,0 +1,30 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 43783, "[WP8.1] Most Device Styles do not render correctly in Windows Phone 8.1 (RT) applications", PlatformAffected.WinPhone)] + public class Bugzilla43783 : TestContentPage + { + protected override void Init() + { + Title = "Device"; + + Content = new StackLayout + { + Children = { + new Label { Margin = new Thickness(10), Text = "The Labels for Body, Caption, List Item, List Item Detail, and No Style should not all look the same. If all of them look the same, this test has failed."}, + new Label { Text = "Title style", Style = Device.Styles.TitleStyle }, + new Label { Text = "Subtitle style", Style = Device.Styles.SubtitleStyle }, + new Label { Text = "Body style", Style = Device.Styles.BodyStyle }, + new Label { Text = "Caption style", Style = Device.Styles.CaptionStyle }, + new Label { Text = "List item text style", Style = Device.Styles.ListItemTextStyle }, + new Label { Text = "List item detail text style", Style = Device.Styles.ListItemDetailTextStyle }, + new Label { Text = "No style" } + } + }; + } + + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index 68193dc..0ca65ac 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -144,6 +144,7 @@ + diff --git a/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs index adbe7de..7b05159 100644 --- a/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs +++ b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Windows.UI.Text; +using Windows.UI.Text; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using WStyle = Windows.UI.Xaml.Style; namespace Xamarin.Forms.Platform.WinRT { @@ -12,89 +10,50 @@ namespace Xamarin.Forms.Platform.WinRT { public IResourceDictionary GetSystemResources() { - var windowsResources = Windows.UI.Xaml.Application.Current.Resources; - - var resources = new ResourceDictionary (); - resources[Device.Styles.TitleStyleKey] = GetStyle ("HeaderTextBlockStyle"); - resources[Device.Styles.SubtitleStyleKey] = GetStyle ("SubheaderTextBlockStyle"); - resources[Device.Styles.BodyStyleKey] = GetStyle ("BodyTextBlockStyle"); - resources[Device.Styles.CaptionStyleKey] = GetStyle ("BodyTextBlockStyle"); - resources[Device.Styles.ListItemTextStyleKey] = GetStyle ("ListViewItemTextBlockStyle"); - resources[Device.Styles.ListItemDetailTextStyleKey] = GetStyle ("ListViewItemContentTextBlockStyle"); - return resources; + var prototype = new TextBlock(); + + return new ResourceDictionary + { + [Device.Styles.TitleStyleKey] = GetStyle("HeaderTextBlockStyle", prototype), + [Device.Styles.SubtitleStyleKey] = GetStyle("SubheaderTextBlockStyle", prototype), + [Device.Styles.BodyStyleKey] = GetStyle("BodyTextBlockStyle", prototype), + [Device.Styles.CaptionStyleKey] = GetStyle("BodyTextBlockStyle", prototype), + [Device.Styles.ListItemTextStyleKey] = GetStyle("ListViewItemTextBlockStyle", prototype), + [Device.Styles.ListItemDetailTextStyleKey] = GetStyle("ListViewItemContentTextBlockStyle", prototype) + }; } - Style GetStyle (object nativeKey) + static Style GetStyle(object nativeKey, TextBlock prototype) { - var style = (Windows.UI.Xaml.Style) Windows.UI.Xaml.Application.Current.Resources[nativeKey]; - style = GetAncestorSetters(style); + var style = (WStyle)Windows.UI.Xaml.Application.Current.Resources[nativeKey]; - var formsStyle = new Style (typeof (Label)); - foreach (var b in style.Setters) { - var setter = b as Windows.UI.Xaml.Setter; - if (setter == null) - continue; + prototype.Style = style; - // TODO: Need to implement a stealth pass-through for things we don't support + var formsStyle = new Style(typeof(Label)); - if (setter.Property == TextBlock.FontSizeProperty) - formsStyle.Setters.Add (Label.FontSizeProperty, setter.Value); - else if (setter.Property == TextBlock.FontFamilyProperty) - formsStyle.Setters.Add (Label.FontFamilyProperty, setter.Value); - else if (setter.Property == TextBlock.FontWeightProperty) - formsStyle.Setters.Add (Label.FontAttributesProperty, ToAttributes (Convert.ToUInt16 (setter.Value))); - else if (setter.Property == TextBlock.TextWrappingProperty) - formsStyle.Setters.Add (Label.LineBreakModeProperty, ToLineBreakMode ((TextWrapping) setter.Value)); - } + formsStyle.Setters.Add(Label.FontSizeProperty, prototype.FontSize); + formsStyle.Setters.Add(Label.FontFamilyProperty, prototype.FontFamily.Source); + formsStyle.Setters.Add(Label.FontAttributesProperty, ToAttributes(prototype.FontWeight)); + formsStyle.Setters.Add(Label.LineBreakModeProperty, ToLineBreakMode(prototype.TextWrapping)); return formsStyle; } - static Windows.UI.Xaml.Style GetAncestorSetters (Windows.UI.Xaml.Style value) + static FontAttributes ToAttributes(FontWeight fontWeight) { - var style = new Windows.UI.Xaml.Style (value.TargetType) - { - BasedOn = value.BasedOn - }; - foreach (var valSetter in value.Setters) + if (fontWeight.Weight == FontWeights.Bold.Weight || fontWeight.Weight == FontWeights.SemiBold.Weight + || fontWeight.Weight == FontWeights.ExtraBold.Weight) { - style.Setters.Add(valSetter); - } - - var ancestorStyles = new List (); - - Windows.UI.Xaml.Style currStyle = style; - while (currStyle.BasedOn != null) - { - ancestorStyles.Add(currStyle.BasedOn); - currStyle = currStyle.BasedOn; + return FontAttributes.Bold; } - foreach (var styleParent in ancestorStyles) - { - foreach (var b in styleParent.Setters) - { - var parentSetter = b as Windows.UI.Xaml.Setter; - if (parentSetter == null) - continue; - - var derviedSetter = style.Setters - .OfType () - .FirstOrDefault (x => x.Property == parentSetter.Property); - - //Ignore any ancestor setters which a child setter has already overridden - if (derviedSetter != null) - continue; - else - style.Setters.Add (parentSetter); - } - } - return style; + return FontAttributes.None; } - static LineBreakMode ToLineBreakMode (TextWrapping value) + static LineBreakMode ToLineBreakMode(TextWrapping value) { - switch (value) { + switch (value) + { case TextWrapping.Wrap: return LineBreakMode.CharacterWrap; case TextWrapping.WrapWholeWords: @@ -104,14 +63,5 @@ namespace Xamarin.Forms.Platform.WinRT return LineBreakMode.NoWrap; } } - - static FontAttributes ToAttributes (ushort uweight) - { - if (uweight == FontWeights.Bold.Weight || uweight == FontWeights.SemiBold.Weight || uweight == FontWeights.ExtraBold.Weight) { - return FontAttributes.Bold; - } - - return FontAttributes.None; - } } } \ No newline at end of file diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs index 64041c0..c448567 100644 --- a/Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs +++ b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs @@ -1,7 +1,7 @@ -using System; -using Windows.UI.Text; +using Windows.UI.Text; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using WStyle = Windows.UI.Xaml.Style; #if WINDOWS_UWP @@ -15,60 +15,47 @@ namespace Xamarin.Forms.Platform.WinRT { public IResourceDictionary GetSystemResources() { - Windows.UI.Xaml.ResourceDictionary windowsResources = Windows.UI.Xaml.Application.Current.Resources; + var prototype = new TextBlock(); + + return new ResourceDictionary + { + [Device.Styles.TitleStyleKey] = GetStyle("HeaderTextBlockStyle", prototype), + [Device.Styles.SubtitleStyleKey] = GetStyle("SubheaderTextBlockStyle", prototype), + [Device.Styles.BodyStyleKey] = GetStyle("BodyTextBlockStyle", prototype), + [Device.Styles.CaptionStyleKey] = GetStyle("CaptionTextBlockStyle", prototype), + [Device.Styles.ListItemDetailTextStyleKey] = GetStyle("BodyTextBlockStyle", prototype), - var resources = new ResourceDictionary(); - resources[Device.Styles.TitleStyleKey] = GetStyle("HeaderTextBlockStyle"); - resources[Device.Styles.SubtitleStyleKey] = GetStyle("SubheaderTextBlockStyle"); - resources[Device.Styles.BodyStyleKey] = GetStyle("BodyTextBlockStyle"); - resources[Device.Styles.CaptionStyleKey] = GetStyle("CaptionTextBlockStyle"); #if WINDOWS_UWP - resources[Device.Styles.ListItemTextStyleKey] = GetStyle("BaseTextBlockStyle"); + [Device.Styles.ListItemTextStyleKey] = GetStyle("BaseTextBlockStyle", prototype), #else - resources[Device.Styles.ListItemTextStyleKey] = GetStyle("TitleTextBlockStyle"); + [Device.Styles.ListItemTextStyleKey] = GetStyle("TitleTextBlockStyle", prototype), #endif - resources[Device.Styles.ListItemDetailTextStyleKey] = GetStyle("BodyTextBlockStyle"); - return resources; + }; } - Style GetStyle(object nativeKey) + Style GetStyle(object nativeKey, TextBlock prototype) { - var style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources[nativeKey]; + var style = (WStyle)Windows.UI.Xaml.Application.Current.Resources[nativeKey]; - var formsStyle = new Style(typeof(Label)); - foreach (SetterBase b in style.Setters) - { - var setter = b as Windows.UI.Xaml.Setter; - if (setter == null) - continue; + prototype.Style = style; - // TODO: Need to implement a stealth pass-through for things we don't support + var formsStyle = new Style(typeof(Label)); - try - { - if (setter.Property == TextBlock.FontSizeProperty) - formsStyle.Setters.Add(Label.FontSizeProperty, setter.Value); - else if (setter.Property == TextBlock.FontFamilyProperty) - formsStyle.Setters.Add(Label.FontFamilyProperty, setter.Value); - else if (setter.Property == TextBlock.FontWeightProperty) - formsStyle.Setters.Add(Label.FontAttributesProperty, ToAttributes(Convert.ToUInt16(setter.Value))); - else if (setter.Property == TextBlock.TextWrappingProperty) - formsStyle.Setters.Add(Label.LineBreakModeProperty, ToLineBreakMode((TextWrapping)setter.Value)); - } - catch (NotImplementedException) - { - // see https://bugzilla.xamarin.com/show_bug.cgi?id=33135 - // WinRT implementation of Windows.UI.Xaml.Setter.get_Value is not implemented. - } - } + formsStyle.Setters.Add(Label.FontSizeProperty, prototype.FontSize); + formsStyle.Setters.Add(Label.FontFamilyProperty, prototype.FontFamily.Source); + formsStyle.Setters.Add(Label.FontAttributesProperty, ToAttributes(prototype.FontWeight)); + formsStyle.Setters.Add(Label.LineBreakModeProperty, ToLineBreakMode(prototype.TextWrapping)); return formsStyle; } - static FontAttributes ToAttributes(ushort uweight) + static FontAttributes ToAttributes(FontWeight fontWeight) { - if (uweight == FontWeights.Bold.Weight || uweight == FontWeights.SemiBold.Weight || uweight == FontWeights.ExtraBold.Weight) + if (fontWeight.Weight == FontWeights.Bold.Weight || fontWeight.Weight == FontWeights.SemiBold.Weight + || fontWeight.Weight == FontWeights.ExtraBold.Weight) + { return FontAttributes.Bold; + } return FontAttributes.None; } -- 2.7.4