如何根据view.Width动态自动设置FontSize?
How to dynamically and automatically set FontSize based on view.Width?
"TRYING OUT AUTO SIZING"
字体太大,以至于字符串的一部分被截掉(当文本太大时,一部分被截掉并用省略号代替)。
"test text"
字体太小。 fontSize 是其各自视图的三分之一(估计)。
如何将元素的字体大小设置为元素(和/或包含视图)宽度的大小?使用上面的示例作为参考 - "test text" 会占用更多的视图,而 "TRYING OUT AUTO SIZING" 会占用更少的视图。
注意:黑框表示其他元素。
期望的目标是一个元素(标签和/或包含视图),当文本在 运行 时更改时,字体大小根据分配的文本和可用宽度设置(这保持不变构建后)。这样所有文本在字符串中都是可见的,并且它使用可用的宽度。
目的是在缩放比例差异很大的各种设备上支持多个平台。
尝试了什么?基于惯用语 (phone/tablet/etc) 的 NamedSizes 并基于 OS(平台,即 IOS、Android 等)通过乘法和除法来操作它们。这不是最佳实践,必须有一种方法来实现这一点。
遵循 "fitting text to available size" 或 "empirically fitting text" 的 Xamarin.Forms 指南会产生与预期不同的结果。"CH5: Dealing with sizes"
请就最佳做法提出建议 and/or 后续步骤。
结构
struct FontCalc
{
public FontCalc(Label label, double fontSize, double containerWidth)
: this()
{
// Save the font size.
FontSize = fontSize;
// Recalculate the Label height.
label.FontSize = fontSize;
SizeRequest sizeRequest =
label.Measure(containerWidth, Double.PositiveInfinity);
// Save that height.
TextHeight = sizeRequest.Request.Height;
}
public double FontSize { private set; get; }
public double TextHeight { private set; get; }
}
实施
标签标签;
public EmpiricalFontSizePage()
{
label = new Label();
Padding = new Thickness(0, Device.RuntimePlatform == Device.iOS ? 30 : 0, 0, 0);
ContentView contentView = new ContentView
{
Content = label
};
contentView.SizeChanged += OnContentViewSizeChanged;
Content = contentView;
}
void OnContentViewSizeChanged(object sender, EventArgs args)
{
// Get View whose size is changing.
View view = (View)sender;
if (view.Width <= 0 || view.Height <= 0)
return;
label.Text =
"This is text displayed. Does it work?";
// Calculate the height of the rendered text.
FontCalc lowerFontCalc = new FontCalc(label, 10, view.Width);
FontCalc upperFontCalc = new FontCalc(label, 100, view.Width);
while (upperFontCalc.FontSize - lowerFontCalc.FontSize > 1)
{
// Get the average font size of the upper and lower bounds.
double fontSize = (lowerFontCalc.FontSize + upperFontCalc.FontSize) / 2;
// Check the new text height against the container height.
FontCalc newFontCalc = new FontCalc(label, fontSize, view.Width);
if (newFontCalc.TextHeight > view.Height)
{
upperFontCalc = newFontCalc;
}
else
{
lowerFontCalc = newFontCalc;
}
}
// Set the final font size and the text with the embedded value.
label.FontSize = lowerFontCalc.FontSize;
label.Text = label.Text.Replace("??", label.FontSize.ToString("F0"));
}
(来自上面链接的 XF 文档的实现代码)
一种解决方案是使用 NuGet 包:Forms9Patch
使用它的 Lines
和 AutoFit
属性,我们可以达到我们想要的结果。在我们的例子中,我们想要一行并且我们希望我们的 FontSize
设置为使我们的文本适合一行所需的内容。 Lines = 1
、AutoFit = Forms9Patch.AutoFit.Width
和 FontSize
设置为较大的值(如果设置 AutoFit
到 Width
会缩小字体,那么它是否远远超过我们期望的最大值并不重要till to what is required to make text fit within our specified number of lines) 导致 Label
自动将其 FontSize
调整为给定文本长度可用的最大值 space。
"TRYING OUT AUTO SIZING"
"test text"
如何将元素的字体大小设置为元素(和/或包含视图)宽度的大小?使用上面的示例作为参考 - "test text" 会占用更多的视图,而 "TRYING OUT AUTO SIZING" 会占用更少的视图。
注意:黑框表示其他元素。
期望的目标是一个元素(标签和/或包含视图),当文本在 运行 时更改时,字体大小根据分配的文本和可用宽度设置(这保持不变构建后)。这样所有文本在字符串中都是可见的,并且它使用可用的宽度。
目的是在缩放比例差异很大的各种设备上支持多个平台。
尝试了什么?基于惯用语 (phone/tablet/etc) 的 NamedSizes 并基于 OS(平台,即 IOS、Android 等)通过乘法和除法来操作它们。这不是最佳实践,必须有一种方法来实现这一点。
遵循 "fitting text to available size" 或 "empirically fitting text" 的 Xamarin.Forms 指南会产生与预期不同的结果。"CH5: Dealing with sizes"
请就最佳做法提出建议 and/or 后续步骤。
结构
struct FontCalc
{
public FontCalc(Label label, double fontSize, double containerWidth)
: this()
{
// Save the font size.
FontSize = fontSize;
// Recalculate the Label height.
label.FontSize = fontSize;
SizeRequest sizeRequest =
label.Measure(containerWidth, Double.PositiveInfinity);
// Save that height.
TextHeight = sizeRequest.Request.Height;
}
public double FontSize { private set; get; }
public double TextHeight { private set; get; }
}
实施
标签标签;
public EmpiricalFontSizePage()
{
label = new Label();
Padding = new Thickness(0, Device.RuntimePlatform == Device.iOS ? 30 : 0, 0, 0);
ContentView contentView = new ContentView
{
Content = label
};
contentView.SizeChanged += OnContentViewSizeChanged;
Content = contentView;
}
void OnContentViewSizeChanged(object sender, EventArgs args)
{
// Get View whose size is changing.
View view = (View)sender;
if (view.Width <= 0 || view.Height <= 0)
return;
label.Text =
"This is text displayed. Does it work?";
// Calculate the height of the rendered text.
FontCalc lowerFontCalc = new FontCalc(label, 10, view.Width);
FontCalc upperFontCalc = new FontCalc(label, 100, view.Width);
while (upperFontCalc.FontSize - lowerFontCalc.FontSize > 1)
{
// Get the average font size of the upper and lower bounds.
double fontSize = (lowerFontCalc.FontSize + upperFontCalc.FontSize) / 2;
// Check the new text height against the container height.
FontCalc newFontCalc = new FontCalc(label, fontSize, view.Width);
if (newFontCalc.TextHeight > view.Height)
{
upperFontCalc = newFontCalc;
}
else
{
lowerFontCalc = newFontCalc;
}
}
// Set the final font size and the text with the embedded value.
label.FontSize = lowerFontCalc.FontSize;
label.Text = label.Text.Replace("??", label.FontSize.ToString("F0"));
}
(来自上面链接的 XF 文档的实现代码)
一种解决方案是使用 NuGet 包:Forms9Patch
使用它的 Lines
和 AutoFit
属性,我们可以达到我们想要的结果。在我们的例子中,我们想要一行并且我们希望我们的 FontSize
设置为使我们的文本适合一行所需的内容。 Lines = 1
、AutoFit = Forms9Patch.AutoFit.Width
和 FontSize
设置为较大的值(如果设置 AutoFit
到 Width
会缩小字体,那么它是否远远超过我们期望的最大值并不重要till to what is required to make text fit within our specified number of lines) 导致 Label
自动将其 FontSize
调整为给定文本长度可用的最大值 space。