Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Add "FontUserScaled" boolean property and fix Android font scaling

GaryMcGheeGaryMcGhee AUMember ✭✭
edited December 2016 in Xamarin.Forms

Summary

Add a "FontUserScaled" boolean property to XF controls with text such as Label, Button, Entry that selects between Android SP-like mode (true) and DiP-like mode (false) for font sizing. Currently on Android, Scaled Pixels are used, which are affected by user preference, and there is no way to choose DiP's which are consistent with iOS and much easier to achieve reliable layout.

API Changes

1) Add FontUserScaled boolean property to Label, Button, Entry etc, wherever font sizes are specified eg. https://github.com/xamarin/Xamarin.Forms/search?utf8=✓&q=SetTextSize
On Android, this would switch between SP and DiP eg. for calls to SetTextSize. On iOS, it may have no effect, or some attempt could be made to emulate SP (not important)

2) With a FontUserScaled property today, there would be a typical choice to be made between future improvement vs breaking existing projects:
a) Backwards Compatible, platform inconsistent, beginner-unfriendly FontUserScaled=true
This is how XF works on Android now, but not iOS. This option would mean good XAML code would be littered with FontUserScaled="false" on most controls.
b) Breaking change, platform consistent, beginner-friendly FontUserScaled=false

I recommend b) It is still early in Xamarin's adoption lifetime. By default, apps would be built ignoring user font size preference, which is easier for beginners, but the developer could

Intended Use Case

Developers should not have to consider or test for user preference font size when learning Xamarin or beginning a project. As a later improvement, they should be able to enable FontUserScaled for particular controls where it makes sense and they have tested for the side effects across devices to accomodate users with poor eyesight.

Background

On Android, Xamarin Forms uses "Scaled Pixels" for font sizes (see github search below). Android also offers "Device Independent Pixels". The difference is that with SP's, all your font sizes and therefore layout is at the mercy of the user font size preference. Text on buttons and labels wraps or is cropped, or the control resizes to accomodate, perhaps breaking other things. I bet the layout breaks on most XF apps when the user preference is set to "Extra Large" or "Huge" because of this, on top of all the other cross platform concerns.

See discussion here : https://forums.xamarin.com/discussion/comment/218238#Comment_218238

To use SP's properly, the developer must think in fluid layout terms for the whole layout. It makes sense for long text areas for users with poor eyesight, but this is generally a more advanced concern, than just getting the layout to work.

From my brief research, iOS has no equivalent to SP's (instead the app can look up the user preference and adjust font sizes in code). This creates an inconsistency between iOS and Android versions of an Xamarin Forms app.

Therefore, DiPs would have been a more reliable and cross-platform-consistent choice for Xamarin Forms in the beginning, but this can still be fixed now.

References

Tagged:

Accepted · Last Updated

No implementor has been assigned. Let us know in a comment below if you wish to implement this proposal.

