我目前正在开发一个 .Net Maui android 应用程序,但我遇到了 FontSizes 的障碍。
部署应用程序并在许多不同的手机上尝试后,我开始意识到相同尺寸的屏幕通常具有不同的像素密度,并且布局会根据像素密度和屏幕尺寸而变得疯狂。
例如,当我检查DeviceDisplayInfo时,平板电脑等大屏幕手机的“高度”比普通尺寸的手机小。而完全相同的屏幕尺寸,不同的像素密度,只会让所有的布局“缩小”。
我会给你一个带有图像的例子,以便你更好地理解。
这是在具有“基本”规格的 Google Pixel 5 模拟器上运行的应用程序的打印屏幕:
这是在 Google Pixel 5 上完全相同的屏幕上打印的照片,但像素密度为 560,而不是基础 440:
正如您在较高像素密度模拟器中看到的,整个布局太大了。
我尝试使用屏幕尺寸(高度/宽度)和密度进行一些计算,但没有得出最终结论,它根据屏幕尺寸和密度而变化很大。
我实际上能够为页面的组件创建特定的样式(小/中/大,例如,使用不同的字体大小/高度等),并根据屏幕尺寸动态地更改它们。我就是这样做的。
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
double ScreenSize = this.Height;
//Also tried doing something like this but wasn't helping me in any way
//ScreenSize = (DeviceDisplay.Current.MainDisplayInfo.Height / DeviceDisplay.Current.MainDisplayInfo.Density);
if(ScreenSize < 0)
return;
if (ScreenSize >= 900)
SetSizesLarge();
if (ScreenSize > 600 && ScreenSize < 900)
SetSizesMedium();
if (ScreenSize < 600)
SetSizesSmall();
}
private void SetSizesLarge()
{
WelcomeHeaderLabel.Style = ResourceHelper.FindResource(this, "ActiveHeaderStyleLarge") as Style;
Go_Natural_Bottom_Logo.WidthRequest = (double) 200;
}
private void SetSizesMedium()
{
WelcomeHeaderLabel.Style = ResourceHelper.FindResource(this, "ActiveHeaderStyle") as Style;
Go_Natural_Bottom_Logo.WidthRequest = (double)150;
}
private void SetSizesSmall()
{
WelcomeHeaderLabel.Style = ResourceHelper.FindResource(this, "ActiveHeaderStyleSmall") as Style;
Go_Natural_Bottom_Logo.WidthRequest = (double)120;
}
那么,我如何知道何时根据手机尺寸/像素密度使用小/中/大布局?
当我遇到类似的情况时,起初我尝试设置
Label.FontAutoScalingEnabled="True"
,但很惊讶它实际上并没有做这样的事情。因此,在我发现一些内置的自动缩放方式之前,我进行了自己的二分搜索。这可能是你可以适应你想做的事情的东西。
public partial class MainPage : ContentPage
{
public MainPage() => InitializeComponent();
private void AnySizeChanged(object sender, EventArgs e)
{
if(sender is Label label)
{
double minFontSize = 1;
double maxFontSize = 100;
double tolerance = 0.1;
double targetHeight = label.Height * 0.9;
double targetWidth = label.Width * 0.8;
while (minFontSize < maxFontSize)
{
double midFontSize = (minFontSize + maxFontSize) / 2;
label.FontSize = midFontSize;
Size textSize = label.Measure(double.PositiveInfinity, double.PositiveInfinity).Request;
bool isHeightWithinTolerance = Math.Abs(textSize.Height - targetHeight) <= targetHeight * tolerance;
bool isWidthWithinLabel = textSize.Width <= targetWidth;
if (isHeightWithinTolerance && isWidthWithinLabel)
{
break;
}
else if (textSize.Height > targetHeight || textSize.Width > targetWidth)
{
maxFontSize = midFontSize - 0.1;
}
else
{
minFontSize = midFontSize + 0.1;
}
}
label.FontSize = (minFontSize + maxFontSize) / 2;
}
}
}
在xaml中,处理SizeChanged事件。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DynamicSizingProto"
x:Class="DynamicSizingProto.MainPage">
<ContentPage.Resources>
<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalTextAlignment" Value="Center" />
<Setter Property="Margin" Value="5" />
<Setter Property="BackgroundColor" Value="{StaticResource Secondary}" />
<Setter Property="TextColor" Value="{StaticResource Primary}" />
</Style>
</ContentPage.Resources>
<Grid
RowDefinitions="*,*,2*,3*,4*,*">
<Label
Text="Text Placeholder"
SizeChanged="AnySizeChanged"
Grid.Row="1"/>
<Label
Text="Text Placeholder"
SizeChanged="AnySizeChanged"
Grid.Row="2"/>
<Label
Text="Text Placeholder"
SizeChanged="AnySizeChanged"
Grid.Row="3"/>
<Label
Text="Text Placeholder"
SizeChanged="AnySizeChanged"
Grid.Row="4"/>
</Grid>
</ContentPage>
我可能会尝试将其烘焙成自定义扩展
LabelEx
,但这是基本想法。