font size best practices?

I've been doing some R&D with Xamarin Forms for the past few days, basically trying to create a screen from a design we used for an iPhone app. For the most part, I can get things laid out where I want them to be. The biggest inconsistency in terms of appearance right now is the fonts, they look smaller on Android than on the other two platforms.

I'm using the same NamedSize values for all of my labels currently. With Forms I know you are supposed to avoid explicit size values when possible, but I anticipate the predefined NamedSize values aren't always going to be what I need. To reach the highest level of detail, do I need to set an explicit numerical value on each platform until it looks right, or is there a better way? What is the best practice of setting font sizes in Xamarin Forms?

Posts

  • SKallSKall USMember ✭✭✭✭

    To get almost identical size fonts I created a font service that calculates the actual height of a font and you can also request the size closest to an actual size (like .25 inches).

    https://github.com/XForms/Xamarin-Forms-Labs/blob/master/src/Xamarin.Forms.Labs/Xamarin.Forms.Labs/Services/IFontManager.cs

    The implementations are part of Xamarin.Forms.Labs. Below are screenshots for Lumia 1020 (high-res screen) vs 521 (low-res screen) + Android (Samsung GS3).

  • Thanks for the reply, Sami. This seems to be what I am looking for.

    I am kind of surprised this functionality isn't baked into XF. Are there plans to add it in the future?

  • VincentPoirierVincentPoirier CAMember ✭✭

    We have a similar issue. Our App works well on Nexus 4 and all the sizes are OK, but when we open it on a tablet, it's too small. Is there a way to give the fonts a proportional/adaptative size using XAML?

    <Label Text="{Binding Title}"
           FontSize="???"/>
    
  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    I'm stuck with this too - I have two Samsung devices, one 10.1” and the other 7”. I am setting the font size using the FontSize NamedSize enumeration. I was expected the font size to change between the devices, but it remains the exactly the same (I measured..) The font on the 10.1” looks tiny even though I'm using

    <Setter Property="FontSize" Value="Large"/>

    The IFontManager looks promising - I cant find an example of how to use it though

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    I am trying to uses the labs FontManager but I cannot get a valid system font:

    var font = Font.SystemFontOfSize(NamedSize.Large, FontAttributes.None);

    The returned font is always zero in size, I need to pass a valid font to the FontManager. What am I missing here?

  • Since the time of this posting, Xamarin has added the FontSize property to Labels.

    Now you can do:

    var myLabel = new Label() { FontSize = 12 }

    You can get a lot more detailed with your text size going this route as opposed to the built in NamedSize enumerations.

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    Thanks, but I'm trying to automatically change the font size based on the size of the device. I guess I have to calculate it myself? The Labs FontManager seem out of date and the NamedSize enumerations don't work.
    How did you solve your issue?

  • Ah, gotcha. My issue was that FontSize wasn't implemented out of the box at the time of this posting so you only had access to a handful of font sizes, unless you used XLabs. It's built into Forms now, although I'm not sure if it scales to device dimensions like XLabs did.

    Android fonts do appear slightly smaller with on larger screen sizes than iOS fonts, but our app runs only on phones so it's not a big discrepancy. If you do find a way to size fonts based on device size I would be interested in hearing how you did it.

  • SKallSKall USMember ✭✭✭✭

    I updated the XLabs sample page for font manager and it seems that WP and Android work as before but iOS is broken and doesn't get the correct font size. I am looking into the reason.

    https://github.com/XLabs/Xamarin-Forms-Labs/blob/master/Samples/XLabs.Sample/Pages/Services/FontManagerPage.cs

  • SKallSKall USMember ✭✭✭✭

    iOS now works as well. I am planning to do NuGet push this weekend for the latest version.

  • PhilipOGormanPhilipOGorman USMember ✭✭✭
    edited April 2015

    Sami - Thanks for the update and the code. I added a FontSizeProvider to my viewModels and bind my FontSizes to the properties.

    It's really frustrating that the NamedSize enumerations don't work well. Large was the same on 10.1” and 7” devices. But your code is a big help

    `
    public class FontSizeProvider : IFontSizeProvider
    {

        public IFontManager FontManager { get; private set;}
    
        public FontSizeProvider(IFontManager fontManager)
        {
            FontManager = fontManager;
    
            var f = Font.SystemFontOfSize(24);
            _fontLarge = fontManager.FindClosest(f.FontFamily, 0.25).FontSize;
            _fontMediumLarge = fontManager.FindClosest(f.FontFamily, 0.2).FontSize;
        }
    
        #region IFontSizeProvider implementation
    
        private double _fontLarge;
        public double FontLarge
        {
            get
            {
                return _fontLarge;
            }
        }
    
        private double _fontMediumLarge;
        public double FontMediumLarge
        {
            get
            {
                return _fontMediumLarge;
            }
        }
    
        #endregion
    }`
    
  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    ok - in hindsight what I really needed was an extra large font, and I don't really understand how the font sizes translate device to device. For example I have the following numbers for my 7" and 10.1" devices:

    [Screen: Height=800, Width=1280, Xdpi=188.1, Ydpi=189.0]
    Large 18.000 height0.127in
    Medium 14.000 height0.099in
    Xamarin label Large 21.784 Medium 18.028

    Screen: Height=800, Width=1280, Xdpi=142.6, Ydpi=136.4]
    Large 18.000 height0.132in
    Medium 14.000 height0.103in
    Xamarin label Large 22.000 Medium 18.000

    It shows that the font height in inches is being scaled from device to device, but on a large device the font just looks very small. When I used a font size of 40, it looks fine on the big device but huge on the smaller device - should it not scale down??

    Anyway for my extralarge font I calculate the height as a function of the Xdpi, on the 7" and 10.1" device I now get the following:

    ExtraLarge 28.701 height0.202in
    ExtraLarge 37.869 height0.278in

    Although the Font sizes are very different - they now look the same relative to the screen size holding the devices side by side.

    Can anyone explain what font sizes mean relative to the screen size??

    Anyway here is the code for ExtraLarge font:

    `public class FontSizeProvider : IFontSizeProvider
    {

        public IFontManager FontManager { get; private set;}
        public IDisplay Display { get; private set;}
    
        public FontSizeProvider(IFontManager fontManager, IDisplay display)
        {
            FontManager = fontManager;
            Display = display;
    
    
            var largeFont = Font.SystemFontOfSize(NamedSize.Large);
            var extraLargeHeight = fontManager.GetHeight(largeFont)*(100/(Display.Xdpi))*3; // scale up
            _extraLarge = display.HeightRequestInInches(extraLargeHeight);
    
            var largeHeight = fontManager.GetHeight(largeFont);
            var large = display.HeightRequestInInches(largeHeight);
    
            var mediumFont = Font.SystemFontOfSize(NamedSize.Medium);
            var mediumHeight = fontManager.GetHeight(mediumFont);
            var medium = display.HeightRequestInInches(mediumHeight);
    
            Debug.WriteLine(Display.ToString());
            Debug.WriteLine(string.Format("ExtraLarge {0:0.000} height{1:0.000}in", ExtraLarge, extraLargeHeight));
            Debug.WriteLine(string.Format("Large {0:0.000} height{1:0.000}in", large, largeHeight));
            Debug.WriteLine(string.Format("Medium {0:0.000} height{1:0.000}in", medium, mediumHeight));
    
            Debug.WriteLine(string.Format("Xamarin label Large {0:0.000} Medium {1:0.000}", 
                Device.GetNamedSize(NamedSize.Large, typeof(Label)), Device.GetNamedSize(NamedSize.Medium, typeof(Label))));
        }
    
        #region IFontSizeProvider implementation
    
        private readonly double _extraLarge;
        public double ExtraLarge
        {
            get
            {
                return _extraLarge;
            }
        }
    
        #endregion
    }`
    
  • JasonMichasJasonMichas USMember ✭✭

    @PhilipOGorman Can you post a more complete example of how you use your FontSIzeProvider? I'm trying to accomplish the same thing but Im not sure how this is put together. Is there an implementation on each platform or is this only in the core PCL?

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    @JasonMichas In my case using the named large font size looked way too small on the large (10"+) android tablets. So what I did was instead of using the named large font size, I bound the font size to a ExtraLarge property that all my viewmodels have:

    View:

    <Label Text = "Field Settings" FontSize = "{Binding FontSizeProvider.ExtraLarge}" HorizontalOptions="Center" VerticalOptions="FillAndExpand" Style="{StaticResource LabelStyle}" />

    ViewModel FontSizeProvider:

    `public class FontSizeProvider : IFontSizeProvider
    {

        public IFontManager FontManager { get; private set;}
        public IDisplay Display { get; private set;}
    
        public double ScreenHeightInches { get; private set;}
        public double ScreenWidthInches { get; private set;}
    
        public FontSizeProvider(IFontManager fontManager, IDisplay display)
        {
            FontManager = fontManager;
            Display = display;
    
            ScreenHeightInches = (double)Display.Height / Display.Ydpi;
            ScreenWidthInches = (double)Display.Width / Display.Xdpi;
    
            var largeFont = Font.SystemFontOfSize(NamedSize.Large);
            var largeHeight = fontManager.GetHeight(largeFont);
            var large = display.HeightRequestInInches(largeHeight);
    
            if (ScreenHeightInches > 5)
            {
                _extraLarge = large * 2;
            }
            else
            {
                _extraLarge = large;
            }
    
            var mediumFont = Font.SystemFontOfSize(NamedSize.Medium);
            var mediumHeight = fontManager.GetHeight(mediumFont);
            var medium = display.HeightRequestInInches(mediumHeight);
    
            Debug.WriteLine(Display.ToString());
            Debug.WriteLine(string.Format("ExtraLarge {0:0.000}", ExtraLarge));
            Debug.WriteLine(string.Format("Large {0:0.000} height{1:0.000}in", large, largeHeight));
            Debug.WriteLine(string.Format("Medium {0:0.000} height{1:0.000}in", medium, mediumHeight));
    
            Debug.WriteLine(string.Format("Xamarin label Large {0:0.000} Medium {1:0.000}", 
                Device.GetNamedSize(NamedSize.Large, typeof(Label)), Device.GetNamedSize(NamedSize.Medium, typeof(Label))));
    
    
    
        }
    
        #region IFontSizeProvider implementation
    
        private readonly double _extraLarge;
        public double ExtraLarge
        {
            get
            {
                return _extraLarge;
            }
        }
    

    }`

    Hope this helps

  • @PhilipOGorman said:
    Sami - Thanks for the update and the code. I added a FontSizeProvider to my viewModels and bind my FontSizes to the properties.

    It's really frustrating that the NamedSize enumerations don't work well. Large was the same on 10.1” and 7” devices. But your code is a big help

    `
    public class FontSizeProvider : IFontSizeProvider
    {

        public IFontManager FontManager { get; private set;}
    
        public FontSizeProvider(IFontManager fontManager)
        {
            FontManager = fontManager;
    
            var f = Font.SystemFontOfSize(24);
            _fontLarge = fontManager.FindClosest(f.FontFamily, 0.25).FontSize;
            _fontMediumLarge = fontManager.FindClosest(f.FontFamily, 0.2).FontSize;
        }
    
        #region IFontSizeProvider implementation
    
        private double _fontLarge;
        public double FontLarge
        {
            get
            {
                return _fontLarge;
            }
        }
    
        private double _fontMediumLarge;
        public double FontMediumLarge
        {
            get
            {
                return _fontMediumLarge;
            }
        }
    
        #endregion
    }`
    

    Can you please provide me the whole code snippet for this Font Manager please?

  • @SKall said:
    I updated the XLabs sample page for font manager and it seems that WP and Android work as before but iOS is broken and doesn't get the correct font size. I am looking into the reason.

    https://github.com/XLabs/Xamarin-Forms-Labs/blob/master/Samples/XLabs.Sample/Pages/Services/FontManagerPage.cs

    Hello ,

    Can you please provide me the sample code project for this Font Manager? Your help will be appreciated.

  • MohanadZahedMohanadZahed DEMember ✭✭
    edited July 2017

    if anyone still searching for the solution , I have found one ;

    SizeChanged += (object sender, EventArgs args) =>
                {
                    if (this.Height > 0)
                    myLabel.FontSize = this.Height / 40;
                };
    

    just add those lines in the code behinde after InitializeComponent(); and change the number into what suits your preferences.

    Now whatever the screen size is or how it rotates, the label will responde to it and change its size accordingly , you can add any element of course.

  • JohnHardmanJohnHardman GBUniversity mod

    @MohanadZahed - What happens if the user has particularly accessibility requirements, and has increased the font sizes in the device's settings?

Sign In or Register to comment.