Опубликован: 10.04.2013 | Доступ: свободный | Студентов: 439 / 9 | Длительность: 16:52:00
Специальности: Программист
Лекция 1:

Командный пользовательский интерфейс

Лекция 1: 123456 || Лекция 2 >

Отображение, скрытие, включение и обновление команд

В предыдущем разделе я упоминал об использовании события beforeshow для настройки свойства commands панели приложения таким образом, чтобы панель содержала команды, соответствующие текущей странице и состоянию страницы. Это может включать установку свойства disabled для некоторых команд, которые, например, зависят от состояния выделения. Это можно реализовать с помощью массива commands, в разметке, или, опять же, используя метод панели приложения getCommandById:

appbar.getCommandById("cmdAdd").disabled = true;

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

Говоря об изменениях, вполне допустимо изменять или обновлять команды во время выполнения программы, что может устранить необходимость создания множества команд, которые вы можете поочередно показывать или скрывать. Так как каждая команда в панели приложения – это лишь DOM-элемент, вы можете, на самом деле, выполнять любые изменения, какие хотите, в любое время. Пример этого показан в Сценарии 3 примера, где панель приложения изначально создается с кнопкой Play (html/custom-icons.html):

<button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{id:'cmdPlay', label:'Play', icon:'play', tooltip:'Play this song'}">
</button>
 

Обработчик события click этой кнопки использует функцию doCluckPlay в js/custom-icons.js для переключения между состояниями:

var isPaused = true;

function doClickPlay() {
var cmd = document.getElementById('cmdPlay');

if (!isPaused) {
isPaused = true; // поставлено на паузу cmd.winControl.icon = 'play'; 
cmd.winControl.label = 'Play'; cmd.winControl.tooltip = 'Play this song';
} else {
isPaused = false; // проигрывается cmd.winControl.icon = 'pause'; 
cmd.winControl.label = 'Pause';
cmd.winControl.tooltip = 'Pause this song';
}
}
 

Вы можете использовать что-то подобное для закрепления или открепления дополнительных плиток (secondary tiles), как мы увидим в лекции 2 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой". И, снова, кнопки – это лишь элементы в DOM и обновление любых их свойств, включая стили, обновит элемент на экране, как только вы вернете управление в поток пользовательского интерфейса.

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

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

Один из подходов заключается в том, чтобы каждая страница приложения объявляла и поддерживала собственную панель приложения, что подразумевает создание панелей приложения "на лету" в методе страниц ready. Это делает взаимодействие между содержимым страницы и панелью приложения весьма четким и ограниченным рамками страницы. Недостаток такого подхода заключается в том, что общие команды – те, которые появляются более чем на одной странице – приходится объявлять множество раз, что ухудшает возможности по управлению ими и способствует привлечению небольшой неоднородности, которая приходит как муравьи на сахар. Тем не менее, если содержимое разных страниц сильно отличается и у вас есть лишь несколько общих команд, такой подход может быть правильным выбором. Это, так же, необходимо, если ваша страница использует несколько страниц верхнего уровня, вместо одной страницы с элементом управления страницы, как мы обсуждали в лекции 3курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript", так как каждая HTML-страница верхнего уровня, в любом случае, должна объявить свою собственную панель приложения.

Для приложений, использующих элементы управления страниц, применяется другой подход, который заключается в объявлении одной панели приложения на странице верхнего уровня и в установке ее свойства command внутри метода ready каждого из подобных элементов управления. Недостатком здесь является то, что так как command – это свойство только для записи, вы не можете объявить общие команды в HTML и позже добавить команды, характерные для отдельной страницы, только если вы не идете сложным путем создания каждого отдельного дочернего элемента AppBar в каждом методе ready . Подобный код утомительно писать и поддерживать.

К счастью, есть и третий подход, который позволяет вам объявить одну панель приложения на странице верхнего уровня, которая содержит все необходимые команды, для всех страниц, и затем выборочно показывать определенные наборы таких команд в каждом из методов ready отдельных страниц. Это – цель существования методов панели приложения showCommands, hideCommands и showOnlyCommands .

