Масштабирование размера шрифта в универсальном приложении Windows Store (W8.1 + WP8.1)
Как масштабировать текст в Windows Store Universal App (W8.1 + WP8.1)? В принципе, приложение должно выглядеть одинаково независимо от того, какое устройство/разрешение используется. Текущая ситуация заключается в том, что макет (макет динамической сетки) и изображения хорошо масштабируются, за исключением текста (размер шрифта).
Отображаемый текст выглядит хорошо для WVGA-разрешения (480 × 800), но невероятно мало для разрешения 1080p.
Я уже много читал
Рекомендации по масштабированию плотности пикселей или
Рекомендации по поддержке нескольких размеров экрана
Но я до сих пор не знаю, как масштабировать текст, чтобы оставаться читаемым, независимо от разрешения экрана /DPI.
Конечно, я мог бы написать класс, который использует свойство DisplayInformation.ResolutionScale для преобразования размера шрифта в присваиваемое значение.
Пример:
- FontSize 16 на WVGA с ScaleFactor 1x равен FontSize 16
- FontSize 16 на WXGA с ScaleFactor 1.6x равен FontSize 25,6
- FontSize 16 на 720p с ScaleFactor 1.5x равен FontSize 24
- FontSize 16 на 1080p с ScaleFactor 2.25x равен FontSize 36
Но я не уверен, что это будет работать для всех сценариев. Есть ли лучший способ сделать это? Я думал, что такая общая задача может быть выполнена с некоторой функциональностью.
Отказ от ответственности:
это (надеюсь) не "позвольте мне ответить на этот вопрос для вас". Я нашел массу страниц, которые касаются масштабирования, но все они покрывают макет или изображения. Но я не мог найти ничего о масштабировании размера шрифта. Пожалуйста, простите меня, если я что-то пропустил.
Изменить: Боюсь, я не смог четко выразить эту проблему: (WVGA слева, 1080p справа)
Ответы
Ответ 1
То, что я сделал для моего приложения Windows Store, было привязать свойство FontSize к высоте страницы и преобразовать значение (вам придется немного поиграть, пока не найдете правильное значение для вашего случая).
<TextBlock Grid.Row="0" Text="Some Text"
FontSize="{Binding ElementName=pageRoot, Path=ActualHeight,
Converter={StaticResource PageHeightConverter}, ConverterParameter='BodyFontSize'}" />
И вот мой класс конвертера
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;
}
}
}
Это не идеально, но работает очень хорошо, пока я не найду более мягкое решение.
Ответ 2
Я обнаружил, что использование метода IValueConverter очень хорошо работает при использовании в сочетании с ResolutionScale свойство:
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;
}
}
Обратите внимание, что если вы используете больше, чем FontSize (поскольку я также использую его для ColumnDefinition.Width), вам нужно будет обрабатывать возвращаемый правильный вывод типа.
Использование моего XAML выглядит примерно так:
<TextBlock Text="string" FontSize="{Binding ElementName=root, Path=ActualHeight, Converter={StaticResource ScaleConverter}, ConverterParameter='30'}" />
И чтобы просто завершить решение, для каждой страницы XAML, в которой вы используете это, вам необходимо включить следующее, заменив SwapChainBackgroundPanel на любой класс, который вы используете, и правильно определите пространство имен xml:
<SwapChainBackgroundPanel.Resources>
<local:ScaleConverter x:Key="ScaleConverter"></local:ScaleConverter>
</SwapChainBackgroundPanel.Resources>
Ответ 3
WinRT может автоматически масштабировать все, что работает поверх него, и будет делать это на основе плотности пикселей дисплея. В Windows 8.0 он использовался для масштабирования в 100%, 140% и 180%. Более новая версия может иметь еще более масштабные коэффициенты. Я не считаю, что вы можете отказаться от этого масштабирования.
Если вы не заинтересованы в использовании встроенного масштабирования, который работает на системном уровне, то вы в значительной степени вынуждены делать все сами. Вы можете масштабировать текст вручную, задав размер шрифта, или вы можете использовать силу преобразований для масштабирования вашего текста или всего пользовательского интерфейса.
Ответ 4
Образцы ваших образцов вводят в заблуждение, так как фактический размер устройств будет другим. В этом сообщении в блоге сообщается, как настроить эмуляторы для более точного представления.
Если вам нужен точный контент на каждом экране (т.е. 6-дюймовый телефон просто показывает взорванную версию 4-дюймового телефона, вместо того, чтобы показывать на 50% больше контента), используйте ViewBox
, чтобы масштабировать ваше приложение. Однако это не очень хороший пользовательский интерфейс.
Ответ 5
Я жду ответа на этот вопрос и сам разместил связанный с ним вопрос.
В качестве промежуточного решения я использовал iValueConverter, и это работает при определенных разрешениях, но не в других.
Мой iValueConverter выглядит следующим образом:
class FontSizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var display = Helpers.ScreenResolution();
var height = display.Height;
var oldFontSize = (int)value;
if(oldFontSize == null) return;
// Calculate the new Fontsize based on the designed Fontsize
// and design display size in Visual Studio designer...
var newFontSize = (int)Math.Round((oldFontSize / 768.0) * height, 0);
return newFontSize;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}}
Надеюсь, это поможет...