让我们从 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>