Отображение элементов с переменной высотой в ListLayout

У меня есть приложение метро WinJs, содержащее ListView с элементами переменной высоты. В основном это делается так же, как в Сценарии 4 в "HTML ListView шаблоны элементов" пример. Функция groupInfo используется для включения диапазона ячеек GridLayout, связанного с ListView:

элементы в сетке

Теперь в представлении привязки моего приложения я хотел бы, чтобы элементы прокручивались вертикально, поэтому я попытался заменить GridLayout на ListLayout. Это вызывает вертикальную прокрутку, но теперь диапазон ячеек отсутствует, а элементы перекрываются:

элементы в макете списка

Я использовал функцию groupInfo так же, как и GridLayout, но она, кажется, игнорируется:

layout: { 
    groupInfo: groupInfo, 
    type: WinJS.UI.ListLayout 
} 

Есть ли способ использовать элементы переменного размера в ListLayout? Некоторые из моих элементов содержат больше контента, чем другие, и мне бы очень хотелось использовать плитки разных размеров, чтобы все отображалось оптимально.


person sth    schedule 29.06.2012    source источник


Ответы (2)


старый пост

Да, вы, конечно, можете настроить все. Я думаю, что ваша проблема с рендерингом возникла из-за того, что вы, возможно, забыли файл forceLayout.

ready: function (element, options) { 
            element.querySelector("#listView").winControl.forceLayout(); 
        }

У меня нет поблизости Windows 8, поэтому, если никто не ответит и проблема не в forceLayout, я обновлю ответ к ночи.

Я надеюсь, что это поможет.

Итак, я неправильно понял вашу проблему ранее.

Вот то, что должно вас удовлетворить.

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

Итак, что касается JavaScript, я использовал две функции, которые можно найти, например, в шаблоне Grid Application. Поэтому я изменил сценарий4.js, чтобы получить этот код.

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;
    });
}

var appViewState = Windows.UI.ViewManagement.ApplicationViewState;
var appView = Windows.UI.ViewManagement.ApplicationView;
var ui = WinJS.UI;

(function () {
    "use strict";
    var page = WinJS.UI.Pages.define("/html/scenario4.html", {
        initializeLayout: function (listView, viewState) {
            /// <param name="listView" value="WinJS.UI.ListView.prototype" />

            if (viewState === appViewState.snapped) {
                listView.layout = new ui.ListLayout();
            } 
            else {
                listView.layout = new ui.GridLayout({ groupInfo: groupInfo });
            }
        },
        ready: function (element, options) {
            var listView = element.querySelector("#listView").winControl;
            this.initializeLayout(listView, appView.value);
        },
        updateLayout: function (element, viewState, lastViewState) {

            var listView = element.querySelector("#listView").winControl;

            if (lastViewState !== viewState) {
                if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {                   
                    this.initializeLayout(listView, viewState);
                } 
                else {
                    listView.layout = new ui.GridLayout({ groupInfo: groupInfo });
                }
            }
        }
    });
})();

Затем я удалил все свойство layout представления списка в сценарии4.html, так как я создал макет выше в сценарии4.js

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

Так что нам просто нужно обновить script4.css в зависимости от состояния просмотра, а в CSS 3 у нас есть медиа-запросы, которые позволяют нам это делать. Затем, в зависимости от состояния просмотра здесь snapped, мы переопределим наши свойства. Вам просто нужно добавить код ниже в ваш сценарий4.css

@media screen and (-ms-view-state: snapped) {
    #listView {
        max-width: 260px;
        height: 280px;
        border: solid 2px rgba(0, 0, 0, 0.13);
    }

    .regularListIconTextItem {
        max-width: 250px;
        max-height: 70px;
        padding: 5px;
        overflow: hidden;
        display: -ms-grid;
    }

    .smallListIconTextItem {
        max-width: 250px;
        max-height: 70px;
        padding: 5px;
        overflow: hidden;
        background-color: Pink;
        display: -ms-grid;
    }

    /* Medium size */
    .mediumListIconTextItem {
        max-width: 250px;
        max-height: 70px;
        padding: 5px;
        overflow: hidden;
        background-color: LightGreen;
        display: -ms-grid;
    }

    /* Large size */
    .largeListIconTextItem {
        max-width: 250px;
        max-height: 70px;
        padding: 5px;
        overflow: hidden;
        background-color: LightBlue;
        display: -ms-grid;
    }
}

Надеюсь, в этот раз поможет ;)

person Aymeric    schedule 02.07.2012
comment
Уже был forceLayout() звонок ready, который не помог. Чтобы проверить это дальше, я добавил кнопку для ручного вызова forceLayout(). Когда вы щелкнете по нему, вы увидите, что ListView отрисовывается, но результат все тот же, с перекрывающимися элементами... - person sth; 02.07.2012
comment
Хорошо, так что я буду дома через 4 часа, я попытаюсь воспроизвести вашу проблему и напишу, если смогу ее исправить. Кстати, вы на Release Preview или на Consumer Preview? - person Aymeric; 02.07.2012
comment
Я использую Release Preview. - person sth; 02.07.2012
comment
Такое переключение макета и CSS должно работать хорошо, я просто предпочел бы, чтобы некоторые элементы могли быть больше других в представлении привязки/ListLayout. Если я сделаю все элементы одинакового размера, то во всех случаях мне не хватит места для данных, которые я хочу отобразить. - person sth; 03.07.2012
comment
Да, вы, конечно, могли бы, но я не уверен, что вы выглядите действительно хорошо, потому что изображение на снимке довольно плотное. Более того, вы не будете следовать рекомендациям по UX, предоставленным MS для Windows 8 Metro, и поэтому ваше приложение может быть отклонено магазином. - person Aymeric; 03.07.2012
comment
@Aymeric Дело в том, что иметь переменную высоту в макете списка... Этот ответ не может быть проверен, потому что он описывает, как иметь макет списка с определенной уникальной высотой. - person enguerran; 17.07.2012

Моя общая идея состоит в том, чтобы переключить шаблон в виде с привязкой, чтобы избежать использования MyCellSpanningJSTemplate, который изменяет размер шаблона элемента. Вы можете дать эту попытку.

1) Создайте второй шаблон элемента:

    <div id="listLayoutItemTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
        <div class="regularListIconItem">
            <img src="#" class="regularListIconItem-Image" data-win-bind="src: picture" />
        </div>
    </div>

2) определить моментальное представление путем прослушивания события изменения размера (см. http://code.msdn.microsoft.com/windowsapps/Snap-Sample-2dc21ee3)

3) Программно измените шаблон на шаблон, созданный на шаге 1.

var listView = document.querySelector("#listView").winControl;
listView.itemTemplate = listLayoutItemTemplate;
person Alan Le    schedule 02.07.2012
comment
На самом деле я хочу, чтобы мои элементы имели разные размеры (некоторые элементы содержат больше содержимого, которое необходимо отобразить). Если я сделаю их всех одинакового размера, то будет либо много пустого места для многих элементов, либо отсутствует важный контент для некоторых других элементов... - person sth; 03.07.2012