Posts

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    iOS has something of an equal in dynamic type. It's not 100% the same though.

    I propose a different method. All naming below is placeholder and not intended to be final, just to be clear for the sake of the demo.

    public class FontSizeType
    {
      public FontSizeType DevicePixel { get; }
      public FontSizeType UserScaledPixel { get; }
      public FontSizeType Default { get; } = UserScaledPixel;
    
      // protected ctor
      protected FontSizeType ();
    
      public static void SetDefault (FontSizeType type)
      {
        if (type != DevicePixel && type != UserScaledPixel)
            throw new ArgumentException ();
    
        // Do not actually change Default private value, just change how it is interpretted when encountered.
      }
    }
    
    var buttonSomewhereOnPage = new Button ();
    buttonSomewhereOnPage.FontSizeType = FontSizeType.DevicePixel; // default value is FontSizeType.Default;
    
  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Personal 2cents worth...
    While it is a nice feature I wouldn't call it 'fixing' anything. Circumventing the user's desire to increase font size because they have poor eye-sight is the user's decision, not the app coder's. It personally bugs the heck out of me that apps such as FacebookMessenger don't honor the increased font size I set in system preferences on my iPhone. As a result of those developers not honoring standards I don't use their app.

    If this feature is to be created it should be more than a bool. It should be a decimal indicating how much the user has scaled the fonts size system wide. That way the app can reverse calculate to get the originally intended font size.

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    Getting the percentage intended scale can't be done on some platforms :/

  • GaryMcGheeGaryMcGhee AUMember ✭✭

    This isn't about circumventing anything - its about the app developer being fully in control of sizing and therefore layout by default, and then the ability to enable support for user preference as and when they are ready.

    The current situation is that in plain XF we don't have control and only advanced developers know how to prevent their Android layout being busted by user preference.

  • JamesMontemagnoJamesMontemagno USForum Administrator, Xamarin Team, Developer Group Leader Xamurai
    edited December 2016

    All Android fonts should always be sized using SP as the user should be in control to scale the fonts. If you use DP then the app would ignore the setting for accessibility and it would be a huge step backwards.

    All Android themes and documentation use SP: https://material.io/guidelines/style/typography.html and is the official guideline when it comes to Android development.

    The actual proposal would be larger and actually update iOS for dynamic type, which would be very nice.

    In this instance the system default should be applied, which is expected, to use scaled based on user, and like Jason has said maybe something to turn it off.

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    We are accepting this proposal with the implementation I proposed above.

  • GaryMcGheeGaryMcGhee AUMember ✭✭

    Good to hear that we will have the option :)

    If SP remains the Android default without SP being emulated on iOS, then it should be documented in the cross-platform section that Android is dependent on user preferences but iOS isn't, and developers should test their apps for different user font preferences.

    I'm not quite sure what the code above means. Would I be able to set the default for my project or form? Or could I set all buttons to DevicePixel by a style?

  • AlexanderFearAlexanderFear GBMember ✭✭

    For me (who has encountered this problem of our apps not responding in iOS only today), I would like the framework to commit to honouring the accessibility font-size settings in iOS which the user makes on the device the same as it does in Android, but allow the app developer to switch that off easily (or vice versa).
    This would allow us to reliably address as simply as possible the issue of the what must be the largest (and presumably fastest growing) single group of users who suffer accessibility issues - those with age-related eyesight degradation.

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    @TheRealJasonSmith Why do you need FontSizeType to be a class? It could be an enum and when it's changed, UpdateFont() on the renderers will be triggered to scale text.

    // Do not actually change Default private value, just change how it is interpretted when encountered.

    What could possibly go in SetDefault() that cannot be done by renderers? I'm trying to understand the use-case for this method.

    Also would love to see this on your roadmap.

  • AdrianGrigoreAdrianGrigore DEMember ✭✭

    @AdrianKnight said:
    Also would love to see this on your roadmap.

    Me too. Honestly I cannot believe this is not already part of the framework.

  • AdamHillAdamHill USBeta ✭✭

    @JamesMontemagno so could we get some guidance on the best practice to set FontSize in Xamarin currently?

    Do we have to be resigned to use <OnPlatform> everywhere? It is a big pain point for developers coming into the platform, especially when we have tools like Zeplin and Sketch that will give us awesome measurements & percentages, then we discover they don't look the same on different OS's.

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Couldn't you define it in a Style which would then be used throughout your app?
    Thus when you get told by the boss... Make all the 'normal' text 2 points bigger you just update the 'NormalStyle' definition.
    The Style would carry <OnPlatform>.

  • AdamHillAdamHill USBeta ✭✭

    Styles were a given. I was thinking more "Here is a formula you could use to convert from DP to SP" or let us specify a system converter / flag at a control/page level to say "Use SP's rather than DP's when you see a Double in this control"

  • GaryMcGheeGaryMcGhee AUMember ✭✭

    Still no action on this (I've searched the source on GitHub).

    It says above "No implementor has been assigned. Let us know in a comment below if you wish to implement this proposal" but it really needs to be embraced by the Xamarin team across all current and future controls.

  • TimRossTimRoss USMember ✭✭

    Thanks Gary for posting this. Still waiting on some action. The issue isn't limited to font size, there is also a display size setting on android that completely resizes all the elements on an app. Would like a way to disable these. With both of these set to max it completely alters the original design of the app.
    Yes, designing an app to be able to handle all of these different scenarios is ideal, but in the real world we have deadlines...

Sign In or Register to comment.