Привет, Хабр! Мы продолжаем нашу экспериментальную серию статей, наблюдая за которой вы можете в реальном времени влиять на ход создания игры на UWP. В этой части расскажем о стиле приложения и покажем, что делать красиво не так уж и сложно. Не забывайте оставлять комментарии!




Передаю слово автору, Алексею Плотникову.

Изначально в данной статье я планировал рассказать о стилизации заголовка окна и строки состояния, однако о заголовке мы в блоге Microsoft уже говорили и дублировать эту информацию не имеет никакого смысла, как и не имеет смысла затрагивать тему стилизации приложения в столь узком аспекте.

Что значит стилизация с точки зрения разработчика и являлись ли, например, стандартные программы Windows 2000 стильными? Безусловно являлись, если рассматривать термин «стилизация» исключительно в цифровом поле. Все элементы управления в системе имели одинаковый цвет и рельеф, а реакция на нажатие или наведение была привычной и ожидаемой вне зависимости от программы или отдельного окна в ней. И я не зря привел пример Windows 2000, так как за ней вышла Windows XP (Windows ME не в счет), которая принесла с собой существенные изменения в стиле элементов управления. Закругления, яркие цвета и более живая реакция на действия пользователя – все это появилось вместе с новой Windows, а каждая последующая версия продолжила эту традицию и ее внешний вид становился прямым продолжением актуальных тенденций в цифровом мире.

Выходит, что стиль в контексте разработки ПО – это то как выглядят наши элементы управления и программа в целом? Нет, потому что стиль – это, в первую очередь, согласованность внешнего вида внутри одной экосистемы и до недавнего времени такой экосистемой было принято считать всю ОС.

Изменения начались с приходом мобильных устройств, которые изменили философию взаимодействия с программой. Все больше пользователь стал воспринимать программу не как часть ОС, а как самостоятельную экосистему со своими внутренними правилами и особенности. Проще всего это понять, просматривая сайты в интернете. Пройдите по всем своим вкладкам в браузере, и вы увидите совершенно разные, не похожие друг на друга стили, но при этом, чаще всего, согласованные внутри одного сайта. Именно мобильные устройства стали стирать грань между правилами применимыми к сайтам, когда пользователь концентрируется на контенте и правилами мира ПО, где программа воспринималась, как часть ОС.

Впервые данную философию попыталась реализовать в Windows 8, когда, в определенном смысле, сама ОС была похожа на браузер, в котором мы запускали приложения словно сайты и вся концентрация была на их содержимом в отрыве от остальной ОС. Однако массовый пользователь таких изменений не понял, так как основной платформой Windows по-прежнему оставались персональные компьютеры. Когда же изменения, внесенные в Windows 8.1 тоже не помогли, на свет появилась Widows 10, где есть классические программы, все еще воспринимаемые как часть всей ОС и универсальные приложения, что в большинстве своем концентрируют внимание пользователя на себе.

Все эти рассуждения и экскурс в историю направлен на понимание единственного важного момента – ваше приложение UWP не столько часть операционной системы, сколько самостоятельный мир в который погружается пользователь. Точнее именно таким оно должно стремится стать.

«А что не так со стандартными элементами управления?» — спросите вы, ведь они имеют согласованный стиль как внутри приложения, так и во всей ОС в целом. А с ними все в полном порядке, при условии, что вы не против, чтобы ваше приложение превратилось для пользователя в одно из многих, что ничем ему не запомнится.

Несмотря на все вышесказанное крайне важно понимать, что без качественного функционала или контента, никакой собственный стиль не поможет вашему приложению добиться расположения пользователя и в то же время при наличии качественного наполнения, ваш стиль должен дополнять, а не извращать его восприятие.

Джентельменский набор красивого приложения


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



На рисунке выше показан пример настроек одного из моих UWP приложений «Шар напоминалка». Первая версия данного приложения была выпущена на Windows Phone 8.1 и с точки зрения основного функционала практически не отличалась от текущей UWP версии за исключением отсутствия уникального стиля. Важность наличия стилизации стала понятна благодаря мониторингу отзывов и оценок приложения, так как версия для UWP имеет оценку выше в среднем на 0,7 балла, а среди отзывов регулярно встречаются фразы «красиво» или «стильно».



Разберем какие именно минимальные элементы стиля я задаю в приложении:

  1. Стандартный цвет фона (он же StandartBackgroundBrush). На примере с выбором стиля он показан заливкой квадрата.
  2. Светлый цвет фона (он же LightBackgroundBrush). Этим цветом закрашена панель, в которой расположены квадраты с наборами.
  3. Темный цвет фона (он же DarkBackgroundBrush). Он задает цвет рамки, что обрамляет квадрат, показывая текущий выбор.
  4. Цвет переднего плана (он же ForegroundBrush). Этим цветом залиты звездочки внутри квадратов, и он же используется как цвет текста.

