Compartir a través de


Cómo mostrar elementos de diferentes tamaños (HTML)

[ Este artículo está destinado a desarrolladores de Windows 8.x y Windows Phone 8.x que escriben aplicaciones de Windows Runtime. Si estás desarrollando para Windows 10, consulta la documentación más reciente ]

De manera predeterminada, ListView asigna el mismo tamaño para cada elemento de la lista. Cuando uses un diseño de cuadrícula, podrás modificar este comportamiento y mostrar elementos que tengan distintos tamaños haciendo que estos elementos se expandan por varias celdas.

Lo que debes saber

Tecnologías

Requisitos previos

Instrucciones

Acerca de las celdas y los tamaños en ListView

Antes de entrar en el código, sería útil comprender cómo ListView controla el tamano de los elementos.

De manera predeterminada, ListView asigna celdas del mismo tamaño para cada elemento que contiene. Aquí vemos un ListView que contiene elementos que tienen todos el mismo tamaño.

Un ListView que contiene elementos del mismo tamaño

Aquí vemos el mismo ListView con una celda individual resaltada.

Una celda en un ListView

El tamaño de la celda viene determinado por el tamaño del primer elemento del ListView. Cuando el ListView contiene elementos de distintos tamaños, todavía puede asignar el tamaño de la celda en función del tamaño del primer elemento. Por lo tanto, si un elemento es mayor que los otros, se recortará para que coincida con los tamaños de los otros elementos del ListView.

Un ListView que contiene elementos de diferentes tamaños

Puedes cambiar este comportamiento habilitando la expansión de celdas. Al hacerlo, un elemento puede ocupar varias celdas. En este ejemplo, la expansión de celdas está activada, de modo que el elemento de mayor tamaño ocupa 5 celdas en vez de una.

Un ListView con la expansión de celdas habilitada

Cuando actives la expansión de celdas, también podrás especificar explícitamente el tamaño de la celda base. Recomendamos que cada elemento del ListView tenga un tamaño que sea un múltiplo del tamaño de la celda base. En el siguiente ejemplo, se ha modificado el elemento de mayor tamaño para que tenga el doble de altura que la celda base, pero el mismo ancho.

Un ListView con elementos que son múltiplos del mismo tamaño de la celda base

Aquí se muestra cómo crear un ListView que contenga elementos de tres tamaños diferentes.

Paso 1: Crea tus datos en el ListView

Primero vamos a crear un origen de datos y un ListView.

  1. En un archivo JavaScript, define un origen de datos para el ListView. Este ejemplo crea un List a partir de una matriz de objetos JSON y los hace accesibles públicamente mediante WinJS.Namespace.define para exponerlo en un espacio de nombres denominado DataExamples.

    Los datos son similares a los ejemplos que hemos mostrado en otros temas, como Inicio rápido: agregar ListView, pero con un elemento adicional: un campo type. Tiene tres valores posibles de menor a mayor tamaño: "smallListIconTextItem", "mediumListIconTextItem" y "largeListIconTextItem". En los siguientes pasos usaremos este campo para asignar una clase CSS que determine el tamaño de cada elemento.

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

    (Si vas a probar este código y quieres usar las imágenes que se usan en este ejemplo, descarga la Muestra de plantillas del elemento ListView).

  2. En el archivo HTML, crea un ListView que use el diseño de expansión de celdas. Establece su propiedad itemDataSource en el origen de datos que creaste en el paso anterior.

    <div id="myListView" 
        data-win-control="WinJS.UI.ListView" 
        data-win-options="{ 
            itemDataSource: DataExamples.myCellSpanningData.dataSource, 
            layout: {  
                type: WinJS.UI.CellSpanningLayout 
            } 
        }"
    ></div>
    

Paso 2: Define el tamaño de la celda base y habilita la expansión de celdas

Ahora tenemos que definir el tamaño de la celda base.

