Pull to refresh
VK
Building the Internet

Адаптация приложений Windows Phone для больших экранов

Reading time 7 min
Views 7K
Неделю назад в продаже появились планшетофоны Nokia. Обновление операционной системы Windows Phone с маркировкой GDR3 стало поддерживать 4-ядерные процессоры и разрешение экрана до FullHD. Именно с такими характеристиками Nokia выпустила свой новый флагман Lumia 1520. Но производитель не стал просто увеличивать плотность размещения пикселей при тех же размерах экрана, как это сделали в конкурентных моделях на ОС Android компании HTC и Samsung. Nokia выпустила аппарат с диагональю экрана 6 дюймов, немного обогнав даже третью версию родоначальника планшетофонов Galaxy Note. Размер экрана и самого аппарата завораживает и пугает одновременно. Но, отбросив лирику, попытаемся разобраться, как нам, разработчикам, с этим жить.


Итак, основные пункты, которые нужно учесть при адаптации приложения под новые телефоны:
— Соотношение сторон экрана 16:9;
— FullHD разрешение экрана;
— Размер экрана 6 дюймов.
Теперь подробнее и по порядку.

16:9



Экраны с соотношением 16:9 немного более вытянуты по сравнению с экранами 15:9. В принципе, такое соотношение сторон у смартфонов далеко не в новинку. Поддержка экранов с разрешение 1280х720 была введена год назад с появление Windows Phone 8. Программы, написанные под WP7, запускаются на смартфонах с такими экранами, однако, для соблюдения пропорций, система оставляет сверху черную полосу. До последнего момента единственным аппаратом с таким разрешением экрана был Samsung ATIV S, а учитывая долю Samsung на рынке WP (около 1,8% по состоянию на ноябрь 2013), на поддержку этого разрешения можно было не тратить много времени.

Но с приходом FullHD-разрешения и аппаратов Lumia 1520 и Lumia 1320, с соотношением сторон 16:9 теперь придется считаться, так как доля Nokia на рынке Windows Phone составляет 90%, к тому же речь идет о новом флагмане.

Что это значит для разработчика? Раньше для охвата большинства пользователей WP7 и WP8 достаточно было иметь одну версию приложения, скомпилированную под WP7. Более того, если вам не нужен был особый функционал, появившийся в WP8 (а различий было крайне мало), то разрабатывать ПО под две платформы вообще не было никакого смысла. Сейчас для поддержки вытянутых экранов необходимо перекомпилировать приложение под Windows Phone 8, так как только в этом случае в манифесте можно указать системе, что приложение готово к соотношению сторон экрана 16:9. Также нужно подготовить новые графические ресурсы в масштабе 150% от «обычного» разрешения 800х480 (для экранов 720p) и убедиться, что расположение элементов выглядит гармонично на вытянутом экране.

FullHD



Казалось бы, тут все просто:
— получаем значение масштаба с помощью известного в WP8 свойства Application.Current.Host.Content.ScaleFactor;
— проверяем, равно ли оно 225 (1080 / 480 = 2,25);
— PROFIT!..

Но не тут-то было. Потому что получаем мы не 225, а 150. «Какого?!..», — воскликните вы, и будете совершенно правы. Так как проверка на увеличение масштаба до 150% была единственным способом, с помощью которого приложение определяло, на каком экране оно запущено, и соответственно этому размещало элементы, то для совместимости старого ПО с новыми экранами было решено для экранов с пропорциями 16:9 возвращать именно этот масштаб.

Но не стоит отчаиваться: с выходом GDR3 у разработчиков появилась новая возможность определения физического разрешения экрана:

var resolution = (Size)DeviceExtendedProperties.GetValue("PhysicalScreenResolution");


Внимание: на версиях WP8 до GDR3 вызов метода GetValue с параметром PhysicalScreenResolution выбросит исключение. Нужно быть к этому готовым, однако вы можете быть уверены, что имеете дело с экраном 1280х720. Если же результат удалось получить, то значение _resolution.Width даст вам точную ширину экрана в пикселях: 720 или 1080 (мы все еще говорим только об экранах 16:9). Теперь вы можете ориентироваться на это и правильно загружать растровые ресурсы. Кстати, не забудьте их подготовить в масштабе 225%.

P.S. Помните, что при верстке XAML даже для разрешения FullHD все размеры и отступы нужно указывать как для разрешения WVGA (480х800).

P.P.S. Если у вас еще нет нового аппарата на GDR3, но уже хочется протестировать в приложении поддержку вызова DeviceExtendedProperties.GetValue(«PhysicalScreenResolution»), то можно установить на телефон приложение Preview for Developers и разрешить в нем устанавливать на телефон обновления для разработчиков. После этого нужно зайти в обновление телефона и выполнить проверку наличия обновлений. И да, телефон должен быть разблокированным для разработки.

6 дюймов



Ну а теперь самое вкусное — поддержка огромных экранов.
Во-первых, нужно определить, с чем мы имеем дело. В GDR3 появилось еще одно свойство, которое говорит нам о характеристиках аппарата:

var screenDpiX = (double)DeviceExtendedProperties.GetValue("RawDpiX");
var screenDpiY = (double)DeviceExtendedProperties.GetValue("RawDpiY");


Это вертикальная и горизонтальная плотность пикселей экрана. Зная плотность и физическое разрешение (см. предыдущий раздел), легко посчитать ширину и высоту экрана, а дальше обратиться к теореме Пифагора:

