Xamarin.Forms 如何使用样式和动态资源正确更新控件的字体大小?
How to correctly update font size of controls using styles and dynamic resources in Xamarin.Forms?
我正在尝试在运行时更新控件的字体大小。
为此,我将样式作为动态资源应用于我的控件。当点击一个按钮时,我在应用程序中找到字体大小为 setter 的样式资源,修改字体大小值,并将整个样式写回到找到该样式的资源字典中。
控件示例:
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="CenterAndExpand"
Style="{DynamicResource DynamicLabel}"/>
样式示例:
<Style x:Key="DynamicLabel" TargetType="Label">
<Setter Property="TextColor" Value="Red" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalTextAlignment" Value="Center" />
<Setter Property="FontSize" Value="23" />
</Style>
正在调用以更新样式的代码:
private void ApplyScale(ResourceDictionary dictionary, double scaleFactor)
{
foreach (var resourceDictionary in dictionary.MergedDictionaries)
{
ApplyScale(resourceDictionary, scaleFactor);
}
Dictionary<string, Style> stylesToAdd = new Dictionary<string, Style>();
foreach (KeyValuePair<string, object> resource in dictionary)
{
if (resource.Value is Style style)
{
foreach (var styleSetter in style.Setters)
{
if (styleSetter.Property.PropertyName == nameof(Font.FontSize))
{
if (styleSetter.Value is OnPlatform<int> platformSetter)
{
foreach (var platform in platformSetter.Platforms)
{
var onPlatformFontSize = int.Parse(platform.Value.ToString());
styleSetter.Value = (int) Math.Round(onPlatformFontSize * scaleFactor);
}
}
else
{
var fontSize = int.Parse(styleSetter.Value.ToString());
styleSetter.Value = (int)Math.Round(fontSize * scaleFactor);
}
stylesToAdd.Add(resource.Key, style);
}
}
}
}
foreach (var style in stylesToAdd)
{
dictionary[style.Key] = style.Value;
}
}
我创建了一个测试应用程序来演示该问题:https://github.com/King-Xero/XF-DynamicStyleFontSizeTest
应用了样式的控件的外观不反映对这些样式所做的更改。控件肯定在使用样式,因为样式中的颜色出现在控件上。通过断点检查时,样式肯定会更新。但是控件的行为就好像它们应用了 StaticResource 而不是 DynamicResource。我不确定这是我的应用程序中的问题,还是 Xamarin.Forms.
中的问题
在 GitHub 的 Xamarin.Forms 存储库中,有一个 Issue 于 19 天前打开,它仍在分类中,但解决方法将强制 ResourceStyle 更新如下:
代码隐藏:
private void IncreaseFont_OnClicked(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
var savedstyle = MyLabel.Style;
MyLabel.Style = null;
_fontScaler.IncreaseFontScaling();
MyLabel.Style = savedstyle;
});
}
Xaml:
<Label x:Name="MyLabel"
Text="Welcome to Xamarin.Forms!"
HorizontalOptions="CenterAndExpand"
Style="{DynamicResource DynamicLabel}"/>
这不是解决问题的方法,请继续关注 GitHub 问题的更新。
我正在尝试在运行时更新控件的字体大小。
为此,我将样式作为动态资源应用于我的控件。当点击一个按钮时,我在应用程序中找到字体大小为 setter 的样式资源,修改字体大小值,并将整个样式写回到找到该样式的资源字典中。
控件示例:
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="CenterAndExpand"
Style="{DynamicResource DynamicLabel}"/>
样式示例:
<Style x:Key="DynamicLabel" TargetType="Label">
<Setter Property="TextColor" Value="Red" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalTextAlignment" Value="Center" />
<Setter Property="FontSize" Value="23" />
</Style>
正在调用以更新样式的代码:
private void ApplyScale(ResourceDictionary dictionary, double scaleFactor)
{
foreach (var resourceDictionary in dictionary.MergedDictionaries)
{
ApplyScale(resourceDictionary, scaleFactor);
}
Dictionary<string, Style> stylesToAdd = new Dictionary<string, Style>();
foreach (KeyValuePair<string, object> resource in dictionary)
{
if (resource.Value is Style style)
{
foreach (var styleSetter in style.Setters)
{
if (styleSetter.Property.PropertyName == nameof(Font.FontSize))
{
if (styleSetter.Value is OnPlatform<int> platformSetter)
{
foreach (var platform in platformSetter.Platforms)
{
var onPlatformFontSize = int.Parse(platform.Value.ToString());
styleSetter.Value = (int) Math.Round(onPlatformFontSize * scaleFactor);
}
}
else
{
var fontSize = int.Parse(styleSetter.Value.ToString());
styleSetter.Value = (int)Math.Round(fontSize * scaleFactor);
}
stylesToAdd.Add(resource.Key, style);
}
}
}
}
foreach (var style in stylesToAdd)
{
dictionary[style.Key] = style.Value;
}
}
我创建了一个测试应用程序来演示该问题:https://github.com/King-Xero/XF-DynamicStyleFontSizeTest
应用了样式的控件的外观不反映对这些样式所做的更改。控件肯定在使用样式,因为样式中的颜色出现在控件上。通过断点检查时,样式肯定会更新。但是控件的行为就好像它们应用了 StaticResource 而不是 DynamicResource。我不确定这是我的应用程序中的问题,还是 Xamarin.Forms.
中的问题在 GitHub 的 Xamarin.Forms 存储库中,有一个 Issue 于 19 天前打开,它仍在分类中,但解决方法将强制 ResourceStyle 更新如下:
代码隐藏:
private void IncreaseFont_OnClicked(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
var savedstyle = MyLabel.Style;
MyLabel.Style = null;
_fontScaler.IncreaseFontScaling();
MyLabel.Style = savedstyle;
});
}
Xaml:
<Label x:Name="MyLabel"
Text="Welcome to Xamarin.Forms!"
HorizontalOptions="CenterAndExpand"
Style="{DynamicResource DynamicLabel}"/>
这不是解决问题的方法,请继续关注 GitHub 问题的更新。