在Xamarin Forms中,如何将标签的字体设置为中等(系统字体)?

4

问题只针对iOS吗?另外,你是如何尝试设置SemiBold字体族的? - Mihail Duchev
我想知道如何在iOS和Android上进行设置。 - Alan2
2个回答

6
让我们从Android开始 - 你不能将Roboto字体设置为semi-bold,因为该字体不支持这种重量。参考链接 - Roboto - Google Fonts
对于iOS,San Francisco支持此字体重量。由于您正在使用内置系统字体,只需将值设置为.SFUIText-Semibold即可解决问题。
更新:
由于问题的更新性质,我们在iOS上可以有两种方法。您收到的警告消息已经说明了一切:
引用:

CoreText note: Client requested name ".SFUIText-Medium", it will get TimesNewRomanPSMT rather than the intended font. All system UI font access should be through proper APIs such as CTFontCreateUIFontForLanguage() or +[UIFont systemFontOfSize:].

这意味着在我们的渲染中,我们可以像这样设置字体:
Control.Font = UIFont.SystemFontOfSize(17, UIFontWeight.Medium);

警告信息还说可以通过以下方式使用CTFont实现:
new CTFont(".SFUIText-Medium", 17);

对于iOS来说,最好使用第一种方法,即使用SystemFontOfSize

注意,这可能无法解决警告信息,因为很多情况下是由第三方软件包引起的,它们仍然引用旧版本的Forms或者设置字体不正确。如果出现这种情况,请检查您的软件包并在必要时提出问题。您可以查看官方提交的修复程序(link)。正如您所看到的,它们正在拆分您提供的字符串并获取最后一部分。如果最后一部分可以转换为UIFontWeight,它们将以与我刚刚描述的相同方式设置字体。因此,如果您在共享项目中提供.SFUIText-Medium字体,它将产生与显式引用自定义渲染器中的相同效果,因为两种方法都以相同的代码结束。再次强调,如果警告持续存在,请检查您的第三方库。
这是一张同时设置共享项目字体和使用渲染器设置字体的截图: iOS 在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系统字体的参考,请参见此处

NB:请记住,Android系统字体也经常更改,因此不建议像这样使用字体。 我已经提供了一个对fonts.xml文件开头的巨大警告的引用:

警告:第三方应用程序不支持解析此文件。该文件及其引用的字体文件将在下一个Android版本中被重命名和/或移动到其各自的位置,并且/或文件的格式或语法可能会发生重大变化。 如果您解析此文件以获取有关系统字体的信息,则自行承担风险。 您的应用程序几乎肯定会在下一个主要Android版本中出现故障。

这里有一张屏幕截图,展示了在共享项目中设置字体和使用渲染器设置字体的两种结果: android 注意:由于文本填充略有差异,字体会稍有不同,可以通过样式进行调整。
<item name="android:padding">1dip</item>

总之,使用自定义渲染器所能做的事情,在共享项目中也可以完成。在所有代码下面,Xamarin团队正在执行与自定义渲染器代码非常相似(如果不是完全相同的)的操作。请勿期望所有警告都会消失,因为如果任何第三方库未升级到最新的格式,或者未正确使用系统字体,则警告仍将出现。
再次强调,尝试使用系统字体真的不是一个好习惯。它们被保留了(在iOS的情况下隐藏在点(.)名称后面)有其原因。在一两个更新中,字体可能会更改并破坏您的应用程序外观。如果您没有任何明确的理由不导入字体文件,我强烈建议您导入字体文件并引用它们的系列。如果您仍想使用系统字体,则可以在没有任何渲染器的情况下实现此目的。对于iOS,只需将系列设置为 .SFUIText-Medium ,而对于Android,则为 sans-serif-medium (均在您的共享项目中)。
更新2
假设您将系列设置为共享项目中的枚举。该枚举可以像这样:
public enum FontFamilyType
{
    Light,
    Regular,
    Medium
}

你可以在CustomLabel包装器中添加一个额外的属性,例如:
public FontFamilyType FontFamilyType { get; set; }

你可以将其变成可绑定属性,如果需要的话。
以下是两个渲染器,可以将字体更改为Regular、Light和Medium。对于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;
            }
        }
    }
}

这里我已经给出了包含所有三种字体族的示例。您可以手动切换它们,检查某些参数等方式进行切换。
对于安卓:
[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平台,您还需要两种风格(用于浅色和常规字体系列)。在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>


1
抱歉,将设置调整为“中等”。 - Alan2
1
将值设置为.SFUIText-Semibold可以工作,但会出现警告消息,因此我想探索在标签自定义渲染器中进行设置。明天我会为此开启悬赏,因为我认为这是一个让其他人了解如何编写渲染器的好机会。 - Alan2
1
我会进行研究并回来提供更多信息。 - Mihail Duchev
1
谢谢,Mihail。我会授予您答案,因为您为我提供了iOS和Android的自定义渲染器。 - Alan2
@Alan2,你为什么接受了我的答案,却把悬赏给了Jack的答案? - Mihail Duchev
显示剩余5条评论

1
这是您想要的吗?不建议使用字体名称,因为它是私有的并且将来可能会更改。
这是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;
            }
        }
    }
}

enter image description here

参考: 使用新的旧金山字体


针对这个解决方案,如果我指定了不同的字体大小会怎么样?例如字体大小为15或20。你为iOS提供的解决方案只适用于一个大小。 - Alan2
@Alan2 请查看我的更新答案,在自定义标签中添加一个 myFont 属性,然后您就可以在渲染器中获取它了。 - nevermore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接