Para hacer que el ListView use un diseño de expansión de celdas, deberás crear un objeto CellSpanningLayout y usarlo para establecer la propiedad layout del control ListView. Para activar la expansión de celdas y definir el tamaño de la celda base, crea una función groupInfo que proporcione esta información y úsala para establecer la propiedad groupInfo del objeto CellSpanningLayout. La función groupInfo que definamos debe devolver un objeto que contenga las siguientes propiedades.

  • enableCellSpanning
    Establecida como true para activar la expansión de celdas. El valor predeterminado es false.

  • cellWidth
    El ancho de la celda base.

  • cellHeight
    La altura de la celda base.

Para este ejemplo usaremos un tamaño de celda base de 310 × 80 píxeles.

JJ657974.wedge(es-es,WIN.10).gifPara definir el tamaño de la celda base y habilitar la expansión de celdas

  1. En el archivo JavaScript donde creaste los datos, crea una función groupInfo que active la expansión de celdas y defina la celda base en 310 × 80 píxeles.

    // Enable cell spanning and specify
    // the cellWidth and cellHeight for the items
    var groupInfo = function groupInfo() {
        return {
            enableCellSpanning: true,
            cellWidth: 310,
            cellHeight: 80
        };
    };
    
  2. Usa WinJS.Utilities.markSupportedForProcessing para que la función sea accesible en 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);
    

    (De manera predeterminada, las funciones y los controladores de eventos no son accesibles en los controles de la Biblioteca de Windows para JavaScript por razones de seguridad. La función WinJS.Utilities.markSupportedForProcessing te permite invalidar este comportamiento predeterminado. Con esto se supone que el HTML que proporciones tiene el formato correcto y puede ser procesado por WinJS. Para obtener más información, consulta Codificar aplicaciones básicas).

    La llamada a WinJS.Utilities.markSupportedForProcessing en tu función no hace que sea accesible públicamente. Eso lo haremos en el siguiente paso.

  3. Haz que tu función groupInfo sea accesible públicamente exponiéndola a través de un espacio de nombres. Este ejemplo actualiza el espacio de nombres DataExamples que hemos creado en el paso 1.1.

    WinJS.Namespace.define("DataExamples",
        {
            groupInfo : groupInfo,
            myCellSpanningData: myCellSpanningData
        });
    
  4. Actualiza tu ListView para que use la función 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>
    

Paso 3: Define el tamaño de un elemento que se expande una sola celda

Ahora que hemos definido el tamaño de la celda base, podremos definir los tamaños de nuestros elementos. Cuando definimos nuestros datos en el primer paso, incluimos un campo type que contiene información sobre el tamaño que puede tener el elemento: pequeño, mediano o grande. Podemos usar esa información para asignar los tamaños de los elementos. La mejor manera de asignar los tamaños es mediante el uso de clases CSS. Este enfoque funciona tanto si usamos una función de plantillas o un WinJS.Binding.Template.

Nuestra celda base es de 310 píxeles de ancho y 80 píxeles de altura. El tamaño total de cada elemento debe ser un múltiplo del tamaño de la celda base. El tamaño de la celda base es el tamaño del elemento más su espaciado interno, márgenes y bordes:

Una celda en un ListView

Esta es la fórmula para calcular el tamaño de la celda base:

  • ancho de la celda base = ancho del elemento + espaciado interno horizontal del elemento + margen horizontal del elemento + grosor del borde del elemento
  • altura de la celda base = altura del elemento + espaciado interno vertical del elemento + margen vertical del elemento + grosor del borde del elemento

