让我们从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](https://istack.dev59.com/vkcj1.webp)
在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](https://istack.dev59.com/xDiwH.webp)
注意:由于文本填充略有差异,字体会稍有不同,可以通过样式进行调整。
<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>