Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do I Support Accessibility Font Sizes in Xamarin Forms?

For example, I have a label on my page:

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

How do I make this label's font size increase (or decrease) depending on the user's accessibility settings for font sizes? For example, in iOS you can set the Font Size for your device under Settings > General > Accessibility > Larger Text. I believe that Apple calls this "Dynamic Text" and is almost a requirement for your app to support.

The same applies for other controls in my app (buttons, entrys, etc).

I have tried this setting on my iPhone and it does not appear to be changing all things in my app. There are a few things like TableView section headers and list view cells that are changing, but things like my standard Labels and Entrys are not.

like image 974
kspearrin Avatar asked Jun 28 '16 03:06

kspearrin


2 Answers

Using the info in the answer provided @SushiHangover, I was able to implement the following renderer strategy for iOS:

Create a renderer for each control that you want to support dynamic text on. In my case, this included Labels, Buttons, and Entrys. The renderers assign the Control.Font to a UIFontDescriptor with the PointSize percentage adjusted based on the NamedSize assigned to the Xamarin Forms control.

Example:

[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);
            }
        }
    }
}

You could even dynamically support fixed font sizes this way by taking their percentage value based on the base NamedSize.Default size.

Example:

[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);
            }
        }
    }
}

For reference, full implementation examples can be found in this GitHub project.

like image 200
kspearrin Avatar answered Sep 24 '22 22:09

kspearrin


For iOS I believe things have changed in Xamarin.Forms since the earlier answers were provided. If a NamedSize value is assigned to the FontSize property of a text element, the text now gets scaled up and down with the value set via the iOS "Larger Text" setting.

For example, this would result in accessible, scalable text:

<Label
    FontSize="Large"
    LineBreakMode="WordWrap"
    Text="Some text here." />
like image 28
rogersillito Avatar answered Sep 23 '22 22:09

rogersillito