JJ657974.wedge(es-es,WIN.10).gifPara definir el tamaño de un elemento que ocupa una sola celda base

  1. Definamos el tamaño del elemento más pequeño. En el archivo CSS, crea una clase de hojas de estilo CSS llamada "smallListIconTextItem".

    .smallListIconTextItem
    {
    
    }     
    
  2. El elemento más pequeño solo ocupará una celda. Establezcamos el ancho del elemento en 300px, su altura en 70px y su espaciado interno en 5px.

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

    Ahora comprobemos esos números con nuestra fórmula para asegurarnos de que coinciden con nuestro tamaño de celda base.

    • ancho de la celda = ancho del elemento + espaciado interno izquierdo + espaciado interno derecho + grosor del borde + margen izquierdo + margen derecho = 300 + 5px + 5px + 0 + 0 + 0 = 310

    • altura de la celda = altura del elemento + espaciado interno superior + espaciado interno inferior + grosor del borde + margen superior + margen inferior = 70px + 5px + 5px + 0 + 0 + 0= 80

    Coinciden con nuestro tamaño de celda base, así que podemos ir al siguiente paso.

Paso 4: Define los tamaños de los elementos que se expanden 2 o más celdas

Al determinar el tamaño de un elemento que se expande una o más celdas, también deberás tener en cuenta el margen win-container entre las celdas en las que se expande. Por ejemplo, si tienes un elemento que se expande una celda horizontalmente pero dos celdas verticalmente, el tamaño total del elemento incluirá el margen inferior win-container de la primera celda y el margen superior win-container de la segunda celda, como se muestra aquí:

Un elemento que se expande en dos celdas

Esta es la fórmula para calcular el tamaño total de un elemento que se expande en varias celdas:

  • ancho total del elemento = number of cells * ancho de celda base + (number of cells - 1) * (win-container margen izquierdo + win-container margen derecho)

  • altura total del elemento = number of cells * altura de celda base + (number of cells - 1) * (win-container margen superior + win-container margen inferior)

Sugerencia  El margen win-container es de 5 píxeles de manera predeterminada.

 

JJ657974.wedge(es-es,WIN.10).gifPara definir el tamaño de un elemento que se expande verticalmente en dos celdas

  1. Usa nuestra fórmula para determinar la altura total del elemento:

    altura total del elemento = number of cells * altura de la celda base + (number of cells - 1) * (win-container margen superior + win-container margen inferior) = 2 * 80 + (2-1) * (5 + 5) = 170

  2. Crea el estilo CSS que especifique el tamaño del elemento. En este ejemplo se define un elemento que tiene una altura de 160 píxeles y un espaciado interno de 5 píxeles, de modo que su altura es 160 + 5 + 5 = 170. Como el elemento solo se expande en una celda horizontalmente, dale el mismo ancho y el mismo espaciado interno que la clase CSS que hemos creado en el paso 3, smallListIconTextItem.

    .mediumListIconTextItem
    {
        width: 300px;
        height: 160px;
        padding: 5px;
        overflow: hidden;
        background-color: LightGreen;
        display: -ms-grid;
    }
    

JJ657974.wedge(es-es,WIN.10).gifPara definir el tamaño de un elemento que se expande verticalmente en tres celdas

  1. Usa nuestra fórmula para determinar la altura total del elemento:

    altura total del elemento = number of cells * altura de la celda base + (number of cells - 1) * (win-container margen superior + win-container margen inferior) = 3 * 80 + (3-1) * (5 + 5) = 260

  2. Crea el estilo CSS que especifique el tamaño del elemento. En este ejemplo se define un elemento que tiene una altura de 250 píxeles y un espaciado interno de 5 píxeles, de modo que su altura es 250 + 5 + 5 = 260.

    .largeListIconTextItem
    {
        width: 300px;
        height: 250px;
        padding: 5px;
        overflow: hidden;
        background-color: LightBlue;
        display: -ms-grid;
    }
    

Paso 5: Crea la función de cambio de tamaño para CellSpanningLayout

Además de la función groupInfo, CellSpanningLayout necesita exponer una función itemInfo que determine cómo cambiar el tamaño de varios 'tipos' en el origen de datos. La función itemInfo debe devolver un objeto de JavaScript que contenga las siguientes propiedades:

  • width
    El ancho del elemento individual en el ListView.

  • height
    La altura del elemento individual en el ListView.

