【问题标题】:In Xamarin Forms how can I set the font of a label to Medium (System font)在 Xamarin Forms 中,如何将标签的字体设置为 Medium(系统字体)
【发布时间】:2020-10-23 16:57:04
【问题描述】:

我想使用系统字体 SF Pro (iOS) 和 Roboto (Android)。两者都有媒介,但我看不到任何方法可以为标签设置这些。

我想我可能需要一个 Label 自定义渲染器,如果有任何建议/建议,我将不胜感激。

以下是一些参考资料:

https://qiita.com/aqubi/items/3a1e668f4f78d4ad0db7

https://forums.xamarin.com/discussion/97446/set-font-weight-on-label

https://github.com/xamarin/Xamarin.Forms/issues/8035

【问题讨论】:

  • 这个问题只针对 iOS 吗?另外,您是如何设置 SemiBold 系列的?
  • 我想知道如何为iOS和Android设置。

标签: xamarin xamarin.forms


【解决方案1】:

让我们从 Android 开始 - 您不能将 Roboto 字体设置为 semi-bold,因为该字体不支持此粗细。参考链接 - Roboto - Google Fonts

对于 iOS,旧金山支持此字体粗细。由于您使用的是内置系统字体,只需将值设置为 .SFUIText-Semibold 即可。

更新

由于问题的更新性质,我们可以在这里为 iOS 提供 2 种方法。您收到的警告消息说明了一切:

CoreText 注意:客户端请求的名称“.SFUIText-Medium”,它将获得 TimesNewRomanPSMT 而不是预期的字体。所有系统 UI 字体访问都应通过适当的 API,例如 CTFontCreateUIFontForLanguage() 或 +[UIFont systemFontOfSize:]。

这意味着在我们的渲染中,我们可以这样设置字体:

Control.Font = UIFont.SystemFontOfSize(17, UIFontWeight.Medium);

警告信息还说可以使用CTFont 来实现,如下所示:

new CTFont(".SFUIText-Medium", 17);

对于 iOS,最好使用带有SystemFontOfSize 的第一种方法。

注意:请记住,这可能不会删除警告消息,因为它们通常是由 3rd 方包引起的,它们仍然引用旧的 Forms 版本,或者字体设置不正确。如果发生这种情况,请检查您的包裹并在必要时提出问题。您可以查看修复此问题的官方提交 (link)。如您所见,他们正在拆分您提供的字符串并获取最后一部分。如果最后一部分可以转换为UIFontWeight,那么他们设置字体的方式与我刚才描述的方式相同。因此,最后,如果您在共享项目中提供.SFUIText-Medium 字体,它将与在自定义渲染器中显式引用它具有相同的效果,因为两种方法最终都会得到相同的代码。同样,如果警告仍然存在,您需要检查您的第 3 方库。

这是两个结果的屏幕截图 - 在共享项目中设置字体并使用渲染器进行设置:

对于 Android,您可以再次在渲染器中设置字体。在这里,您需要一个自定义样式。在您的 Android 项目中,在 Resources/values/styles.xml 中创建一个新样式,如下所示:

<style name="FontRobotoMedium">
  <item name="android:fontFamily">sans-serif-medium</item>
  <item name="android:textColor">#333333</item>
  <item name="android:textSize">17sp</item>
</style>

您可以在此处自定义很多内容,但对于此示例,我只是添加了系列、尺寸和颜色。

然后,在您的渲染器中,只需更改控件的TextAppearance

Control.SetTextAppearance(Resource.Style.FontRobotoMedium);

请记住,这也可以在没有任何渲染器的情况下利用系统内置字体的功能来实现,如下所示:

<Label FontFamily="sans-serif-medium" />

Android系统字体参考请见here

注意:请记住,Android 系统字体也​​会经常更改,因此再次不建议使用这样的字体。 fonts.xml 文件的开头有一个巨大的警告,我已经给出了参考:

警告:不支持第三方应用程序解析此文件。这 文件及其引用的字体文件将被重命名和/或移出 从它们在下一个 Android 版本中的各自位置,和/或 文件的格式或语法可能会发生显着变化。如果你解析这个 文件以获取有关系统字体的信息,请自行承担风险。您的 应用程序几乎肯定会与下一个主要的 Android 系统决裂 释放。

这是两个结果的屏幕截图 - 在共享项目中设置字体并使用渲染器进行设置: 注意:由于文本填充的细微差异,字体会有所延迟,可以像这样调整样式:

<item name="android:padding">1dip</item>

总而言之,您可以使用自定义渲染器完成的操作,也可以在共享项目中完成。在所有代码下,来自 Xamarin 的团队所做的与来自自定义渲染器的代码非常相似(如果不相同)。不要指望所有的警告都会消失,因为如果任何 3rd-party 库没有升级到最新形式,或者没有正确使用系统字体,警告仍然会出现。

