【问题标题】:How to dynamically and automatically set FontSize based on view.Width?如何根据view.Width动态自动设置FontSize?
【发布时间】:2019-04-02 01:21:57
【问题描述】:

“尝试自动调整大小” 字体太大,以至于部分字符串被截断(当文本太大时,部分被截断并替换为省略号)。

“测试文本” 字体太小。 fontSize 是其各自视图的三分之一(估计)。

如何将元素的 fontSize 设置为元素(和/或包含视图)宽度的大小?使用上面的示例作为参考 - “测试文本”会占用更多的视图,而“尝试自动调整大小”会占用更少的视图。

注意:黑框表示其他元素。

期望的目标是一个元素(标签和/或包含视图),当文本在运行时更改时,fontSize 根据分配的文本和可用的宽度设置(在构建后保持不变)。这样字符串中的所有文本都是可见的,并且它使用可用的宽度。

目的是在具有不同缩放比例的各种设备上支持多个平台。

尝试了什么? NamedSizes 基于成语(手机/平板电脑/等),并通过基于操作系统(平台,即 IOS、Android 等)的乘法和除法来操作它们。这不是最佳实践,必须有办法实现这一点。

按照 Xamarin.Forms 指南“将文本拟合到可用大小”或“根据经验拟合文本”会产生不符合预期的结果。"CH5: Dealing with sizes"

请就最佳做法和/或后续步骤提出建议。

结构

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 文档的实现代码)

【问题讨论】:

  • 关于字体的适配,首先要区分不同系统的设备。如果是安卓设备,可以修改系统的密度显示在不同的安卓设备上。如果是iOS设备,可以根据iOS不同的屏幕尺寸进行显示。毕竟iOS的设备尺寸不像安卓那么多样化,这点还是蛮可行的。
  • Okey,在android中,你可以修改密度显示在不同的android设备上。stackoverflow.com/questions/55302016/…这需要在native平台做。

标签: xamarin xamarin.forms fonts runtime font-size


【解决方案1】:

一种解决方案是使用 NuGet 包:Forms9Patch

使用它的LinesAutoFit 属性,我们可以实现我们想要的结果。在我们的例子中,我们想要一行,我们希望我们的FontSize 设置为使我们的文本适合一行所需的内容。 Lines = 1AutoFit = Forms9Patch.AutoFit.WidthFontSize 设置为一个较大的值(如果将 AutoFit 设置为 Width 将字体缩小到使文本适合其中所需的大小,这与我们期望的最大值无关我们指定的行数)产生一个Label,它会自动将其FontSize调整为给定文本长度的最大可用空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-09
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 2023-04-07
    • 2014-04-19
    • 2011-01-14
    相关资源
    最近更新 更多