Все эти методы прпнимают массив командных элементов, которые могут быть либо объектами AppBarCommand , либо id команд. Метод showCommands делает эти командные элементы управления видимыми и может быть вызван несколько раз с различными установками для получения итогового набора. С другой стороны, метод hideCommands скрывает заданные команды в панели приложения, опять же, с возможностью многократного вызова. Основы использования этих методов показаны в Сценарии 4 нашего примера.

Метод showOnlyCommands объединяет два вышеописанных метода, делая заданные команды видимыми и скрывая остальные. Если вы задаете панель приложения со всеми командами, вы можете использовать метод showOnlyCommands в методе ready каждой страницы для того, чтобы быстро и просто настроить вид панели приложения. Хитрость заключается в получении массива, подходящего для передачи в метод. Вы можете, конечно, вручную написать код для команд, занести данные в специальный массив, как в Сценарии 4 примера сделано для showCommands и hideCommands . Однако, если вы думаете, что это хороший пример Плохой идеи, то знайте, что я тоже так думаю! Использование подобного массива подразумевает, что любые изменения, которые вы вносите в панель приложения, должны произойти и в HTML-файле, и в JS-файле, а это означает, что любой, кто будет поддерживать ваш код в будущем, без сомнения, станет осыпать вас проклятиями!

Лучший путь к счастью и долгой жизни, таким образом – программно получать необходимые массивы из DOM, используя свойство extraClass для каждой команды для того, чтобы эффективно задавать наборы команд. Это позволяет вам вызывать querySelectorAll для получения тех команд, которые принадлежат опреденному набору.

Рассмотрим нижеприведенное определение панели приложения, где, для краткости, я опустил свойства вроде label, icon и section , так же, как и любые другие классы стилей:

<div id="appbar" data-win-control="WinJS.UI.AppBar" data-win-options="{
commands:[
{id:'home', extraClass: 'menuView gameView scoreView'},
{id:'play', extraClass: 'menuView gameView scoreView'},
{id:'rules', extraClass: 'menuView gameView scoreView'},
{id:'scores', extraClass: 'menuView gameView scoreView'},
{id:'newgame', extraClass: 'gameView gameSnapView'},
{id:'resetgame', extraClass: 'gameView gameSnapView'},
{id:'loadgame', extraClass: 'gameView gameSnapView'},
{id:'savegame', extraClass: 'gameView gameSnapView'},
{id:'hint', extraClass: 'gameView gameSnapView'},
{id:'timer', extraClass: 'gameView gameSnapView'},
{id:'pause', extraClass: 'gameView gameSnapView'},
{id:'home2', extraClass: 'gameSnapView'},
{id:'replaygame', extraClass: 'scoreView'},
{id:'resetscores', extraClass: 'scoreView'}
]}" >
</div >
 

В свойствах extraClass мы задаем четыре различных набора: menuView, gameView, gameSnapView, и scoreView. Когда все находится там, где нужно, простой вызов querySelectorAll предоставляет тот массив, который нам нужен для showOnlyCommands. Общая функция, наподобие следующей, может быть, затем, использована из метода ready каждой страницы (или из любого другого места) для активации командных элементов для нужного экрана программы:

function updateAppBar(view) {
var appbar = document.getElementById("appbar").winControl;
var commands = appbar.element.querySelectorAll(view);
appbar.showOnlyCommands(commands);
}	
 

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

Стилизация панели приложения

Свойство команд extraClass может, конечно, быть использовано для целей стилизации, так же, как и для управления наборами команд. Это очень просто: любые классы, которые заданы в extraClass, добавляются к элементам AppBarCommand, созданных для панели приложения.

Существуют семь классов WinJS для стилизации, которые используются панелью приложения, как описано в нижеприведенной таблице, где первые два применяются к панели приложения в целом, а другие пять – к отдельным командным элементам:

