Как отображать элементы различных размеров (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 рекомендуется устанавливать размер, кратный размеру основной ячейки. В следующем примере более крупный элемент изменяется таким образом, что его высота становится в два раза больше высоты основной ячейки, а ширина остается та же.

ListView, содержащий элементы, кратные одному и тому же размеру основной ячейки

Ниже описано создание ListView, содержащего элементы трех разных размеров.

Шаг 1. Создание данных в ListView

Сначала создаются источник данных и ListView.

  1. Определите источник данных для 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.)

  2. В 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 пикселей.

JJ657974.wedge(ru-ru,WIN.10).gifОпределение размера основной ячейки и включение объединения ячеек

  1. В файле 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
        };
    };
    
  2. Сделайте функцию общедоступной в 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 для вашей функции не делает ее общедоступной. Это делается на следующем шаге.

  3. Сделайте функцию groupInfo общедоступной, предоставив ее с помощью пространства имен. В этом примере обновляется пространство имен DataExamples, созданное на шаге 1.1.

    WinJS.Namespace.define("DataExamples",
        {
            groupInfo : groupInfo,
            myCellSpanningData: myCellSpanningData
        });
    
  4. Обновите 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 пикселей в высоту. Общий размер каждого элемента должен быть кратным размеру основной ячейки. Размер основной ячейки составляют размер элемента, а также отбивка, поля и граница:

Ячейка в ListView

Ниже приводится формула для расчета размера основной ячейки:

  • ширина основной ячейки = ширина элемента + горизонтальная отбивка элемента + горизонтальное поле элемента + толщина границы элемента
  • высота основной ячейки = высота элемента + вертикальная отбивка элемента + вертикальное поле элемента + толщина границы элемента

JJ657974.wedge(ru-ru,WIN.10).gifОпределение размера элемента, занимающего одну ячейку

  1. Определите размер наименьшего элемента. В файле CSS создайте класс каскадных таблиц стилей (CSS) с именем "smallListIconTextItem".

    .smallListIconTextItem
    {
    
    }     
    
  2. Наименьший элемент занимает только одну ячейку. Задайте ширину элемента 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 пкс.

 

JJ657974.wedge(ru-ru,WIN.10).gifОпределение размера элемента, объединяющего две ячейки по вертикали

  1. Определите общую высоту элемента с помощью формулы:

    общая высота элемента = number of cells * высота основной ячейки + (number of cells - 1) * (win-container верхнее поле + win-container нижнее поле) = 2 * 80 + (2-1) * (5 + 5) = 170

  2. Создайте стиль 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;
    }
    

JJ657974.wedge(ru-ru,WIN.10).gifОпределение размера элемента, объединяющего три ячейки по вертикали

  1. Определите общую высоту элемента с помощью формулы:

    общая высота элемента = number of cells * высота основной ячейки + (number of cells - 1) * (win-container верхнее поле + win-container нижнее поле) = 3 * 80 + (3 -1 ) * (5 + 5) = 260

  2. Создайте стиль 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, который содержит следующие свойства.

  • width
    Ширина отдельного элемента в ListView.

  • height
    Высота отдельного элемента в ListView.

JJ657974.wedge(ru-ru,WIN.10).gifОпределение размера отдельных элементов в ListView

  1. В файле 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.

  2. Сделайте функцию itemInfo общедоступной, предоставив ее с помощью пространства имен. В этом примере обновляется пространство имен DataExamples, созданное на шаге 1.1.

    WinJS.Namespace.define("DataExamples",
        {
            myCellSpanningData: myCellSpanningData,
            groupInfo: groupInfo,
            itemInfo: itemInfo
    });
    
  3. Обновите 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 и функции шаблонов.

JJ657974.wedge(ru-ru,WIN.10).gifВариант А. Использование шаблона WinJS.Binding.Template

  1. В 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>
    
  2. Помните, как при определении данных на шаге 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.

     

  3. Чтобы использовать шаблон, обновите 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 и назначении размеров.

JJ657974.wedge(ru-ru,WIN.10).gifВариант Б. Использование функции шаблонов

  1. В файле 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;
        });
    };
    
  2. Вызовите markSupportedForProcessing для функции, чтобы она была доступна с помощью разметки.

    WinJS.Utilities.markSupportedForProcessing(myCellSpanningJSTemplate);
    
  3. Сделайте функцию общедоступной с помощью WinJS.Namespace.define.

    WinJS.Namespace.define("Templates",
        {
            myCellSpanningJSTemplate: myCellSpanningJSTemplate
        });
    
  4. Чтобы использовать функцию шаблонов, в коде 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 с включенным объединением ячеек вызывайте ListView.recalculateItemPosition, когда необходимо внести изменение.

Связанные разделы

Пример шаблона элемента ListView