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

时间:2016-06-28 03:57:04

标签: xamarin xamarin.forms

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

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

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

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

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

3 个答案:

答案 0 :(得分:14)

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

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

的约束

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

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

注意:Xamarin.iOS没有像Swift那样定义的常量/枚举(ObjC也没有定义这些),所以它们作为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"));
        }
    }
}

结果:

enter image description here

enter image description here

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

答案 1 :(得分:5)

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

为要支持动态文本的每个控件创建一个渲染器。就我而言,这包括标签,按钮和Entrys。渲染器将​​Control.Font分配给UIFontDescriptor,其PointSize百分比根据分配给Xamarin Forms控件的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);
            }
        }
    }
}

您甚至可以通过这种方式动态支持固定字体大小,方法是根据基本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);
            }
        }
    }
}

作为参考,可在此GitHub project中找到完整的实施示例。

答案 2 :(得分:0)

对于iOS,我相信提供了things have changed in Xamarin.Forms since the earlier answers。如果将NamedSize value分配给文本元素的FontSize属性,则现在可以使用通过iOS“较大文本”设置设置的值来按比例缩放文本

例如,这将导致可访问的可扩展文本:

<Label
    FontSize="Large"
    LineBreakMode="WordWrap"
    Text="Some text here." />