CSS-класс (панель приложения) Описание
win-appbar Задает стиль контейнера панели приложения. Обычно этот стиль используется в качестве корневого для более специфических селекторов.
win-commandlayout Задает стиль макета команд панели приложения. Обычно приложения не модифицируют этот стиль
CSS-класс (команды) Описание
win-command Задает стиль всех элементов AppBarCommand.
win-commandicon Задает стиль контейнера элемента для AppBarCommand.
win-commandimage Задает стиль изображения для AppBarCommand.
win-commandring Задает стиль круглой рамки, которая выводится вокруг изображения на AppBarCommand.
win-label Стилизует подпись AppBarCommand.

Подсказка. Для того чтобы помочь себе в настройке стилей панели приложения в Blend сделайте ее залипающей (sticky ), или добавьте вызов метода show в методе ready страницы, или в обработчике события activated . Это позволит сделать панель приложения видимой в Blend, работать с ней, в противном случае возникают сложностью с открытием панели в процессе разработки.

Обычно нет необходимости в прямом переопределении стилей win-appbar или win-commandlayout. Вместо этого следует создавать селекторы для пользовательских классов, связанных с этими стилями и затем стилизовать то, что вам нужно. Здесь можно использовать и псевдоселекторы, наподобие button:hover, button:active и так далее.

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

В качестве основы, Сценарии 2 (html/custom-color.html) добавляет CSS-класс customColor к панели приложения:

<div id="customColorAppBar" data-win-control="WinJS.UI.AppBar" class="customColor" ...> 

В css/custim-color.css он затем стилизует селекторы на основе .win-appbar.customColor. Следующие правила, например, задают фоновый цвет, цвет текста подписи и цвет круглой рамки вокруг команды для состояний :hover и :active:

 .win-appbar.customColor {
background-color: rgb(20, 20, 90);
}
.win-appbar.customColor .win-label {
color: rgb(90, 200, 90);
}
.win-appbar.customColor button:hover .win-commandring,
.win-appbar.customColor button:active .win-commandring {
background-color: rgba(90, 200, 90, 0.13);
border-color: rgb(90, 200, 90);
}

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

Пользовательские значки

Ранее мы видели, что свойство icon элемента типа AppBarCommand обычно является одним из символов шрифта Segoe UI Symbol. Хотя для большинства нужд это подходит, время от времени может возникнуть необходимость в использовании символов из разных шрифтов (некоторые из нас просто не могут не пользоваться Wingdings!) или в отображении пользовательских изображений. Панель приложения поддерживает и то и другое.

Для использования различных шрифтов для всей панели приложения, просто добавьте класс к панели приложения и создайте правило, основанное на win-appbar :

win-appbar.customFont {
font-family: "Wingdings";
}
 

Для изменения шрифта определенной командной кнопки, добавьте класс к ее свойству extraClass (такому, как customButtonFont ) и создать правило со следующим селектором (как в Сценарии 1 модифицированного примера):

button.customButtonFont .win-commandimage {
font-family: "Wingdings";	
}
 

Для использования собственных изображений, выполните следующие шаги для масштаба разрешения 100%:

  • Создайте спрайт в формате png с размером 160х80 пикселей с прозрачным фоном, сохранив файл с именем, имеющим суффикс .scale-100.
  • Этот спрайт разделен на две строки по два столбца, то есть, на ячейки размером 40х40 пикселей. Верхняя строка предназначена для светлой темы интерфейса, нижняя – для темной.
  • Каждая строка содержит четыре иконки для следующих состояний кнопок, по поярдку слева направо: кнопка по умолчанию (не нажатая), кнопка, над которой находится указатель мыши, нажатая кнопка (активная) и неактивная кнопка
  • Каждое изображение отцентровано в соответствующей ему ячейке, но помните, что вокруг значка будет нарисована круглая рамка, поэтому помещайте изображение в диапазоне 20-30 пикселей вертикально и горизонтально. Оно, конечно, может быть шире или выше в центре – там, где больше места в круглой рамке.

Для других масштабов разрешений, умножьте размеры на 1.4 (140%) и 1.8 (180%) и используйте в именах файлов суффиксы .scale-140 и .scale-180.

