Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

font size scaling in Windows Store Universal App (W8.1 + WP8.1)

How do i scale text in Windows Store Universal App (W8.1 + WP8.1)? Basically, the app should look the same regardless which device/resolution is used. The current situation is that layout (dynamic grid based layout) and images scale well except of the text (font size).

The text displayed looks nice for WVGA resolution (480 × 800) but is incredible small for 1080p resolution.

I already read a lot of stuff like Guidelines for scaling to pixel density or Guidelines for supporting multiple screen sizes

But i still don't know how to scale text to stay readable regardless of display resolution/DPI.

Of course i could write a class which uses the DisplayInformation.ResolutionScale property to convert the font size to an appropriated value.

example:

  • FontSize 16 on WVGA with ScaleFactor 1x equals FontSize 16
  • FontSize 16 on WXGA with ScaleFactor 1.6x equals FontSize 25,6
  • FontSize 16 on 720p with ScaleFactor 1.5x equals FontSize 24
  • FontSize 16 on 1080p with ScaleFactor 2.25x equals FontSize 36

But I'm uncertain if this will work for all scenarios. Is there a better way to do so? I thought such a common task could be performed with some build in functionality.

Disclaimer: this is (hopefully) not a "let me google this for you question" I found tons of pages which are about scaling but they all cover the layout or images. But I couldn't find anything about font size scaling. Please forgive me if I missed something.


Edit: I'm afraid, i failed to express the problem clearly: (WVGA on the left, 1080p on the right) WVGA vs. 1080p
like image 203
Joel Avatar asked Apr 13 '14 11:04

Joel


4 Answers

What I did for my Windows Store app was to bind the FontSize property to the page height and convert the value (you'd have to play a bit, until you find the right value for your case).

<TextBlock Grid.Row="0" Text="Some Text" 
FontSize="{Binding ElementName=pageRoot, Path=ActualHeight, 
Converter={StaticResource PageHeightConverter}, ConverterParameter='BodyFontSize'}" />

And here's my Converter class

    class PageHeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        switch ((string)parameter)
        {
            case "HeroImage":
                return ((((double)value) * 2) / 3);
            case "TitleFontSize":
                return (int)((double)value / 40);
            case "BodyFontSize":
                return (int)((double)value / 60);
            default:
                return 0;
        }
    }
}

It's not perfect, but works pretty well until I find a perttier solution.

like image 138
smeshko Avatar answered Oct 17 '22 04:10

smeshko


I found that using the IValueConverter method worked pretty well when used in conjunction with the ResolutionScale property:

class ScaleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var resolutionScale = (int)DisplayInformation.GetForCurrentView().ResolutionScale / 100.0;
        var baseValue = int.Parse(parameter as string);
        var scaledValue = baseValue * resolutionScale;
        if (targetType == typeof(GridLength))
            return new GridLength(scaledValue);
        return scaledValue;
    }
}

Please note, that if you use for more than FontSize (as I am also using it for ColumnDefinition.Width) you will need to handle returning the proper Type'ed output.

My XAML usage looks something like this:

<TextBlock Text="string" FontSize="{Binding ElementName=root, Path=ActualHeight, Converter={StaticResource ScaleConverter}, ConverterParameter='30'}" />

And to just complete the solution, for each XAML page you use this on, you need to include the following, replacing SwapChainBackgroundPanel with whatever class you are using, and defining the xml namespace properly:

<SwapChainBackgroundPanel.Resources>
    <local:ScaleConverter x:Key="ScaleConverter"></local:ScaleConverter>
</SwapChainBackgroundPanel.Resources>
like image 42
Nick Banks Avatar answered Oct 17 '22 05:10

Nick Banks


WinRT can automatically scale everything running on top of it and will do so based on the display's pixel density. In Windows 8.0 it used to scale in 100%, 140% and 180%. Newer version might have even more scale factors. I do not believe that you can opt out of this scaling.

If you are not interested in using the built-in scaling which operates on a system level, then you are pretty much forced to do everything yourself. You can scale the text manually by setting the font size or you can use the power of transforms to scale either your text or your whole UI.

like image 2
Kasper Holdum Avatar answered Oct 17 '22 06:10

Kasper Holdum


Your sample images are misleading because the actual size of the devices would be different as well. This blog post tells you how to setup emulators for a more accurate representation.

If you want the exact same content on every screen (ie, a 6" phone just shows a blown-up version of a 4" phone, rather than showing 50% more content) then use a ViewBox to scale your app. This is not a particularly good user experience though.

like image 1
Peter Torr - MSFT Avatar answered Oct 17 '22 04:10

Peter Torr - MSFT