var screenSize = Math.Sqrt(Math.Pow(resolution.Width / screenDpiX, 2) +
                           Math.Pow(resolution.Height / screenDpiY, 2));


Тут-то мы и получаем искомые 6 дюймов. Встает вопрос: что считать большим экраном? На своей страничке для разработчиков Nokia предлагает считать «большим» экраном любой с диагональю больше 5 дюймов. Положимся на их мнение (они-то могут знать, какие аппараты мы вскоре увидим):

var isBigScreen = (screenSize > 5.0);


Когда мы знаем, что имеем дело с большим экраном, нужно немного адаптировать контент.

Если в интерфейсе вы используете плитки, то можно сделать их в три колонки вместо двух, по аналогии со стартовым экраном. Размеры элементов и шрифтов сделать немного меньше, чтобы разместить на экране больше контента. Для этого в ресурсах объявляете набор констант, на которые ссылаетесь в остальных xaml-файлах, а при обнаружении большого экрана подменяете эти константы меньшими.
Пример
ScreenNormal.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
					xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
					xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
					xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    xmlns:system="clr-namespace:System;assembly=mscorlib"
                    mc:Ignorable="d">
    <system:Double x:Key="SmallThumbSize">75</system:Double>
    <system:Double x:Key="SmallIconFontSize">75</system:Double>
    <system:Double x:Key="ListNameFontSize">32</system:Double>
    <system:Double x:Key="ListDescFontSize">20</system:Double>
    <Thickness x:Key="ListItemMargin">0,10,0,10</Thickness>
</ResourceDictionary>


ScreenBig.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
					xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
					xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
					xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    xmlns:system="clr-namespace:System;assembly=mscorlib"
                    mc:Ignorable="d">
    <system:Double x:Key="SmallThumbSize">56</system:Double>
    <system:Double x:Key="SmallIconFontSize">56</system:Double>
    <system:Double x:Key="ListNameFontSize">24</system:Double>
    <system:Double x:Key="ListDescFontSize">15</system:Double>
    <Thickness x:Key="ListItemMargin">0,6,0,6</Thickness>
</ResourceDictionary>


App.xaml

<Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Styles/ScreenNormal.xaml" />
            </ResourceDictionary.MergedDictionaries>



App.xaml.cs

            if (Platform.PlatformHelper.IsBigScreen)
            {
                var appTheme = new ResourceDictionary
                    {
                        Source = new Uri("/[projectname];component/Styles/ScreenBig.xaml", UriKind.Relative)
                    };
                Resources.MergedDictionaries.Add(appTheme);
            }



Весь процесс с исходным кодом описан на сайте Nokia для разработчиков. Там достаточно подробно рассказано, как именно можно адаптировать приложение, но я немного добавлю от себя.

Во-первых, на сколько именно нужно уменьшать размер элементов для больших экранов?
В статье Resolution specific considerations разработчики из Nokia дают совет умножать изначальный размер на 0,711. Они исходят из того, что масштаб на WXGA экранах равен 1,6, а масштаб для FullHD экранов 2,25. Из этого выводим соотношение: 1,6/2,25 = 0,711.

В этом методе меня настораживает тот факт, что никак не учитывается физический размер экрана. Как пользователь HTC Titan, а затем Lumia 920, я привык к размеру экрана около 4,5 дюймов. Исходя из этого, вычисляем пропорцию диагоналей экрана 4,5/6 = 0,75. Для небольших экранов, таких как в Lumia 620 (3,8 дюйма), вычисляем соотношение с возможным экраном в 5 дюймов: 3,8/5 = 0,76. Таким образом, нужно брать за эталон экраны с диагональю 3,8-4,5 дюйма (100%), а для экранов 5-6 дюймов уменьшать размеры на 25%.

Кстати, не забывайте менять не только размеры элементов и шрифтов, но и отступы (Margin), иначе элементы разлетятся друг от друга.
Во-вторых, подмена констант, как описано в вышеуказанном примере, хорошо работает для DataTemplate'ов, которые применяются в момент отображения списков.

Параметры элементов не в списках мы обычно описываем в стилях. Стили объединяем в словари ресурсов (ResourceDictionary), на которые ссылаемся в App.xaml. Если же в таких стилях вы сошлетесь на константы размеров, а потом подмените эти константы, то обнаружите, что ничего не изменилось. Это происходит потому, что объект стиля был сформирован при парсинге словаря и подмена констант уже не влияет на размеры в нем. Выносите ссылки на константы из стиля в сами объекты.

Но и это еще не все. Если вы попытаетесь указать ссылку на константу в качестве размера элемента, который создается в самом начале запуска приложения (например, заголовок главного окна), то обнаружите, что подмена констант никак не сказалась на размере. Элемент успел сформироваться до подмены констант. В таком случае можно сделать класс ScreenSizeHelper, в котором определить ряд свойств, описывающих размеры, а экранные элементы привязать (binding) к этим свойствам.

Из практики


В заключение хочется показать пример того, как данные советы были применены в одном из наших приложений Хаб Mail.Ru:
Список статей
Вот что было:

Вот что стало:


Текст статьи
Вот что было:

Вот что стало:


Как видите, на экране стало помещаться больше контента.
Кстати, приложение уже опубликовано в «Магазине приложений» и все владельцы планшетофонов могут в полной мере насладиться преимуществами большого экрана =)
Tags:
Hubs:
+18
Comments 14
Comments Comments 14

Articles

Information

Website
vk.com
Registered
Founded
Employees
5,001–10,000 employees
Location
Россия
Representative
Миша Берггрен