同样,尝试使用系统字体确实不是一个好习惯。它们被保留(在 iOS 的情况下 - 隐藏在点 (.) 名称后面)是有原因的。在一两次更新中,字体可能会发生变化,并且会破坏您的应用程序的外观。如果您没有任何明确的理由不导入字体文件,我强烈建议您导入字体文件以供参考。如果你仍然想使用系统字体,你可以在没有任何渲染器的情况下实现这一点。对于 iOS,只需将家庭设置为 .SFUIText-Medium,对于 Android - 设置为 sans-serif-medium(都在您的共享项目中)。

更新 2

假设您将在共享项目中将族设置为枚举。枚举可能如下所示:

public enum FontFamilyType
{
    Light,
    Regular,
    Medium
}

您可以在 CustomLabel 包装器中添加一个附加属性 - 例如

public FontFamilyType FontFamilyType { get; set; }

如有必要,您可以将其设为可绑定属性。

这里有 2 个渲染器,它们将字体更改为常规、轻和中。对于 iOS:

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace FontRenderers.iOS
{
    public class CustomLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            if (Control != null && Element != null)
            {
                UIFont font;

                switch (Element.FontFamilyType)
                {
                    case FontFamilyType.Light:
                        font= UIFont.SystemFontOfSize(18, UIFontWeight.Light);
                        break;
                    case FontFamilyType.Regular:
                        font= UIFont.SystemFontOfSize(18, UIFontWeight.Regular);
                        break;
                    case FontFamilyType.Medium:
                        font= UIFont.SystemFontOfSize(18, UIFontWeight.Medium);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                Control.Font = font;
            }
        }
    }
}

在这里,我给出了所有 3 个请求字体系列的示例。您可以随意切换它们 - 手动、检查一些参数等。

对于安卓:

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace FontRenderer.Droid
{
    public class CustomLabelRenderer : LabelRenderer
    {
        public CustomLabelRenderer(Context context)
            : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            int fontFamilyResId;

            switch (Element.FontFamilyType)
            {
                case FontFamilyType.Light:
                    fontFamilyResId = Resource.Style.FontRobotoLight;
                    break;
                case FontFamilyType.Regular:
                    fontFamilyResId = Resource.Style.FontRobotoRegular;
                    break;
                case FontFamilyType.Medium:
                    fontFamilyResId = Resource.Style.FontRobotoMedium;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }


            Control.SetTextAppearance(fontFamilyResId);
        }
    }
}

当然,对于 Android,您还需要 2 种样式(适用于轻型和普通家庭)。在styles.xml 中添加这两种样式:

<style name="FontRobotoLight">
  <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="FontRobotoRegular">
  <item name="android:fontFamily">sans-serif</item>
</style>

【讨论】:

  • 道歉设置为中
  • 将值设置为 .SFUIText-Semibold 有效,但会出现警告消息,因此我想探索标签自定义渲染器中的设置。明天我将为此开放赏金,因为我认为这将是其他人了解渲染器如何编码的好机会。
  • 我会研究并返回更多信息。
  • 谢谢米哈伊尔。期待适用于 iOS 和 Android 的自定义渲染器解决方案。我希望那里有一个。祝你晚安。
  • 谢谢,米哈伊尔。我会给你答案,因为你给了我 iOS 和 Android 自定义渲染器。
【解决方案2】:

这是你想要的吗?不建议使用字体名称,因为它是私有的,将来可能会更改。

这里是customLabel的代码:

public class customLabel : Label{

    public int myFont { get; set; }
}

在 Xaml 中:

<StackLayout>
    <!-- Place new controls here -->
    <Label Text="Welcome to Xamarin.Forms!" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />

    <app307:customLabel Text="testText" myFont="15"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
</StackLayout>

这是渲染器的代码

[assembly: ExportRenderer (typeof(customLabel), typeof(MyLabelRenderer))]
namespace App307.iOS
{
    public class MyLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            int fontSize = 18;

            if (e.NewElement != null)
            {
                customLabel label = e.NewElement as customLabel;

                fontSize = label.myFont;
            }

            if (Control != null)
            {
       
                UIFont font = UIFont.SystemFontOfSize(fontSize, UIFontWeight.Medium);
                Control.Font = font;
            }
        }
    }
}

参考:use new San Francisco font

【讨论】:

  • 对于这个解决方案,如果我指定了不同的字体大小会怎样?例如字体大小=15 或字体大小=20。您的 iOS 解决方案仅适用于一种尺寸。
  • @Alan2 查看我更新的答案,在自定义标签中添加一个 myFont 属性,然后您可以在渲染器中获取它。
猜你喜欢
  • 2020-01-22
  • 1970-01-01
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
  • 2020-09-24
  • 1970-01-01
  • 1970-01-01
  • 2019-11-08
相关资源
最近更新 更多