Макет
Быстрый старт: Сдвигаемые разделы и точки прикрепления
В "Коллекции и элементы управления для вывода коллекций" мы потратили некоторое время на разговор о том, когда ListView - это правильный выбор, а когда - нет. Один из главных случаев, когда разработчики неоправданно пытаются использовать ListView, заключается в реализации домашней страницы или хаба приложения, который содержит множество различных групп содержимого, организованных в столбцы, как показано на Рис. 6.4 и разъяснено в материале "Проектирование навигации для приложений Магазина Windows" (http://msdn.microsoft.com/library/windows/apps/hh761500.aspx). На первый взгляд это выгдялит как ListView, но так как данные, на самом деле, не являются коллекцией, это лишь макет, выводящий фиксированное содержимое, в итоге, имеет смысл использовать для подобной работы HTML и CSS, через метод проб и ошибок.
Я особо обратил на это ваше внимание, так как все отличные элементы управления, которые предоставляет WinJS, позволяют просто забыть о том, что всё, что вы знаете об HTML и CSS, всё еще применимо в приложениях для Магазина Windows. В конце концов, эти элементы управления - лишь блоки HTML и CSS с некоторыми дополнительными методами, свойствами и событиями.
увеличить изображение
Рис. 6.4. Макет типичной домашней страницы (хаба) приложения для Магазина Windows с фиксированным заголовком (1) и горазонтально сдвигаемым разделом (2), и разделами или категориями содержимого (3)
Создание макета хаба
Посмотрим, как использовать HTML и CSS для того, чтобы реализовать раздел стартовой страницы приложения (хаба), который поддерживает сдвиг, как на Рис. 6.4. Вспомнив, для начала, к материалу "Создание макета приложения" (http://msdn.microsoft.com/library/windows/apps/hh872191.aspx), мы можем сказать, что отступ между группами должен составлять четыре единицы по 20 пикселей каждая, то есть - 80 пикселей. Большинству групп следует иметь квадратную форму, за исключением второй, ширина которой вдвое меньше. Основываясь на размерах дисплея, 1366х768, высота каждого раздела должна составлять 768 пикселей минус 128 пикселей (это место для заголовка), минус, как минимум, 50 пикселей снизу. В итоге остаётся 590 пикселей (если мы добаим заголовки групп для каждого раздела, нужно будет вычесть еще 40 пикселей). В итоге, квадратная группа на базовом дисплее будет иметь 590 пикселей в ширину (мы установили реальную высоту в 100% содержащей её ячейки сетки). Полная ширина раздела будет, таким образом, (590*4 полноразмерных раздела)+(295*один раздел половинной ширины)+(80*4 разделительные пустые пространства). Результат равняется 2975 пикселей. К этому мы добавим колонки по краям - 120 пикселей слева (в соовтетствии с общим стилем Windows) и 80 пикселей справа. В итоге, мы получаем 3175 пикселей.
Для того, чтобы создать раздел с подобным макетом, мы можем использовать CSS-сетку внутри элемента-контейнера. Для того, чтобы это увидеть, запустим Blend, создадим новый проект с шаблоном Приложение навигации (у нас будет базовая страница, но не все вспомогательные страницы, всё будет оформлено в нужном стиле). Внутри элемента section в pages/home/home.html, создадим новый div-элемент и зададим его параметр класс как hubSections:
<section aria-label="Main content" role="main"> <div class="hubSections"> </div> </section>
По адресу pages/home/home.css добавим несоколько правил стилей. Зададим параметр overflow-x: auto элементу section, и расположим сетку в div'е hubSections, используем добавление колонок слева и справа для создания отступов (удалив margin-left: 120px из section и добавив это в качестве первого столбца в div):
.homepage section[role=main] { overflow-x: auto; } .homepage .hubSections { width: 2975px; height: 100%; display: -ms-grid; -ms-grid-rows: 1fr 50px; -ms-grid-columns: 120px 2fr 80px 1fr 80px 2fr 80px 2fr 80px 2fr 80px; }
Применив эти стили, мы уже можем увидеть, как начальная страница принимает форму, уменьшив масштаб отображения данных на монтажной панели:
Теперь создадим отдельные разделы в pages/home/home.html, каждый из них представляет собой div.
<section aria-label="Main content" role="main"> <div class="hubSections"> <div class="hubSection1"></div> <div class="hubSection2"></div> <div class="hubSection3"></div> <div class="hubSection4"></div> <div class="hubSection5"></div> </div> </section>
И стилизуем их в соответствии с занимаемыми ими ячейками сетки, в 100% по ширине (width) и высоте (height). Я показал здесь hubSection1, другие выглядят точно так же, имея лишь другие номера столбцов (4, 6, 8 и, соответственно, 10).
.homepage .hubSection1 { -ms-grid-row: 1; -ms-grid-column: 2; /* 4 для hubSection2, 6 для hubSection3, и так далее. */ width: 100%; height: 100%; }
Создание макетов разделов
Сейчас мы можем взглянуть на содержимое каждого раздела. В зависимости от того, что вы хотите отобразить, и как отображенные разделы должны взаимодействовать, вы можете снова просто использовать макет (CSS-сетку, или, возможно, гибкое окно), или использовать элементы управления наподобие ListView. Разделы hubSection3 и hubSection5 имеют пустые пространства в низу, поэтому они могут быть элементами управления ListView с изменяющимся количеством элементов. Обтатите внимание на то, что если мы создаём список с более чем 9 или 6 элементами, соответственно, мы захотим, настроить размеры столбцов во всей сетке, захотим сделать ширину элемента section больше, но давайте предположим, что дизайн требуется для максимум 6 и 9 элементов в разделах.
Скажем так же, что мы хотим, чтобы каждый из разделов был интерактивен, когда прикосновение к элементу запускает навигацию к странице детальной информации. (В этом примере не показаны заголовки групп, используемые для навигации к странице группы). Мы просто используем ListView в каждом из разделов, где каждый из ListView будет иметь собственный источник данных. Для hubSection1 нам понадобится использовать объединение ячеек, в остальных же группах вполне подойдут декларативные шаблоны. Ключевое соглашение, касающееся всех этих групп, заключается в том, чтобы стилизовать элементы таким образом, чтобы они хорошо вписались в базовые размеры, которые мы используем. И, возвращаясь к общему стилю приложения, расстояние между изображениями элементов должно быть 10 пикселей, расстояние между столбцами со смешанным содержимым (hubSection4 и hubSection5) должно быть 40 пикселей (что может быть установленно с помощью подходящих CSS-полей).
Точки прикрепления
Если вы запустите упражнение HubPage и поработаете немного с ним, используя жесты инерционной прокрутки (то есть, такие, когда сдвиг элемента продолжается даже после того, как вы убрали палец; подробнее об этом - в "Анатомия приложения и навигация по страницам" курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript"), вы заметите, что сдвиг может остановиться в любом месте. Вам и вашему дизайнеру это может понравится, но во многих сценариях имеет смысл автоматическая остановка сдвига на границе раздела или группы. Для сенсорного взаимодействия это можно реализовать с использованием CSS-стилей для точек прикрепления (snap points), как описано в нижеприведенной таблице. Это - стили, которые вы добавляете к элементу, поддерживающему сдвиг, вместе со стилями, отвечающими за переполнение, иначе они не окажут нужного воздействия. Документацию по этому вопросу (и по некоторым другим) можно найти в материале "Сенсорное взаимодействие: изменение масштаба и сдвиг" (http://msdn.microsoft.com/ru-ru/library/windows/apps/hh453816.aspx).
Стиль | Описание | Синтаксис значений |
---|---|---|
-ms-scroll-snap-points-x | Задаёт точку прикрепления для оси Х | snapInterval(start<length>, step<length>) | snapList(list<lengths>) |
-ms-scroll-snap-points-y | Задаёт точку прикрепления по оси Y | snapInterval(start<length>, step<length>) | snapList(list<lengths>) |
-ms-scroll-snap-type | Задаёт, точка прикрепления какого типа должна быть использована для элемента: none отключает точку прикрепления, mandatory всегда осуществлять сдвиг до остановки на точке прикрепления (что включает в себя окончание инерционного сдвига), и proximity воздействовать на процесс сдвига лишь в том случае, если движение, на самом деле, заканчивается "очень близко" к точке прикрепления. Использование mandatory, таким образом, приводит к сдвигу с шагом в один раздел/элемент, в то время, как proximity позволит "проскочить" очередную точку прикрепления при инерционном сдвиге. Так же обратите внимание на то, что перетаскивание пальцем (то есть, использование жеста, где нет инерционного движения) позволяет пользователю передвинуть элемент в позиции, отличающиеся от точек прикрепления. | none | proximity | mandatory |
-ms-scroll-snap-x | Сокращение для комбинации -ms-scroll-snap-type и -ms-scroll-snap-points-x | <-ms-scroll-snap-type> <-ms-scroll-snap-points-x> |
-ms-scroll-snap-y | Сокращение для комбинации -ms-scroll-snap-type и -ms-scroll-snap-points-y | <-ms-scroll-snap-type> <-ms-scroll-snap-points-y> |
В таблице, <length> - это число с плавающей запятой, за которым следует указатель абсолютной единицы (cm, mm, in, pt или pc), или относительной единицы измерения (em, ex или px).
Для того, чтобы добавить точку прикрепления к каждому из разделов нашей стартовой страницы, нам лишь нужно добавить два стиля точек прикрепления после overflow-x:
.homepage section[role=main] { overflow-x: auto; -ms-scroll-snap-type: mandatory; -ms-scroll-snap-points-x: snapList(0px, 670px, 1045px, 1715px, 1795px); }
Обратите внимание на то, что показанные здесь точки прикрепления включают 120-пиксельную левую границу, таким образом, каждая выравнивается с разделом, расположенным под текстом заголовка. Таким образом, точка прикрепления 0px соответствует первому разделу, 670px - второму (80-пиксельный разделитель и 590-пиксельная ширина первого раздела) и так далее. Последняя точка прикрепления в 1895px, однако, не следует этому правилу, так как div не может быть сдвинут за эту точку. Это означает, что мы прикрепляем точку где-то в предпоследней секции, но отображаем последнюю секцию и её 80-пиксельную границу.
После этих изменений, мы обнаружите, что при прокрутке осуществляются остановки (приятно анимированные) точно на границах разделов. Отметьте, что для стартовой страницы, наподобие этой, использование точек прикрепления типа proximity обычно подходит больше. Обязательные точки прикрепления (mandatory) предназначены больше для элементов, с которыми невозможно взаимодействовать или работать без того, чтобы видеть их целиком, как, например, при пролистывании наборов фотографий, статей и так далее. (Элемент управления FlipView это использует).
Для того, чтобы узнать об этом больше, в том числе - о некоторых других стилях -ms-scroll-* и -ms-content-zoom-*, об ограничителях прокрутки, обратитесь к примеру: "HTML-прокрутка, сдвиг, изменение масштаба" (http://code.msdn.microsoft.com/windowsapps/Scrolling-panning-and-47d70d4c). Обратите, так же внимание на то, что точки прикрепления предназначены не только для использования с элементом управления ListView, они предназначены и для использования в ваших собственных макетах.