JJ657974.wedge(es-es,WIN.10).gifPara definir el tamaño de los elementos individuales en el ListView

  1. En el archivo de JavaScript donde has creado los datos, crea una función itemInfo que recupere un elemento del origen de datos y devuelva el tamaño y la altura correspondientes de ese elemento.

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

    La itemInfo está ajustada por una llamada a WinJS.Utilities.markSupportedForProcessing para hacer que se pueda acceder a la función en HTML.

  2. Haz que tu función itemInfo sea accesible públicamente exponiéndola a través de un espacio de nombres. Este ejemplo actualiza el espacio de nombres DataExamples que hemos creado en el paso 1.1.

    WinJS.Namespace.define("DataExamples",
        {
            myCellSpanningData: myCellSpanningData,
            groupInfo: groupInfo,
            itemInfo: itemInfo
    });
    
  3. Actualiza tu ListView para que use la función 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>
    

Paso 6: Crea la plantilla

El paso final consiste en crear una plantilla o una función de plantillas que use las clases CSS que acabamos de definir. Mostraremos cómo crear tanto un WinJS.Binding.Template como una función de plantillas.

JJ657974.wedge(es-es,WIN.10).gifOpción A: Usa un WinJS.Binding.Template

  1. En el HTML, define un 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. ¿Recuerdas cómo, cuando definimos nuestros datos en el Paso 1.1, incluimos una propiedad type que especificaba qué clase CSS se asigna a cada elemento? Ahora podemos usar estos datos. En el elemento raíz del elemento, enlaza el nombre de la clase al valor del campo type de nuestros datos.

    <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>
    

    Nota  El ejemplo se enlaza con className, no con class. Eso es porque, aunque uses la "clase" en HTML, la propiedad JavaScript de soporte se llama "className". Cuando la aplicación procesa el atributo data-win-bind, asigna los valores enlazados mediante llamadas a JavaScript.

    Esto significa que el nombre del atributo HTML y el nombre de la propiedad JavaScript de soporte sean diferentes, usarás el nombre de la propiedad JavaScript cuando establezcas data-win-bind.

     

  3. Actualiza tu ListView para que use la plantilla; para ello, configura la propiedad itemTemplate como el identificador de tu plantilla.

    <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
    

Si quieres, puedes usar una función de plantillas en vez de un WinJS.Binding.Template. El uso de una función de plantillas puede darte más flexibilidad para generar el HTML y asignar tamaños.

JJ657974.wedge(es-es,WIN.10).gifOpción B: Usa una función de plantillas

  1. Define tu función de plantillas en un archivo JavaScript. Puedes guardar este código en el mismo archivo que contiene los datos o puedes agregarlo en un archivo distinto. Asegúrate de que la página que contiene tu ListView hace referencia a este archivo.

    Este ejemplo usa los datos de type de cada elemento para asignarlos a la clase CSS que determina su tamaño.

    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. Realiza una llamada a markSupportedForProcessing en la función para que se pueda acceder a ella mediante marcado.

    WinJS.Utilities.markSupportedForProcessing(myCellSpanningJSTemplate);
    
  3. Usa WinJS.Namespace.define para que la función sea accesible públicamente.

    WinJS.Namespace.define("Templates",
        {
            myCellSpanningJSTemplate: myCellSpanningJSTemplate
        });
    
  4. En el HTML, actualiza tu ListView para usar la función de plantillas estableciendo la propiedad itemTemplate como el nombre de la función de plantillas.

    <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>
    

Independientemente de qué enfoque de plantillas hayas usado, cuando ejecutes la aplicación, el ListView mostrará elementos de varios tamaños.

Un control ListView que contiene elementos de varios tamaños

Observaciones

Edición de elementos

Cuando cambies los elementos de un ListView que tiene habilitada la expansión de celdas, realiza una llamada a ListView.recalculateItemPosition siempre que hagas un cambio.

Temas relacionados

Muestra de plantillas del elemento ListView