Как отображать элементы различных размеров (HTML)
[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. В случае разработки приложений для Windows 10 см. раздел последняя документация]
По умолчанию элемент управления ListView выделяет одинаковый размер для каждого элемента в списке. Если используется макет сетки, можно изменить эту реакцию на событие и отображать элементы разного размера, помещая их в несколько ячеек.
Что необходимо знать
Технологии
Необходимые условия
- Предполагается, что вы умеете создавать и использовать базовый объект ListView. Начальные сведения об элементе управления ListView см. в разделе Краткое руководство. Добавление элемента управления ListView.
Инструкции
Ячейки и изменение размера в ListView
Перед подробным рассмотрением кода рекомендуется изучить, как ListView изменяет размер.
По умолчанию ListView выделяет ячейки одного размера для каждого элемента, который в нем содержится. Ниже приводится ListView, который содержит элементы одного размера.
Здесь представлен тот же ListView с одной выделенной ячейкой.
Размер ячейки определяется размером первого элемента в ListView. Если ListView содержит элементы разного размера, размер ячейки все равно выделяется в зависимости от первого элемента. Таким образом, если один элемент крупнее других, он будет обрезан по размеру других элементов в ListView.
Эту реакцию на событие можно изменить, включив объединение ячеек. Тогда элемент может занимать несколько ячеек. В этом примере включено объединение ячеек, так что более крупные элементы занимают не одну, а до 5 ячеек.
Когда включается объединение ячеек, можно также явным образом указать размер основной ячейки. Для каждого элемента в ListView рекомендуется устанавливать размер, кратный размеру основной ячейки. В следующем примере более крупный элемент изменяется таким образом, что его высота становится в два раза больше высоты основной ячейки, а ширина остается та же.
Ниже описано создание ListView, содержащего элементы трех разных размеров.
Шаг 1. Создание данных в ListView
Сначала создаются источник данных и ListView.
Определите источник данных для ListView в файле JavaScript. В этом примере из массива объектов JSON создается List, и функция WinJS.Namespace.define делает его общедоступным, чтобы предоставлять объект в пространстве имен
DataExamples
.Данные аналогичны примерам, показанным в других темах, таких как Краткое руководство. Добавление элемента управления ListView, с одним добавлением — полем
type
. Это поле может иметь три значения: "smallListIconTextItem", "mediumListIconTextItem" и "largeListIconTextItem". На дальнейших шагах это поле используется для назначения класса CSS, определяющего размер каждого элемента.(function () { "use strict"; var myCellSpanningData = new WinJS.Binding.List([ { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png", type: "smallListIconTextItem" }, { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png", type: "mediumListIconTextItem" }, { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png", type: "largeListIconTextItem" }, { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png", type: "mediumListIconTextItem" }, { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png", type: "smallListIconTextItem" }, { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png", type: "smallListIconTextItem" }, { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png", type: "mediumListIconTextItem" }, { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png", type: "mediumListIconTextItem" }, { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png", type: "smallListIconTextItem" }, { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png", type: "smallListIconTextItem" }, { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png", type: "smallListIconTextItem" }, { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png", type: "smallListIconTextItem" }, { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png", type: "smallListIconTextItem" }, { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png", type: "smallListIconTextItem" }, { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png", type: "mediumListIconTextItem" }, { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png", type: "smallListIconTextItem" }, { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png", type: "largeListIconTextItem" }, { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png", type: "mediumListIconTextItem" } ]); WinJS.Namespace.define("DataExamples", { myCellSpanningData: myCellSpanningData }); })();
(Если во время программирования необходимо использовать рисунки из этого примера, их можно получить, скачав выборку шаблонов элемента ListView.)
В HTML-файле создайте элемент управления ListView, использующий макет объединения ячеек. Для свойства itemDataSource задайте источник данных, созданный на предыдущем шаге.
<div id="myListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: DataExamples.myCellSpanningData.dataSource, layout: { type: WinJS.UI.CellSpanningLayout } }" ></div>
Шаг 2. Определение размера основной ячейки и включение объединения ячеек
Теперь необходимо определить размер основной ячейки.
Чтобы в ListView использовался макет объединения ячеек, создайте объект CellSpanningLayout и с его помощью установите свойство layout элемента управления ListView. Чтобы включить объединение ячеек и определить размер основной ячейки, создайте функцию groupInfo и с ее помощью задайте свойство groupInfo объекта CellSpanningLayout. Функция groupInfo, которая определяется, должна возвращать объект, содержащий эти свойства:
enableCellSpanning
Чтобы включить объединение ячеек, установите значение true. Значение по умолчанию — false.cellWidth
Ширина основной ячейки.cellHeight
Высота основной ячейки.
В этом примере используется основная ячейка размером 310×80 пикселей.
Определение размера основной ячейки и включение объединения ячеек
В файле JavaScript, в котором вы создали данные, создайте функцию groupInfo, которая включает объединение ячеек и определяет размер основной ячейки как 310×80 пикселей.
// Enable cell spanning and specify // the cellWidth and cellHeight for the items var groupInfo = function groupInfo() { return { enableCellSpanning: true, cellWidth: 310, cellHeight: 80 }; };
Сделайте функцию общедоступной в HTML с помощью функции WinJS.Utilities.markSupportedForProcessing.
// Enable cell spanning and specify // the cellWidth and cellHeight for the items var groupInfo = function groupInfo() { return { enableCellSpanning: true, cellWidth: 310, cellHeight: 80 }; }; WinJS.Utilities.markSupportedForProcessing(groupInfo);
(По умолчанию функции и обработчики событий недоступны для элементов управления библиотеки Windows для JavaScript по причинам безопасности. Функция WinJS.Utilities.markSupportedForProcessing позволяет переопределить эту реакцию на событие. Предполагается, что предоставленный вами HTML-код правильно сформирован и может обрабатываться WinJS. Подробнее см. в разделе Программирование основных приложений.)
Вызов WinJS.Utilities.markSupportedForProcessing для вашей функции не делает ее общедоступной. Это делается на следующем шаге.
Сделайте функцию groupInfo общедоступной, предоставив ее с помощью пространства имен. В этом примере обновляется пространство имен
DataExamples
, созданное на шаге 1.1.WinJS.Namespace.define("DataExamples", { groupInfo : groupInfo, myCellSpanningData: myCellSpanningData });
Обновите ListView, чтобы использовать функцию groupInfo.
<div id="myListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: DataExamples.myCellSpanningData.dataSource, layout: { groupInfo: DataExamples.groupInfo, type: WinJS.UI.GridLayout } }" ></div>
Шаг 3. Определение размера элемента, занимающего одну ячейку
После определения размера основной ячейки можно определить размеры элементов. При определении данных на первом шаге было включено поле type
, содержащее сведения о размере элемента: маленький, средний или крупный. Эти сведения можно использовать для назначения размеров элементов. Лучший способ назначить размеры — использовать классы CSS. Этот подход работает независимо от использования функции шаблонов или WinJS.Binding.Template.
Основная ячейка имеет размер 310 пикселей в ширину и 80 пикселей в высоту. Общий размер каждого элемента должен быть кратным размеру основной ячейки. Размер основной ячейки составляют размер элемента, а также отбивка, поля и граница:
Ниже приводится формула для расчета размера основной ячейки:
- ширина основной ячейки = ширина элемента + горизонтальная отбивка элемента + горизонтальное поле элемента + толщина границы элемента
- высота основной ячейки = высота элемента + вертикальная отбивка элемента + вертикальное поле элемента + толщина границы элемента
Определение размера элемента, занимающего одну ячейку
Определите размер наименьшего элемента. В файле CSS создайте класс каскадных таблиц стилей (CSS) с именем "smallListIconTextItem".
.smallListIconTextItem { }
Наименьший элемент занимает только одну ячейку. Задайте ширину элемента 300 пкс, высоту — 70 пкс, а отбивку — 5 пкс.
.smallListIconTextItem { width: 300px; height: 70px; padding: 5px; overflow: hidden; background-color: Pink; display: -ms-grid; }
Сверьте числа ниже с нашей формулой, чтобы убедиться, что они соответствуют размеру основной ячейки.
ширина ячейки = ширина элемента + отбивка слева + отбивка справа + толщина границы + левое поле + правое поле = 300 + 5 пкс + 5 пкс + 0 + 0 + 0 = 310
высота ячейки = высота элемента + отбивка сверху + отбивка снизу + толщина границы + верхнее поле + нижнее поле = 300 + 5 пкс + 5 пкс + 0 + 0 + 0 = 80
Значения соответствуют размеру основной ячейки, и можно переходить к следующему шагу.
Шаг 4. Определение размеров элементов, объединяющих две ячейки
При определении размера элемента, занимающего одну или несколько ячеек, необходимо также учитывать поле win-container
между этими ячейками. Например, если у вас есть элемент, занимающий по горизонтали одну ячейку, а по вертикали две ячейки, общий размер элемента включает win-container
нижнее поле первой ячейки и win-container
верхнее поле второй ячейки, как показано здесь:
Ниже приводится формула для расчета размера элемента, объединяющего несколько ячеек:
общая ширина элемента = number of cells * ширина основной ячейки + (number of cells – 1) * (
win-container
левое поле +win-container
правое поле)общая высота элемента = number of cells * высота основной ячейки + (number of cells – 1) * (
win-container
верхнее поле +win-container
нижнее поле)
Совет По умолчанию поле win-container
равно 5 пкс.
Определение размера элемента, объединяющего две ячейки по вертикали
Определите общую высоту элемента с помощью формулы:
общая высота элемента = number of cells * высота основной ячейки + (number of cells - 1) * (
win-container
верхнее поле +win-container
нижнее поле) = 2 * 80 + (2-1) * (5 + 5) = 170Создайте стиль CSS, в котором указывается размер элемента. В этом примере определяется элемент с высотой 160 пкс и отбивкой 5 пкс, и общая высота составляет 160 + 5 + 5 = 170. Так как элемент занимает только одну ячейку по горизонтали, задайте те же ширину и отбивку, что и в классе CSS, созданном на шаге 3,
smallListIconTextItem
..mediumListIconTextItem { width: 300px; height: 160px; padding: 5px; overflow: hidden; background-color: LightGreen; display: -ms-grid; }
Определение размера элемента, объединяющего три ячейки по вертикали
Определите общую высоту элемента с помощью формулы:
общая высота элемента = number of cells * высота основной ячейки + (number of cells - 1) * (
win-container
верхнее поле +win-container
нижнее поле) = 3 * 80 + (3 -1 ) * (5 + 5) = 260Создайте стиль CSS, в котором указывается размер элемента. В этом примере определяется элемент с высотой 250 пкс и отбивкой 5 пкс, и общая высота составляет 250 + 5 + 5 = 260.
.largeListIconTextItem { width: 300px; height: 250px; padding: 5px; overflow: hidden; background-color: LightBlue; display: -ms-grid; }
Шаг 5. Создание функции определения размера элемента CellSpanningLayout
В дополнение к функции groupInfo объект CellSpanningLayout должен предоставлять функцию itemInfo, которая указывает способ определения размера элементов разных типов в источнике данных. Функция itemInfo должна возвращать объект JavaScript, который содержит следующие свойства.
Определение размера отдельных элементов в ListView
В файле JavaScript, где вы создали свои данные, создайте функцию itemInfo, которая получает элемент из источника данных и возвращает соответствующий размер и высоту этого элемента.
// Item info function that returns the size of a cell spanning item var itemInfo = WinJS.Utilities.markSupportedForProcessing(function itemInfo(itemIndex) { var size = { width: 310, height: 80 }; // Get the item from the data source var item = DataExamples.myCellSpanningData.getAt(itemIndex); if (item) { // Get the size based on the item type switch (item.type) { case "smallListIconTextItem": size = { width: 310, height: 80 }; break; case "mediumListIconTextItem": size = { width: 310, height: 170 }; break; case "largeListIconTextItem": size = { width: 310, height: 260 }; break; default: } } return size; });
Свойство itemInfo упаковывается вызовом WinJS.Utilities.markSupportedForProcessing для обеспечения доступа к функции в HTML.
Сделайте функцию itemInfo общедоступной, предоставив ее с помощью пространства имен. В этом примере обновляется пространство имен
DataExamples
, созданное на шаге 1.1.WinJS.Namespace.define("DataExamples", { myCellSpanningData: myCellSpanningData, groupInfo: groupInfo, itemInfo: itemInfo });
Обновите ListView, чтобы использовать функцию itemInfo.
<div id="myListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: DataExamples.myCellSpanningData.dataSource, layout: { groupInfo: DataExamples.groupInfo, itemInfo: DataExamples.itemInfo, type: WinJS.UI.CellSpanningLayout } }" ></div>
Шаг 6. Создание шаблона
На последнем шаге создается шаблон или функция шаблонов, которая использует только что созданные классы CSS. Ниже показано создание WinJS.Binding.Template и функции шаблонов.
Вариант А. Использование шаблона WinJS.Binding.Template
В HTML определите WinJS.Binding.Template.
<div id="myItemTemplate" data-win-control="WinJS.Binding.Template" style="display: none"> <div> <img src="#" class="regularListIconTextItem-Image" data-win-bind="src: picture" /> <div class="regularListIconTextItem-Detail"> <h4 data-win-bind="innerText: title"></h4> <h6 data-win-bind="innerText: text"></h6> </div> </div> </div>
Помните, как при определении данных на шаге 1.1 мы включили свойство
type
, указывающее класс CSS для назначения каждому элементу? Теперь можно использовать эти данные. В корневом элементе привяжите имя класса к значению поляtype
данных.<div id="myItemTemplate" data-win-control="WinJS.Binding.Template" style="display: none"> <div data-win-bind="className: type"> <img src="#" class="regularListIconTextItem-Image" data-win-bind="src: picture" /> <div class="regularListIconTextItem-Detail"> <h4 data-win-bind="innerText: title"></h4> <h6 data-win-bind="innerText: text"></h6> </div> </div> </div>
Примечание В примере привязывается className, а не class. Это связано с тем, что хотя используется "класс" в HTML, резервное свойство JavaScript называется "className". Когда ваше приложение обрабатывает атрибут data-win-bind, привязанные значения назначаются посредством вызовов JavaScript.
Это значит, что если имя атрибута HTML и имя резервного свойства JavaScript различаются, при настройке data-win-bind используется имя свойства JavaScript.
Чтобы использовать шаблон, обновите ListView, присвоив его свойству itemTemplate идентификатор вашего шаблона.
<div id="listView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: DataExamples.myCellSpanningData.dataSource, itemTemplate: select(#'myItemTemplate'), layout: { groupInfo: DataExamples.groupInfo, itemInfo: DataExamples.itemInfo, type: WinJS.UI.CellSpanningLayout } }"></div
При необходимости вместо WinJS.Binding.Template можно использовать функцию шаблонов. Использование функции шаблонов может обеспечить большую гибкость в создании кода HTML и назначении размеров.
Вариант Б. Использование функции шаблонов
В файле JavaScript определите функцию шаблонов. Этот код можно добавить в тот же файл, который содержит ваши данные, или в другой файл. Просто убедитесь, что страница с вашим ListView ссылается на этот файл.
В этом примере с использованием данных
type
каждый элемент назначается классу CSS, определяющему размер этого элемента.var myCellSpanningJSTemplate = function myCellSpanningJSTemplate(itemPromise) { return itemPromise.then(function (currentItem) { var result = document.createElement("div"); // Use source data to decide what size to make the // ListView item result.className = currentItem.data.type; result.style.overflow = "hidden"; // Display image var image = document.createElement("img"); image.className = "regularListIconTextItem-Image"; image.src = currentItem.data.picture; result.appendChild(image); var body = document.createElement("div"); body.className = "regularListIconTextItem-Detail"; body.style.overflow = "hidden"; result.appendChild(body); // Display title var title = document.createElement("h4"); title.innerText = currentItem.data.title; body.appendChild(title); // Display text var fulltext = document.createElement("h6"); fulltext.innerText = currentItem.data.text; body.appendChild(fulltext); return result; }); };
Вызовите markSupportedForProcessing для функции, чтобы она была доступна с помощью разметки.
WinJS.Utilities.markSupportedForProcessing(myCellSpanningJSTemplate);
Сделайте функцию общедоступной с помощью WinJS.Namespace.define.
WinJS.Namespace.define("Templates", { myCellSpanningJSTemplate: myCellSpanningJSTemplate });
Чтобы использовать функцию шаблонов, в коде HTML обновите ListView, задав для свойства itemTemplate имя вашей функции шаблонов.
<div id="myListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: DataExamples.myCellSpanningData.dataSource, itemTemplate: Templates.myCellSpanningJSTemplate layout: { groupInfo: DataExamples.groupInfo, itemInfo: DataExamples.itemInfo, type: WinJS.UI.CellSpanningLayout } }" ></div>
Независимо от используемого подхода к шаблонам, при запуске приложения ListView отображает элементы с разными размерами:
Примечания
Изменение элементов
При изменении элементов в ListView с включенным объединением ячеек вызывайте ListView.recalculateItemPosition, когда необходимо внести изменение.
- Если источником данных является WinJS.Binding.List, вызовите recalculateItemPosition немедленно после редактирования (например, после вызова List.push или List.splice).
- Если источником данных является пользовательский объект VirtualizedDataSource, вызовите beginEdits, выполните редактирование, вызовите recalculateItemPosition, а затем endEdits.