Комбинации из этих четырех цветов более чем достаточно, чтобы изменить стиль всего приложения. Например, стандартная кнопка имеет цвет для фона в спокойном состоянии, второй для фона при наведении и отдельный для индикации нажатия. Четвертый же цвет определяет каким будет текст внутри кнопки.



Обращаю внимание, что в статьях, посвященных стилизации и дизайну я не рассматриваю новый стиль оформления приложений Fluent Design, так как он появился сравнительно недавно и все еще развивается. К тому же концепция Fluent Design куда шире, чем просто задание особого стиля для базовых элементов и требует глубокого погружения в его философию, что со мной пока еще не случилось. Я однозначно буду рассматривать Fluent Design позже, но только как альтернативную версию стиля для своих приложений.

Перейдем к практике. Для начала определимся с местом хранения цветов приложения. Так как перечисленные цвета должны быть доступны практически из любой точки приложения, сохранять их лучше всего в глобальном файле ресурсов. Таким файлом в моих приложениях является файл ApplicationStyle о котором я писал в конце первой статьи цикла.

Хранится цвета будут в виде ресурсов SolidColorBrush.

Ресурсы в UWP это экземпляры объекта с заранее заданными свойствами и текстовым ключом по которому можно к ним обращаться.

Вот пример ресурсов, которые я использую в приложении:

<SolidColorBrush x:Key="LightBackgroundBrush" Color="#7690C9"/>
<SolidColorBrush x:Key="StandartBackgroundBrush" Color="#56698F"/>
<SolidColorBrush x:Key="DarkBackgroundBrush" Color="#2D2556"/>
<SolidColorBrush x:Key="ForegroundBrush" Color="#FFFFFF"/>

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

Далее можно обращаться к этому ресурсу как из XAML, так и из кода приложения.
В первом случае разметка выглядит так:

Background="{StaticResource StandartBackgroundBrush}"

А во втором так:

.Background = Application.Current.Resources.Item("StandartBackgroundBrush")

Именно второй вариант поможет при установке цветов заголовка окна, с упоминания которого я начал повествование. В «разделе 3» статьи о стилизации заголовка я привел пример кода для окрашивания заголовка в требуемые цвета. Для удобства работы с данным кодом, я объединяю его в процедуру под названием SetTitleBar, которую размещаю в основном классе приложения (при использовании MVVM это ViewModel).

Public Sub SetTitleBar()
        Dim tb As ApplicationViewTitleBar = ApplicationView.GetForCurrentView.TitleBar
        Dim lb As SolidColorBrush = Application.Current.Resources.Item("LightBackgroundBrush")
        Dim sb As SolidColorBrush = Application.Current.Resources.Item("StandartBackgroundBrush")
        Dim db As SolidColorBrush = Application.Current.Resources.Item("DarkBackgroundBrush")
        Dim fb As SolidColorBrush = Application.Current.Resources.Item("ForegroundBrush")

        tb.BackgroundColor = sb.Color
        tb.ButtonForegroundColor = fb.Color
        '...
End Sub

Заметьте, что свойства заголовка принимают объекты типа Color, а наши ресурсы имеют тип SolidColorBrush, поэтому сначала мы создаем локальные объекты для каждого цвета, а затем обращаемся к их свойствам Color.

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

If Metadata.ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar") Then
            StatusBar.GetForCurrentView.BackgroundOpacity = 1
            Dim db As SolidColorBrush = Application.Current.Resources.Item("DarkBackgroundBrush")
            StatusBar.GetForCurrentView.BackgroundColor = db.Color            statusBarRect = StatusBar.GetForCurrentView.OccludedRect
End If

Этот код частично вам знаком, так как мы использовали его для получения высоты строки состояния с целью правильного позиционирования изображения на экране заставке, но теперь он дополнен тремя строками для установки цвета. Первая сообщает, что строка состояния не должна быть прозрачной, а вторая и третья по уже знакомой методике устанавливает для нее цвет.

Итак, с технической частью разобрались, а как быть с творческой? Не многие из вас являются частью команды, где есть дизайнер и, уж тем более не все сами обладают творческими талантами. Я также к таковым не отношусь, зато я знаю, что «Не боги горшки обжигают» и нет ничего постыдного в достижении результата экспериментальным путем.

Именно так и родилась цветовая схема по умолчанию в упомянутом приложении «Шар напоминалка». Сначала я выбрал подходящую фоновую картинку, а затем на ее основе наиболее контрастный цвет для фона (StandartBackgroundBrush). После в графическом редакторе уже на основе этого цвета выбрал более светлый (LightBackgroundBrush) и более темный (DarkBackgroundBrush), а в конце самый светлый для переднего плана (ForegroundBrush). Далее последовал длительный процесс переписывания стилей основных элементов управления и по мере этой работы, выбранные цвета претерпевали изменения для лучшего восприятия.

