如何在Xamarin表单中支持辅助功能字体大小?

ksp*_*rin 10 xamarin xamarin.forms

例如,我的页面上有一个标签:

var label = new Label
{
    Text = "Some text here.",
    LineBreakMode = LineBreakMode.WordWrap,
    FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
};
Run Code Online (Sandbox Code Playgroud)

如何根据用户对字体大小的可访问性设置增加(或减少)此标签的字体大小?例如,在iOS中,您可以在"设置">"常规">"辅助功能">"大文本"下设置设备的"字体大小".我相信Apple称之为"动态文本",几乎是您的应用程序支持的要求.

这同样适用于我的应用程序中的其他控件(按钮,托管等).

我在我的iPhone上试过这个设置,它似乎并没有改变我的应用程序中的所有内容.有一些事情,如TableView部分标题和列表视图单元格正在改变,但像我的标准标签和Entrys之类的东西不是.

Sus*_*ver 14

您需要提供UIFontpreferredFontWithTextStyle(C#= UIFont.PreferredFontForTextStyle)返回的返回值 作为标签,按钮,条目等的使用上下文...将不知道Xamarin.Forms.

所以我为一个客户端做的是基础渲染器和视图元素的子类,并为这些元素添加了一个仅iOS的属性,因此他们可以定义如何在UI中开始使用该控件的上下文,因此当iOS呈现这些控件时受动态文本大小限制.

iOS 9中定义了六种动态字体类型:

  • UICTFontTextStyleBody
  • UICTFontTextStyleCaption1
  • UICTFontTextStyleCaption2
  • UICTFontTextStyleFootnote
  • UICTFontTextStyleHeadline
  • UICTFontTextStyleSubhead

注意:Xamarin.iOS没有像Swift那样定义的常量/枚举(ObjC也没有定义这些),因此它们作为a传递NSString,参见下面的示例.

示例渲染器:

设置UICTFontTextStyleBody标签子类名为BodyLabel:

[assembly: ExportRenderer(typeof(BodyLabel), typeof(iOSLabelBodyRenderer))]
namespace Foobar.iOS
{
    public class iOSLabelBodyRenderer : LabelRenderer
    {
        public iOSLabelBodyRenderer() { }

        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
                Control.Font = UIFont.GetPreferredFontForTextStyle(new NSString("UICTFontTextStyleBody"));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果是:

在此输入图像描述

在此输入图像描述

注意:从技术上讲,您还应该实现UIContentSizeCategoryDidChangeNotification通知,以便在用户更改动态字体大小时调整控件的大小/使其无效.


ksp*_*rin 5

使用@SushiHangover提供的答案中的信息,我能够为iOS实现以下渲染器策略:

为要支持动态文本的每个控件创建渲染器.就我而言,这包括标签,按钮和Entrys.渲染器将Control.Fonta 分配给根据分配给Xamarin Forms控件调整UIFontDescriptorPointSize百分比NamedSize.

例:

[assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRenderer))]
namespace iOS.Controls
{
    public class CustomButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            var view = e.NewElement as Button;
            if(Control != null && view != null)
            {
                var descriptor = UIFontDescriptor.PreferredBody;
                var pointSize = descriptor.PointSize;

                var size = view.FontSize;
                if(size == Device.GetNamedSize(NamedSize.Large, typeof(Button)))
                {
                    pointSize *= 1.4f;
                }
                else if(size == Device.GetNamedSize(NamedSize.Small, typeof(Button)))
                {
                    pointSize *= .8f;
                }
                else if(size == Device.GetNamedSize(NamedSize.Micro, typeof(Button)))
                {
                    pointSize *= .6f;
                }

                Control.Font = UIFont.FromDescriptor(descriptor, pointSize);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您甚至可以通过基于基本NamedSize.Default大小获取其百分比值来以这种方式动态支持固定字体大小.

例:

[assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRenderer))]
namespace iOS.Controls
{
    public class CustomButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            var view = e.NewElement as Button;
            if(Control != null && view != null)
            {
                var descriptor = UIFontDescriptor.PreferredBody;
                var percent = view.FontSize / Device.GetNamedSize(NamedSize.Default, typeof(Button));

                Control.Font = UIFont.FromDescriptor(descriptor, percent * descriptor.PointSize);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

作为参考,可以在此GitHub项目中找到完整的实现示例.