Como exibir itens de tamanhos diferentes (HTML)
[ Este artigo destina-se aos desenvolvedores do Windows 8.x e do Windows Phone 8.x que escrevem aplicativos do Windows Runtime. Se você estiver desenvolvendo para o Windows 10, consulte documentação mais recente ]
Por padrão, o ListView aloca o mesmo tamanho para cada item na lista. Quando você usa um layout de grade, pode modificar esse comportamento e exibir itens de tamanhos diferentes distribuindo os itens em múltiplas células.
O que você precisa saber
Tecnologias
Pré-requisitos
- Nós presumimos que você é capaz de criar um objeto ListView básico. Veja uma introdução ao controle ListView em Guia de início rápido: adicionando um ListView.
Instruções
Sobre células e dimensionamento no ListView
Antes de entrarmos no código, vale a pena saber como o ListView lida com o dimensionamento de itens.
Por padrão, o ListView aloca células do mesmo tamanho para cada item que ele contém. Aqui está um ListView que contém itens do mesmo tamanho.
Aqui está o mesmo ListView, com uma célula individual realçada.
O tamanho da célula é determinado pelo tamanho do primeiro item no ListView. Quando o ListView contém itens de diferentes tamanhos, ele ainda aloca o tamanho de célula com base no tamanho do primeiro item. Sendo assim, se um item for maior do que os outros, ele será cortado para corresponder aos tamanhos dos outros itens do ListView.
Você pode alterar esse comportamento habilitando a abrangência de célula. Quando você faz isso, um item pode abranger várias células. Neste exemplo, a abrangência de célula está ativada para que o maior item abranja 5 células em vez de uma.
Ao ativar um espaçamento de célula, você também pode especificar explicitamente o tamanho de uma célula base. Nós recomendamos que cada item no ListView tenha um tamanho que seja múltiplo do tamanho da célula base. No exemplo a seguir, o maior item foi modificado para ter o dobro da altura da célula base, mas com a mesma largura.
Veja como criar um ListView que contém itens de três tamanhos diferentes.
Etapa 1: criar os dados e o ListView
Primeiro, vamos criar uma fonte de dados e um ListView.
No arquivo JavaScript, defina uma fonte de dados para o ListView. Este exemplo criar um List a partir de uma matriz de objetos JSON e o torna publicamente acessível usando WinJS.Namespace.define para expô-lo por meio de um namespace chamado
DataExamples
.Os dados são semelhantes aos exemplos mostrados em outros tópicos, como Início rápido: adicionando um ListView, com um item a mais: um campo
type
. Ele tem três valores possíveis: "smallListIconTextItem", "mediumListIconTextItem" e "largeListIconTextItem". Nas etapas posteriores, nós usamos esse campo para atribuir uma classe CSS que determina o tamanho de cada item.(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 }); })();
(Se você estiver codificando e quiser usar as imagens desse exemplo, poderá obtê-las baixando o Exemplo de modelos de item do ListView.)
No seu arquivo HTML file, crie um ListView que usa o layout de espaçamento de célula. Defina a propriedade itemDataSource com a fonte de dados que você criou na etapa anterior.
<div id="myListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: DataExamples.myCellSpanningData.dataSource, layout: { type: WinJS.UI.CellSpanningLayout } }" ></div>
Etapa 2: Defina o tamanho da célula base e habilite o espaçamento de célula
Agora precisamos definir o tamanho da célula base.
Para criar o ListView use um layout de espaçamento de célula, crie um objeto CellSpanningLayout e use-o para definir as propriedades do ListView controle layout. Para ativar a abrangência de célula e definir o tamanho da célula base, crie uma função groupInfo que forneça essas informações e use-a para definir a propriedade groupInfo do objeto CellSpanningLayout. A função groupInfo que definimos deve retornar um objeto que contém essas propriedades.
enableCellSpanning
Defina como true para ativar a abrangência de célula. O valor padrão é false.cellWidth
A largura da célula base.cellHeight
A altura da célula base.
Para este exemplo, vamos usar um tamanho de célula base de 310×80 pixels.
Para definir o tamanho da célula base e habilitar o espaçamento de célula
No arquivo JavaScript onde você criou seus dados, crie uma função groupInfo que ativa o espaçamento de célula e define a célula base como tendo 310×80 pixels.
// Enable cell spanning and specify // the cellWidth and cellHeight for the items var groupInfo = function groupInfo() { return { enableCellSpanning: true, cellWidth: 310, cellHeight: 80 }; };
Use WinJS.Utilities.markSupportedForProcessing para tornar sua função acessível em HTML.
// 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);
(Por padrão, as funções e os manipuladores de eventos estão inacessíveis para os controles da Biblioteca do Windows para JavaScript por questões de segurança. A função WinJS.Utilities.markSupportedForProcessing permite que você substitua esse comportamento padrão. Isto presume que o HTML fornecido por você está corretamente formado e pode ser processado pelo WinJS. Para saber mais, veja Codificando aplicativos básicos.)
Chamar WinJS.Utilities.markSupportedForProcessing na sua função não a torna publicamente acessível. Faremos isso na próxima etapa.
Torne a sua função groupInfo publicamente acessível expondo-a em um namespace. Este exemplo atualiza o
DataExamples
namespace criado na Etapa 1.1.WinJS.Namespace.define("DataExamples", { groupInfo : groupInfo, myCellSpanningData: myCellSpanningData });
Atualize o ListView para usar a função 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>
Etapa 3: definir o tamanho de um item que abrange uma única célula
Agora que definimos o tamanho da célula base, podemos definir os tamanhos dos itens. Quando nós definimos os dados na primeira etapa, incluímos um campo type
que contém informações sobre de que tamanho um item pode ser: pequeno, médio ou grande. Podemos usar essas informações para atribuir tamanhos de item. A melhor maneira de atribuir tamanhos é usar classes CSS. Essa abordagem funciona quando usamos uma função de modelagem ou WinJS.Binding.Template.
Nossa célula base tem 310 pixels de largura e 80 pixels de altura. O tamanho total de cada item deve ser um múltiplo do tamanho da célula base. O tamanho da célula base é o tamanho do item mais o preenchimento, a margem e a borda do item:
Aqui está a fórmula para calcular o tamanho da célula base:
- largura da célula base = largura do item + preenchimento horizontal do item + margem horizontal do item + espessura da borda do item
- altura da célula base = altura do item + preenchimento vertical do item + margem vertical do item + espessura da borda do item
Para definir o tamanho de um item que abrange uma única célula base
Vamos definir o tamanho do menor item. No seu arquivo CSS file, crie uma classe de Cascading Style Sheets (CSS) chamada "smallListIconTextItem".
.smallListIconTextItem { }
O menor item ocupa apenas uma célula. Vamos definir a largura do item para 300px, sua altura para 70px e seu preenchimento para 5px.
.smallListIconTextItem { width: 300px; height: 70px; padding: 5px; overflow: hidden; background-color: Pink; display: -ms-grid; }
Vamos verificar esses números em relação à nossa fórmula para ter certeza de que eles correspondem ao tamanho da nossa célula base.
largura da célula = largura do item + preenchimento esquerdo + preenchimento direito + espessura da borda + margem esquerda + margem direita = 300 + 5px + 5px + 0 + 0 + 0 = 310
altura da célula = altura do item + preenchimento superior + preenchimento inferior + espessura da borda + margem superior + margem inferior = 70px + 5px + 5px + 0 + 0 + 0= 80
Eles realmente correspondem ao tamanho da nossa célula base, então podemos passar para a próxima etapa.
Etapa 4: definir os tamanhos dos itens que abrangem 2 ou mais células
Ao determinar o tamanho de um item que se espalha por mais de uma ou mais células, você deve também levar em consideração a margem win-container
entre as células nas quais ele ocupa. Por exemplo se você tem um item que se espalha por uma célula horizontalmente, mas por duas células verticalmente, o tamanho total inclui a margem inferior win-container
da primeira célula e a margem superior win-container
da segunda célula, conforme mostrado aqui.
Aqui está a fórmula para calcular o tamanho total de um item que abrange várias células:
largura total do item = largura da célula base number of cells * + (number of cells - 1) * (margem esquerda
win-container
+ margem direitawin-container
)altura total do item = altura da célula base number of cells * + (number of cells - 1) * (margem superior
win-container
+ margem inferiorwin-container
)
Dica A margem win-container
é por padrão 5 pixels.
Para definir o tamanho de um item que se espalha verticalmente por duas células
Use nossa fórmula para determinar a altura total do item:
altura total do item = altura da célula base number of cells * + (number of cells - 1) * (margem superior
win-container
+ margem inferiorwin-container
) = 2 * 80 + (2-1) * (5 + 5) = 170Crie o estilo CSS que especifica o tamanho do item. Este exemplo define um item que tem uma altura de 160 pixels e um espaçamento de 5 pixels, de modo que o tamanho total é de 160 + 5 + 5 = 170. Como o item abrange apenas uma célula na horizontal, atribua a ele a mesma largura e o mesmo preenchimento da classe CSS criada na Etapa 3,
smallListIconTextItem
..mediumListIconTextItem { width: 300px; height: 160px; padding: 5px; overflow: hidden; background-color: LightGreen; display: -ms-grid; }
Para definir o tamanho de um item que abrange três células na vertical
Use nossa fórmula para determinar a altura total do item:
altura total do item = altura da célula base number of cells * + (number of cells - 1) * (margem superior
win-container
+ margem inferiorwin-container
) = 3 * 80 + (3-1) * (5 + 5) = 260Crie o estilo CSS que especifica o tamanho do item. Este exemplo define um item que tem uma altura de 250 pixels e um espaçamento de 5 pixels, de modo que o tamanho total é de 250 + 5 + 5 = 260.
.largeListIconTextItem { width: 300px; height: 250px; padding: 5px; overflow: hidden; background-color: LightBlue; display: -ms-grid; }
Etapa 5: Crie uma função de dimensionamento de item para CellSpanningLayout
Além da função groupInfo, o CellSpanningLayout precisa expor uma função itemInfo que determina como dimensionar os itens de diferentes 'tipos' na origem de dados. A função itemInfo precisa retornar um objeto JavaScript que contenha as seguintes propriedades:
Para definir o tamanho dos itens individuais na ListView
No arquivo JavaScript onde você criou seus dados, crie uma função itemInfo que recupera um item da origem de dados e retorna o tamanho e altura correspondente para aquele item.
// 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; });
O itemInfo é envolvido em uma chamada para WinJS.Utilities.markSupportedForProcessing para tornar a função acessível em HTML.
Torne a sua função itemInfo publicamente acessível expondo-a em um namespace. Este exemplo atualiza o
DataExamples
namespace criado na Etapa 1.1.WinJS.Namespace.define("DataExamples", { myCellSpanningData: myCellSpanningData, groupInfo: groupInfo, itemInfo: itemInfo });
Atualize o ListView para usar a função 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>
Etapa 6: criar o modelo
Na última etapa, vamos criar um modelo ou uma função de modelagem que usa as classes CSS que acabamos de definir. Nós mostraremos a você como criar um WinJS.Binding.Template e uma função de modelagem.
Opção A: usar um WinJS.Binding.Template
No arquivo HTML, defina um 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>
Lembre-se de como, quando definimos nossos dados na Etapa 1.1, incluímos uma propriedade
type
que especificou qual classe CSS foi atribuída a cada item? Agora nós podemos usar esses dados. No elemento raiz do item, associe o nome da classe ao valor do campotype
dos nossos dados.<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>
Observação O exemplo associa a className, não class. Isso porque, mesmo que você use "class" em HTML, a propriedade JavaScript auxiliar é denominada "className". Quando seu aplicativo processa o atributo data-win-bind, ele atribui os valores associados via chamadas JavaScript.
Isso significa que sempre que o nome do atributo HTML e o nome da propriedade JavaScript auxiliar forem diferentes, você usará o nome da propriedade JavaScript ao definir data-win-bind.
Atualize o ListView para usar o modelo configurando sua propriedade itemTemplate com o ID do seu modelo.
<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
Se quiser, você pode usar uma função de modelagem em vez de um WinJS.Binding.Template. A função de modelagem proporciona mais flexibilidade na forma como você gera o HTML e atribui tamanhos.
Opção B: usar uma função de modelagem
Em um arquivo JavaScript, defina sua função de modelagem. Você pode adicionar esse código ao mesmo arquivo que contém seus dados ou pode adicioná-lo a outro arquivo. Verifique se a página que contém seu ListView faz referência a esse arquivo.
Este exemplo usa os dados
type
para cada item para atribuir a classe CSS que determina seu tamanho.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; }); };
Chame markSupportedForProcessing na função para que ela possa ser acessada por marcação.
WinJS.Utilities.markSupportedForProcessing(myCellSpanningJSTemplate);
Use WinJS.Namespace.define para tornar a função publicamente acessível.
WinJS.Namespace.define("Templates", { myCellSpanningJSTemplate: myCellSpanningJSTemplate });
No arquivo HTML, atualize o ListView para usar a função de modelagem definindo a propriedade itemTemplate com o nome da função de modelagem.
<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>
Independente de qual abordagem de modelo for usada, quando você executar o aplicativo, o ListView exibe itens de vários tamanhos.
Comentários
Editando itens
Ao alterar itens em um ListView que tem o espaçamento de célula ativado, chame ListView.recalculateItemPosition sempre que fizer uma alteração.
- Se a fonte de dados for um WinJS.Binding.List, chame recalculateItemPosition logo após fazer uma edição (como após chamar List.push ou List.splice).
- Se a fonte de dados for um VirtualizedDataSource personalizado, chame beginEdits, faça as edições e, depois, chame recalculateItemPosition e endEdits.