Однако ближе к концу разработки выбранная цветовая схема начала мне изрядно надоедать и, хоть я и понимал, что эффект исключительно психологический, это сподвигло меня добавить в приложение еще несколько цветовых схем и возможность их выбора. И вот в процессе написания этой статьи меня вдруг осенило, ведь добавлять новые цветовые схемы в уже готовое приложение куда проще, так как можно сразу видеть изменение всего интерфейса. Но как быть читателям, что вероятно только начали разработку своего приложения и испытывают трудности в представлении итогового результата? Да мне и самому в процессе разработки новых приложений хотелось бы заранее понимать какие цвета выбрать и как все это будет выглядеть в итоге.

Недолго думая, я решил написать небольшое приложение «ColorSelector» для быстрого создания цветовых схем приложения. Так как на его создание ушло всего пара дней, оно имеет самый базовый набор функций и, несомненно, в будущем будет расширятся и развиваться с точки зрения функционала. Подключайтесь к этому процессу на GitHub.



Важно отметить отличия подхода в коде ColorSelector от того, что я описываю в данной статье. Подход в статье предполагает наличие одной цветовой схемы в вашем приложении, а ColorSelector создан с учетом возможности выбора схем. Если исходников ColorSelector вам недостаточно для реализации настраиваемых схем в вашем приложении, то пишите в комментариях, и в отдельной статье я расскажу о том, как модифицировать решения, описанные выше.

Дальнейшие действия


Если рассматривать данную статью, как продолжение предыдущей, то на данный момент мы создали расширенный экран-заставку и задействовали в нем два цвета из цветовой схемы приложения: LightBackgroundBrush для фона окна (в статье про экран-заставку просто BackgroundBrush) и ForegroundBrush для текста. По итогам данной статьи, используя уже весь набор цветов, был стилизован заголовок окна и строка состояния.

Следующим шагом будет разработка интерфейса основного окна, а в нем уже появятся самые разные элементы управление, для стилизации которых недостаточно просто присвоить ресурсы для каких-либо свойств. Изменения, что нам нужно будет внести, потребуют переписывания шаблонов элементов управления, а эта тема обширна и касается не только стилизации приложения, поэтому ее я буду рассматривать в отдельной статье (а возможно и не в одной).

Благо такие элементы как панели и контейнеры не требуют глубокого вмешательства в их структуру, поэтому к ним сразу же можно применять цвета из набора, для достижения согласованного внешнего вида. Так же в статье «Съесть три «пончика» из UWP и не подавиться» я рассказывал о том, как легко перекрасить иконки приложения, созданные на основе PNG файлов, которые мы без труда можем стилизовать одним из цветов набора (по логике это ForegroundBrush).

Заключение


В заключении хотел бы разъяснить на кого ориентирован описанный в данной статье подход. Если в вашей команде есть опытный дизайнер или вы сами обладаете достаточным опытом, то не мне вас учить как сделать внешне привлекательное приложение. Однако магазин Windows переполнен приложениями с качественным контентом или функционалом, но с абсолютно невзрачным внешним видом. Это связано с тем, что многие разработчики считают вопрос стилизации слишком сложным или долгим в изучении, в результате чего не готовы тратить на это время. Я же предлагаю достигнуть хорошего результата, при минимальном наборе усилий. После двух статей вы уже имеете качественный внешний вид на старте, а еще после двух-трех, что планируются и вовсе сможете стилизовать все приложение.

Следите за данным циклом и обязательно принимайте участие посредством ваших отзывов и пожеланий в комментариях. До новых встреч!

Комментарии (8)


  1. Splo1ter
    27.04.2018 11:57

    Desctop?
    На одной из картинок.


    1. lxgdark
      27.04.2018 12:11

      Дело было глубокой ночью ))) Поправим


      1. DimaTiunov
        27.04.2018 20:59

        Исходника не было?) Поправлено другим штифтом


        1. lxgdark
          28.04.2018 09:00

          Такую тягу к эстетике, да в стилизации приложений бы!
          А то, не так давно один youtube-канал посвященный Windows 10, рекламировал UWP приложение на которое без слез не взглянешь, но при этом с хорошим функционалом.
          Так что да, я больше уделил внимание теме статьи, чем подкрепляющим картинкам.)


      1. sasha1024
        29.04.2018 20:17

        А на другом скриншоте — «Standart».


        1. sasha1024
          29.04.2018 20:58

          Блин, и даже в исходниках.


  1. Siemargl
    29.04.2018 04:37

    Простите, а Windows10 на мобильных устройствах — это вообще кому-нибудь бывает нужно?


    1. lxgdark
      29.04.2018 11:55

      Вот вам статистика — упомянутое приложение «Шар напоминалка» имеет 80% закачек на мобильных устройствах и только 20% на ПК.
      Само собой в количественном исчислении рынок Windows 10 проигрывает конкурентам, но если и делать приложение на UWP то обязательно! адаптивное и адекватно работающее в том числе и на мобильных устройствах.