Для использования пользовательского значка, установите свойство icon командного элемента в значение базового URI изображения (без суффиксов .scale-1x0). Например, icon: 'url(images/icon.png)' .

Сценарий 3 примера, посвященного элементу управления HTML AppBar показывает использование пользовательских значков для кнопки Accept:


Значок хранится в файле, который называется accept.png, который выглядит примерно так, как показано ниже. Я настроил яркость и контраст, добавил рамку, чтобы вы могли четко увидеть каждую ячейку:


Объявление кнопок панели приложения, таким образом, выглядит так, как показано ниже (некоторые свойства опущены для краткости):

<button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{id:'cmdAccept', label:'Accept', icon:'url(images/accept.png)' }">
 

Обратите внимание на то, что хотя в примере нет различных значков для разных масштабов разрешения, он содержит варианты для тем с высокой контрастностью, это важное условие обеспечения соглашений по специальным возможностям, о которых мы поговорим в лекции 6 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой". По этой причине элемент button включает style="-ms-high-contrast-adjust:none" для того, чтобы переопределить автоматическую настройку для тем с высокой контрастностью.

Командные меню

Следующий аспект панели приложения, который нуждается в пояснениях, касается тех команд, свойство type который установлено в значение flyout. В данном случае свойство flyout командного элемента должно идентифицировать объект WinJS.UI.Flyout или на элемент управления WinJS.UI.Menu (он является всплывающим элементом). Как мы упоминали ранее, всплывающие элементы или всплывающие меню наподобие этих используются тогда, когда в панели приложения нужно расположить слишком много связанных команд, или когда вам нужны другие типы элементов управления, которые не вполне подходят для их непосредственного расположения в панели приложения. Если вы пытаетесь воспользоваться кнопками с подписями "Еще", "Дополнительно", "Другие возможности", так как вы не можете решить, как организовать команды, это верный признак того, что приложение получается слишком сложным. Изыщите способы упрощения целей приложения, в итоге панель приложения не превратится в хранилище случайных элементов управления.

Мы подробнее поговорим о всплывающих элементах ниже в этой лекции, а сейчас посмотрим, как использовать их в панели приложения, как показано в Сценарии 6 примера "Всплывающие элементы управления HTML" (http://code.msdn.microsoft.com/windowsapps/Flyout-sample-258757b3) (обратите внимание, это не пример про панель приложения!):


В файле html/appbar-flyout.html этого примера мы видим, что кнопка панели приложения задана следующим образом:

<button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{id:'respondButton', label:'Respond', icon:'edit', type:'flyout', flyout:'respondFlyout'}"
>
 

Элемент respondFlyout, который здесь идентифицируется, определен ранее, в html/appbar-flyout.html. Обратите внимание на то, что подобный элемент должен быть объявлен раньше, чем панель приложения для того, чтобы его экземпляр был создан до создания панели приложения:

<div id="respondFlyout" data-win-control="WinJS.UI.Menu"
<button data-win-control="WinJS.UI.MenuCommand" 
data-win-options="{id:'alwaysSaveMenuItem',
label:'Always save drafts', type:'toggle', selected:'true'}">
</button>
<hr data-win-control="WinJS.UI.MenuCommand"
data-win-options="{id:'separator', type:'separator'}" />
<button data-win-control="WinJS.UI.MenuCommand"
data-win-options="{id:'replyMenuItem', label:'Reply'}">
</button>
<button data-win-control="WinJS.UI.MenuCommand"
data-win-options="{id:'replyAllMenuItem', label:'Reply All'}">
</button>	
<button data-win-control="WinJS.UI.MenuCommand"	
data-win-options="{id:'forwardMenuItem', label:'Forward'}">
</button>	
</div>
 

Вас не должно уже удивить то, что меню – это лишь еще один элемент управления WinJS, WinJS.UI.Menu, дочерние элементы которого определяютс содержимое меню. Все эти элементы, опять же, лишь элементы в DOM. Их события click подключаются к обработчикам в js/appbar-flyout.js с уже известным вам addEventListener. (В примере использована команда document.getElementById для получения элементов при вызове addEventListener. Эффективнее будет использовать метод панели приложения getCommandById, как в модифицированном примере работы с панелью приложения).

Каждый элемент меню, как вы можете видеть, это объект WinJS.UI.MenuCommand, мы так же рассмотрим подробности позднее, а сейчас вы можете видеть, что эти элементы имеют свойства id, label, type – это очень похоже на объекты WinJS.UI.AppBarCommand.

Вот и почти все, что нужно сделать, добавлю лишь, что когда элемент меню выбирают, нужно скрыть меню и, возможно, так же панель приложения (если она не находится в режиме залипания). Это показано в примере, в файле hs/appbar-flyout.js, в функции, которая называется hideFlyoutAndAppBar:

function hideFlyoutAndAppBar() {	
document.getElementById("respondFlyout").winControl.hide();
document.getElementById("appBar").winControl.hide();
 

Пользовательские панели приложений и панели навигации

Все это время мы изучали стандартный макет команд панели приложения, что, конечно, является самым простым способом использования этого элемента управления. Однако, стандартных возможностей хватает не всегда. Возможно, вы захотите расположить на панели приложения больше интересных элементов управления, в особенности это касается пользовательских элементов управления (таких, как средство для выбора цвета). Для подобных целей вы можете установить свойство панели приложения layout в значение ‘custom’ и задать любой HTML-макет для панели приложения, стилизовать его с помощью CSS и подключить обработчики любых необходимых событий в JavaScript.

Пользовательские макеты обычно используют для создании верхней панели навигации – то есть, панели приложения со свойством placement установленным в значение ‘top’ – так как командные кнопки – это обычно не тот пользовательский интерфейс, который вам нужен. Мы видели пример подобной панели приложения ранее, в приложении Weather, и навигационная панель в Internet Explorer устроена по тому же принципу:


Наш старый друг – пример элемента управления HTML AppBar (http://code.msdn.microsoft.com/windowsapps/App-bar-sample-a57eeae9) предоставляет пример пользовательского макета в Сценарии 5. В html/custom-layout.html мы видим разметку для пользовательской верхней панели приложения, содержащей произвольные элементы:

 <div id="customLayoutAppBar" data-win-control="WinJS.UI.AppBar" aria-label="Navigation Bar" 
data-win-options="{layout:'custom', placement:'top'}">
<header aria-label="Navigation bar" role="banner">
<button id="cmdBack" class="win-backbutton" aria-label="Back"
</button>
<div class="titleArea">
<h1 class="win-type-xx-large" tabindex="0"> 
Page Title </h1>
</div>
</header>
</div>

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


Как я упоминал в подразделе "Некоторые советы и секреты" (в разделе "Стилизация элементов управления), в лекции 4 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript", вы можете подавить вывод прямоугольника фокуса с помощью правила <selector>:focus { outline: none; } в CSS. Для того, чтобы убрать его с кнопки "Назад", например, вы можете добавить следующее правило стиля в css/custom-layout.css

.win-appbar header .win-backbutton {
margin-left: 39px;	
margin-top: 59px;	
outline: none;	
	}
 

Снова обратите внимание на то, как это правило и другие правила в css/custom-layout.ss используют класс win-appbar как базовый селектор, но только потому, что он используется для стилизации других обычных классов, таких, как header или win-backbutton. Если вы используете особые классы в панели приложения или в навигационной панели, вы можете совсем не пользоваться селектором win-appbar.

Для того, чтобы реализовать навигационную панель, напоминающую таковую в Internet Explorer или в приложении Weather, вы можете использовать элемент управления ListView вместе с шаблонами элементов или пользовательскими функциями вывода элементов, где вы подключаете события itemInvoked к WinJS.Navigation.navigate и так далее. Опять же, здесь нет ничего особенно сложного: панель приложения с пользовательским макетом – это лишь всплывающий контейнер для других HTML-элементов.

Лекция 1: 123456 || Лекция 2 >
Вадик Елетин
Вадик Елетин
Россия, г. Санкт-Петербург
Николай Жигульский
Николай Жигульский
Россия, Тверь, Тверской государственный технический университет