Como adicionar funcionalidade comum ao modelo de grade (aplicativos da Windows Store que usam JavaScript e HTML)

Windows 8:  Este tópico aplica-se apenas ao Windows 8. Para saber mais sobre como usar um padrão de navegação hierárquica no Windows 8.1, veja Navegação hierárquica, do início ao fim (HTML).

Você pode ampliar o modelo Aplicativo de Grade do Microsoft Visual Studio para incluir outras funcionalidades principais que agregarão valor ao aplicativo. Este tutorial deve ser usado com o Microsoft Visual Studio 2012 no Windows 8. É possível encontrar aqui o pacote de aplicativos do tutorial completo.

Esta é página de aterrissagem padrão do modelo Aplicativo de Grade.

Captura de tela da página de aterrissagem padrão do modelo Aplicativo de Grade.

Depois de concluído o tutorial, o aplicativo terá itens de vários tamanhos e que usam diferentes modelos.

Captura de tela do aplicativo de grade com itens de vários tamanhos e diferentes modelos

Terá também uma barra de aplicativos que, quando algum item for selecionado, mostrará os comandos contextuais.

Captura de tela de aplicativo com barra de aplicativos e comandos contextuais quando itens são selecionados

O controle SemanticZoom será implementado.

Captura de tela de aplicativo que implementa o controle Zoom Semântico

E o aplicativo conterá animações fluidas em todas as páginas.

O modelo de aplicativo de grade

O uso de um modelo de aplicativo do Visual Basic é um jeito excelente de começar rapidamente um aplicativo com estilo de design da Microsoft. Como nem todos os desenvolvedores têm as mesmas necessidades, os modelos não incluem toda a funcionalidade. Este tutorial mostra como personalizar e agregar valor a um aplicativo baseado em modelo, mas que ainda assim segue as diretrizes do estilo de design da Microsoft. Especificamente, o tutorial mostra como personalizar um aplicativo baseado no modelo Aplicativo de Grade.

Cada seção do tutorial focaliza como adicionar um recurso específico ao modelo Aplicativo de Grade. À grade, adicionamos animações de página de transição, uma barra de aplicativos com comandos globais e contextuais, o controle SemanticZoom e itens de vários tamanhos. Explicamos a motivação por trás de cada adição e fornecemos orientação passo a passo sobre como adicionar o recurso ao modelo. Embora nosso foco seja o modelo Aplicativo de Grade, você também poderá aplicar muitas das lições disponibilizadas aqui ao modelo Aplicativo Dividido.

Introdução

Antes de iniciar este tutorial, conclua as seguintes etapas.

  1. Inicie o Visual Studio 2012 e escolha Arquivo > Novo Projeto.
  2. Crie um novo projeto JavaScript usando o modelo Aplicativo de Grade.

Adicionando animações de transição de página

Aplicativos com várias páginas devem animar as transições de páginas quando o usuário navega entre elas. Nesta seção, adicionamos animações de transição às páginas do modelo Aplicativo de Grade.

Motivação

A animação de página de entrada garante uma navegação rápida e fácil. Você deve incluir essas animações sempre que o usuário passa de uma página para outra.

Implementação

Em cada página do modelo, adicionamos uma função que retorna os elementos na página a ser animada, na ordem em que devem ser animados. Depois, adicionamos uma função ao Navigator.js, garantindo que o sistema chame as animações sempre que o usuário navega para uma página.

Para saber mais sobre animações de transição de página, consulte a amostra de biblioteca de animações HTML.

  1. No GroupedItems.js, adicione ao ui.Pages.define uma função que retorne uma matriz de elementos HTML. Essa função fornece o cabeçalho e a seção de página que contém o modo de exibição de grade.
    
    
    getAnimationElements: function () {
        return [[this.element.querySelector("header")], [this.element.querySelector("section")]];
    },
    
    

    Observação  Como mostra o exemplo anterior, é preciso adicionar uma vírgula ao final dessa função, a não ser que ela seja a última função da lista. Se for a última função, você precisará adicionar uma vírgula antes da função. A mesma regra se aplica às etapas a seguir.

  2. No GroupDetail.js, adicione ao ui.Pages.define uma função que retorne uma matriz de elementos HTML para animação.
    
    getAnimationElements: function () {
        return [[this.element.querySelector("header")], [this.element.querySelector("section")]];
    },
    
    
  3. No ItemDetail.js, adicione ao ui.Pages.define uma função que retorne uma matriz de elementos HTML para animação.
    
    getAnimationElements: function () {
        return [[this.element.querySelector("header")], [this.element.querySelector(".content")]];
    },
    
    
  4. No Navigator.js, adicione ao WinJS.Namespace.define uma função que tente recuperar os elementos em uma página para animação. Se a página não fornecer uma função para retornar uma matriz de elementos, toda a página será animada.
    
    _getAnimationElements: function () {
        if (this.pageControl && this.pageControl.getAnimationElements) {
            return this.pageControl.getAnimationElements();
        }
        return this.pageElement;
    },
    
    
  5. Para definir o foco correto da interface do usuário após a conclusão da animação, é preciso adicionar uma única função a cada página. Vamos chamar essa função depois que a animação de entrada for concluída.

    No GroupedItems.js, adicione ao ui.Pages.define uma função que defina o foco da interface do usuário para um controle na página.

    
    setPageFocus: function () {
        this.element.querySelector(".groupeditemslist").winControl.element.focus();
    },
    
    

    Observação  Como mostra o exemplo anterior, é preciso adicionar uma vírgula ao final dessa função, a não ser que ela seja a última função da lista. Se for a última função, você precisará adicionar uma vírgula antes da função. A mesma regra se aplica às etapas a seguir.

    No GroupDetail.js, adicione ao ui.Pages.define uma função que defina o foco da interface do usuário para um controle na página.

    
    setPageFocus: function () {
        this.element.querySelector(".itemslist").winControl.element.focus();
    },
    
    

    No ItemDetail.js, adicione ao ui.Pages.define uma função que defina o foco da interface do usuário para um controle na página.

    
    setPageFocus: function () {
        this.element.querySelector(".content").focus();
    },
    
    

    Atualize a função pronta em cada página (ItemDetail.js, GroupDetail.js e GroupedItems.js) para remover estas linhas:

    • GroupedItems.js: listView.element.focus();
    • GroupDetail.js: listView.element.focus();
    • ItemDetail.js: element.querySelector(".content").focus();
  6. Por fim, adicione a animação de página de entrada. No Navigator.js, adicione o seguinte código à parte superior da função navigated (e não _navigated) para definir as animações em movimento.
    
    
    navigated: function () {
        // Add the following two lines of code.
        var that = this;
        WinJS.UI.Animation.enterPage(that._getAnimationElements(), null).done(function () { 
            that.pageControl.setPageFocus.bind(that.pageControl); 
            });
    
        var backButton = this.pageElement.querySelector("header[role=banner] .win-backbutton");
    
        ...
    
    
    

Adicionar uma barra de aplicativos

Aqui, adicionamos uma barra de aplicativos contendo os comandos globais ou contextuais que podem ser convenientes ao usuário.

Motivação

Um dos princípios do estilo de design da Microsoft é "priorizar o conteúdo e não os elementos visuais". A ideia aqui é que menos é mais e que apenas os elementos mais relevantes devem aparecer na tela. Alinhados a esse princípio, os aplicativos do Windows 8 usam a barra de aplicativos – um controle comum, que permite colocar comandos relevantes e contextuais em um local de fácil acesso, mas fora da tela. Os comandos usados com frequência ficam próximos das bordas direita e esquerda, ao alcance da mão. A barra de aplicativos permite que, na superfície do aplicativo, se concentre o conteúdo em vez dos controles. Como a barra de aplicativos é usada em todo o sistema, os usuários terão facilidade para se acostumar com as interações da barra de aplicativos. Isso aumenta a usabilidade do aplicativo e torna todo o sistema mais coerente.

Na prática

O estudo de caso sobre o site para aplicativo da Windows Store mostra como os desenvolvedores podem repensar o suporte aos comandos, usando a barra de aplicativos. A seguir está um passo a passo sobre como carregar uma foto. À esquerda, você vê o passo sobre como isso é feito na Web. À direita está o cenário equivalente que usa o estilo de design da Microsoft.

Capturas de tela das etapas para carregar uma foto

No passo a passo anterior, o site mostra o comando para carregar suas fotos na página. Em contrapartida, o aplicativo da Windows Store usa a barra de aplicativos para mostrar a ação de carregar uma foto. Em seguida, o comando da barra de aplicativos abre o seletor de arquivos. Este é apenas um exemplo de como os aplicativos podem executar ações e colocá-las na barra de aplicativos para fazer mais com menos e priorizar o conteúdo em vez do cromado.

Diretrizes

Os comandos da barra de aplicativos podem variar, dependendo da página que está sendo visualizada ou do contexto do aplicativo. Os comandos globais aparecem quando o usuário navega para uma página; os comandos contextuais (ou seleção) aparecem quando determinados itens são selecionados. Vamos analisar os comandos contextuais em Tornando a grade selecionável e mostrando os comandos contextuais da barra de aplicativos.

Observação  Os comandos necessários à conclusão de um fluxo de trabalho, como envio de email ou compra de um produto, são uma exceção e podem ser colocados na tela.

Visão geral do exemplo

Nesta parte do tutorial, adicionamos uma barra de aplicativos à página Itens Agrupados e a página Detalhes do Item, do modelo Aplicativo de Grade. Adicionamos comandos que permitem alterar o tamanho dos rótulos na página Itens Agrupados e o tamanho do corpo de texto na página Detalhes do Item. Mostramos apenas os comandos que são relevantes à página que está sendo visualizada. Não mostraremos a barra de aplicativos na página Detalhes do Grupo.

Nesta captura de tela, a barra de aplicativos na página Itens Agrupados mostra o comando Aumentar tamanho do rótulo:

Captura de tela da página Itens Agrupados mostrando o comando Aumentar tamanho do rótulo, na barra de aplicativos

Esta captura de tela mostra a página Detalhes do Item com a barra de aplicativos exibindo o comando Aumentar tamanho do texto:

Captura de tela da página Detalhes do Item mostrando o comando Aumentar tamanho do texto, na barra de aplicativos

Implementação

Nas próximas etapas, vamos adicionar uma barra de aplicativos global com botões. Mostramos e ocultamos os botões nas funções prontas de cada página. Conectamos os comandos aos ouvintes de eventos que podem chamar os manipuladores de eventos para executar a funcionalidade descrita anteriormente. Desabilitamos a barra de aplicativos na página Detalhes do Grupo porque essa página não contém comandos para exibição.

  1. No Default.html, você encontrará uma barra de aplicativos do modelo, mas assinalada com comentários. Remova os comentários para fazer com que a barra de aplicativos faça parte do HTML.

  2. Os elementos div da barra de aplicativos contêm um botão de espaço reservado. Substitua-o pelos seguintes botões.

    
    <button id="labelSize" data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'labelSize', section:'global', label:'Label size', icon:'add'}"></button>
    <button id="textSize" data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'textSize', section:'global', label:'Text size', icon:'add'}"></button>
    
    
  3. No Default.js, adicione estes ouvintes de eventos.

    
    
    app.addEventListener("activated", function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize your 
                // application here.
    
                // Add the following two lines of code.									
                document.getElementById("labelSize").onclick = increaseLabelSize;
                document.getElementById("textSize").onclick = increaseTextSize;
            } else {
    
            ...
    
    
    
  4. No Default.js, adicione as seguintes funções ao lado das outras funções (com escopo no arquivo).

    
    function increaseLabelSize() {
        var titles = document.getElementsByClassName("item-title");
        var subtitles = document.getElementsByClassName("item-subtitle");
        var i;
        for (i = 0; i < titles.length; i++) {
            var prevTitleAttributes = titles[i].getAttribute("style");
            var prevSubtitleAttributes = subtitles[i].getAttribute("style");
            if (prevTitleAttributes != null)
                titles[i].setAttribute("style", prevTitleAttributes + "font-size:20px");
            else
                titles[i].setAttribute("style", "font-size:20px");
            if (prevSubtitleAttributes != null)
                subtitles[i].setAttribute("style", prevSubtitleAttributes + "font-size: 14px");
            else
                subtitles[i].setAttribute("style", "font-size: 14px");
        }
    };
    
    function increaseTextSize() {
        var content = document.getElementsByClassName("item-content");
        content[0].setAttribute("style", "font-size:20px");
    };
    
    
  5. Verifique se é possível mostrar somente os comandos relevantes em cada página.

    No GroupedItems.js, adicione o seguinte código à função ready:

    
    appbar.winControl.disabled = false;
    appbar.winControl.hideCommands([textSize]);
    appbar.winControl.showCommands([labelSize]);
    
    

    No GroupDetail.js, adicione a seguinte linha de código à função ready:

    
    appbar.winControl.disabled = true;
    
    

    No ItemDetail.js, adicione o seguinte código à função ready:

    
    appbar.winControl.disabled = false;
    appbar.winControl.hideCommands([labelSize]);
    appbar.winControl.showCommands([textSize]);
    
    

Tornando a grade selecionável e mostrando os comandos contextuais da barra de aplicativos

Aqui, adicionamos um ListView para permitir que o usuário selecione os itens com os quais deseja interagir. Para saber mais sobre o ListView, consulte o pacote de amostra ListView do HTML.

Motivação

Pode ser conveniente executar várias ações em um item do ListView. Dividimos as ações em uma ação primária e algumas ações secundárias. Para executar a ação primária, você toque ou clique em um item. Isso geralmente leva o usuário para o item.

O usuário então executa uma ação secundária selecionando um item e usando a barra de aplicativos para executar um comando no item. É possível executar várias ações secundárias em um item da grade, como excluir um item, adicioná-lo ao recurso Iniciar, defini-lo como favorito, marcar o item como lido, renomeá-lo etc. O usuário pode selecionar itens deslizando perpendicularmente na direção do movimento panorâmico, clicando com o botão direito do mouse ou pressionando a barra de espaço no teclado.

Na prática

O estudo de caso de aplicativo da Windows Store iPad para Windows 8 mostra como os aplicativos podem usar uma grade selecionável e uma barra de aplicativos para redefinir os comandos contextuais. Veja a seguir um passo a passo sobre como excluir fotos de um aplicativo de diário de fotos. À esquerda, você vê o passo sobre como isso é feito no iPad. À direita está o cenário equivalente que usa o estilo de design da Microsoft.

Capturas de tela das etapas para excluir fotos no iPad e em um aplicativo da Windows Store.

No aplicativo do iPad, o usuário primeiro entra no modo de seleção e então os comandos contextuais aparecem na parte superior da tela. No aplicativo da Windows Store, os comandos contextuais estão ocultos fora da tela na barra de aplicativos. Na etapa A, o usuário invoca a barra de aplicativos. Quando a barra de aplicativos é invocada pela primeira vez, nenhum item está selecionado na grade, portanto, apenas o comando global é mostrado. Na etapa B, o usuário começa a selecionar itens na grade, o que mostra os comandos contextuais na parte esquerda da barra de aplicativos.

Descrição

Quando um item é selecionado, a barra de aplicativos é invocada para mostrar os comandos que são contextuais ao item selecionado. Quando vários itens são selecionados, a barra de aplicativos permanece ativada e mostra os comandos que são contextuais a todos os itens selecionados. Se o usuário desmarcar itens, quando o último item for desmarcado, a barra de aplicativos ficará oculta.

Quando a barra de aplicativos é exibida com os comandos contextuais, os comandos globais ficam sempre visíveis. Os comandos globais ficam alinhados à direita da barra de aplicativos e os comandos contextuais, alinhados à esquerda.

É possível estipular a seleção de um único item ou de vários itens de uma só vez.

Quando um aplicativo é ajustado, ele deve manter o máximo de estado possível. Se a barra de aplicativos estiver ativada e o aplicativo for ajustado, a barra de aplicativos deverá permanecer ativada. Se um item for selecionado e o aplicativo for ajustado, o item deverá permanecer selecionado, quando possível.

Entretanto, ao ajustar a página Itens Agrupados, o modo de exibição ajustado mostra a exibição reduzida dos grupos. Como resultado, não é possível mostrar a seleção de cada item quando aplicativo tem o estado ajustado. Como não é possível mostrar os itens individuais, qualquer comando contextual de itens selecionados anteriormente ficará oculto.

Visão geral do exemplo

Nesta seção do tutorial, tornamos os itens da grade selecionáveis. Isso permite a seleção de vários itens de uma só vez. Após a seleção de um item, a barra de aplicativos é imediatamente invocada e aparece o comando contextual para marcar o item como lido. O título de todos os itens selecionados adquirem a cor cinza. Quando os itens são desmarcados, a barra de aplicativos fica oculta. Se você optar por marcar os itens como lidos, isso executará a ação, desmarcará os itens e ocultará a barra de aplicativos.

Esta captura de tela mostra a página Itens Agrupados com vários itens selecionados e uma barra de aplicativos mostrando o comando contextual Marcar como lido e o comando global Aumentar tamanho do rótulo:

Captura de tela mostrando a página Itens Agrupados com vários itens selecionados e uma barra de aplicativos mostrando um comando contextual e um comando global

Implementação

Nas próximas etapas, habilitaremos a seleção de itens de grade. Também adicionaremos um ouvinte de eventos que exibe uma barra de aplicativos contendo comandos contextuais para o item selecionado.

  1. No GroupedItems.html, para tornar os itens de GridView selecionáveis, mude o modo de seleção do ListView de 'none' para 'multi'.

    
    data-win-options="{ selectionMode: 'multi' }"
    
    
    
  2. No Default.html, adicione o seguinte comando contextual da barra de aplicativos ao lado dos demais comandos da barra de aplicativos.

    
    <button id="markItem" data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'markItem', section:'selection', label:'Mark as read', icon:'accept'}"></button>
    
    
  3. No Default.js, adicione os seguintes ouvintes de eventos ao lado dos outros ouvintes de eventos da barra de aplicativos, no manipulador app.onactivated.

    
    document.getElementById("markItem").onclick = markItem;
    
    
  4. No Default.js, adicione a função markItem ao lado das outras funções de comando da barra de aplicativos.

    
    function markItem() {
        var titles = document.getElementsByClassName("item-title");
        var subtitles = document.getElementsByClassName("item-subtitle");
        var listView = document.querySelector(".groupeditemslist").winControl;
        var items = listView.selection.getItems();
        var i;
        for (i = 0; i < items._value.length; i++) {
            var key = parseFloat(items._value[i].key);
            if (titles[0].innerHTML != "") {
                if (key == 0) continue;
                key--;
            }
            var prevTitleAttributes = titles[key].getAttribute("style");
            var prevSubtitleAttributes = subtitles[key].getAttribute("style");
            if (prevTitleAttributes != null)
                titles[key].setAttribute("style", prevTitleAttributes + "color:gray");
            else
                titles[key].setAttribute("style", "color:gray");
    
            if (prevSubtitleAttributes != null)
                subtitles[key].setAttribute("style", prevSubtitleAttributes + "color:gray");
            else
                subtitles[key].setAttribute("style", "color:gray");
        }
        listView.selection.clear();
    }
    
    
  5. No ItemDetail.js, modifique a chamada da função hideCommands para ocultar também o botão Marcar Item.

    
    appbar.winControl.hideCommands([labelSize, markItem]);
    
    
  6. No GroupedItems.js, modifique a chamada da função hideCommands para ocultar também o botão Marcar Item.

    
    appbar.winControl.hideCommands([textSize, markItem]);
    
    
  7. No GroupedItems.js, adicione as seguintes funções antes da função ui.Pages.define: Essas funções mostram e ocultam a barra de ferramentas, de forma programática.

    
    function showAppBar(currentItem) {
        // Get the app bar.
        var element = document.activeElement;
        var appbar = document.getElementById("appbar");
        
        // Keep the app bar open after it's shown.
        appbar.winControl.sticky = true;
     
        // Set the app bar context.
        showItemCommands();
    
        // Show the app bar.
        appbar.winControl.show();
    
        // Return focus to the original item which invoked the app bar.
        if (element != null) element.focus();
    }
    
    function hideAppBar() {
        var element = document.activeElement;
        var appbar = document.getElementById("appbar");
        appbar.winControl.sticky = false;
        appbar.winControl.hide();
        hideItemCommands();
        if (element != null) element.focus();
    }
    
    
  8. No GroupedItems.js, adicione as seguintes funções ao lado das funções precedentes. Essas funções mostram e ocultam os comandos da barra de aplicativos.

    
    function showItemCommands() {
        appbar.winControl.showCommands([markItem]);
    }
    
    function hideItemCommands() {
        appbar.winControl.hideCommands([markItem]);
    }
    
    
  9. No GroupedItems.js, adicione código para abrir e fechar a barra de aplicativos de maneira programática. Na função ready, adicione um manipulador de eventos de alteração de seleção para os dois ListViews na página.

    
    listView.onselectionchanged = this.itemSelected.bind(this);
    
    
  10. No GroupedItems.js, adicione as seguintes funções para manipular a seleção no ListView.

    
    itemSelected: function (eventObject) {
        var listView = document.querySelector(".groupeditemslist").winControl;
    
        // Check for selection.
        if (listView.selection.count() === 0) {
            hideAppBar();
        } else {
            listView.selection.getItems().then(function (items) {
                showAppBar(items[0]);
           	});
        }
    },
    
    
  11. No GroupedItems.js, adicione uma chamada para a função hideItemCommands em updateLayout. Essa chamada oculta o comando contextual na barra de aplicativos quando o aplicativo é ajustado. O comando contextual não deve aparecer quando o aplicativo é ajustado porque o item não é mostrado como selecionado no estado ajustado.

    
    updateLayout: function (element, viewState, lastViewState) {
        /// <param name="element" domElement="true" />
        /// <param name="viewState" value="Windows.UI.ViewManagement.ApplicationViewState" />
        /// <param name="lastViewState" value="Windows.UI.ViewManagement.ApplicationViewState" />
    
        var listView = element.querySelector(".groupeditemslist").winControl;
        if (lastViewState !== viewState) {
            if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
                var handler = function (e) {
                    listView.removeEventListener("contentanimating", handler, false);
                    e.preventDefault();
                }
            listView.addEventListener("contentanimating", handler, false);
    
            // Add the following five lines of code.        
            this.initializeLayout(listView, viewState);
            hideItemCommands();
            if (viewState === appViewState.snapped)
                listView.selectionMode = "none";
            else
                listView.selectionMode = "multi";
            }
        }
    }
    
    

Adicionando o controle SemanticZoom

Nesta seção, adicionamos um controle SemanticZoom para fornecer uma exibição semântica dos itens na grade ListView. Cada item no modo de exibição reduzido corresponde a um grupo de itens na grade.

Captura de tela mostrando itens na grade ListView

Para saber mais sobre o Zoom Semântico, consulte a a amostra de SemanticZoom e agrupamento ListView do HTML.

Motivação

O modelo Aplicativo de Grade usa um padrão de navegação hierárquica. Isso significa que o conteúdo interessante de cada seção principal de um aplicativo pode ser promovido na página de aterrissagem. É possível ampliar essa página de aterrissagem com um grande número de grupos ou de itens. Embora seja possível usar o movimento panorâmico no modo de exibição para navegar pelo conteúdo, considere a adição do Zoom Semântico para permitir que o usuário vá rapidamente para outras seções da página.

O controle SemanticZoom permite reduzir a grade em uma exibição semântica, em vez de óptica, dos grupos. Nesse modo de exibição, o usuário pode selecionar um grupo para ampliá-lo. Com o Zoom Semântico, é possível exibir grupos grandes de itens sem o uso da panorâmica. O recurso também proporciona uma exibição global dos grupos na grade.

A exibição reduzida pode ainda fornecer informações meta dos grupos, para direcionar o usuário para as seções interessantes na página. Por exemplo, a exibição reduzida pode mostrar o número de itens do grupo que tem uma sobreposição de número.

Na prática

O estudo de caso de aplicativo da Windows Store iPad para Windows 8 mostra como os aplicativos podem usar o Zoom Semântico para permitir que o usuário se movimente rapidamente entre os grupos de itens. Veja a seguir um passo a passo sobre como usar o Zoom Semântico para apresentar uma exibição semântica de grupos. À esquerda, você vê o passo sobre como isso é feito no iPad. À direita está o cenário equivalente que usa o estilo de design da Microsoft.

Captura de tela mostrando como o Zoom Semântico se compara ao iPad quando o assunto é se movimentar entre os grupos de itens

No aplicativo do iPad, é possível tocar no botão Anos, na barra de navegação superior, para mostrar um menu pop-up com uma lista de anos. No aplicativo da Windows Store, o usuário pode usar um gesto de pinçagem para usar o Zoom Semântico para reduzir nos grupos. Neste exemplo, a exibição semântica foi configurada para mostrar o número de comentários no grupo Comentários e para indicar quantos meses têm fotos.

Implementação

Nas etapas a seguir, adicionamos o contêiner Zoom Semântico à página Itens Agrupados e acrescentamos um modelo aos grupos Zoom Semântico.

Conectamos os grupos semânticos à fonte de dados do grupo e, depois, aplicamos CSS (Folhas de Estilo em Cascata) para estilizar os grupos adequadamente.

  1. No GroupedItems.html, localize o controle ListView na seção de conteúdo principal:

    
    <section aria-label="Main content" role="main">
        <div class="groupeditemslist" aria-label="List of groups" data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'multi' }"></div>
    </section>
    
    

    Na sua concepção mais básica, o controle SemanticZoom é um contêiner que exibe um de seus elementos filho, dependendo do atual fator de escala. Aqui, vamos adicionar um controle SemanticZoom como a "raiz" da seção e colocar dois controles ListView no controle SemanticZoom.

    Primeiro, altere a seção de conteúdo principal da seguinte maneira:

    
    <section aria-label="Main content" role="main">
        <div class="sezoDiv" data-win-control="WinJS.UI.SemanticZoom" data-win-options="{ zoomFactor: 0.5, initiallyZoomedOut: false }">
            <div class="groupeditemslist" aria-label="List of groups" data-win-control="WinJS.UI.ListView" data-win-options="{selectionMode: 'multi'}"></div>
            <div class="groupeditemslistZoomOut groupeditemslist" aria-label="List of groups" data-win-control="WinJS.UI.ListView" data-win-options="{selectionMode: 'none'}"></div>
        </div>
    </section>
    
    
    
    • Agora que configuramos os controles na página, vamos adicionar código para garantir que o conteúdo correto seja exibido.

      No GroupedItems.js, faça as seguintes adições e alterações à função ready. Em essência, simplesmente duplicamos o que já existia no primeiro modo de exibição de lista e aplicamos no novo ListView reduzido.

      
      ready: function (element, options) {
          var listView = element.querySelector(".groupeditemslist").winControl;
      
          // Add the following two lines of code.
          var listViewZoomOut = element.querySelector(".groupeditemslistZoomOut").winControl;
          var semanticZoom = element.querySelector(".sezoDiv").winControl;
      
          listView.groupHeaderTemplate = element.querySelector(".headerTemplate");
          listView.itemTemplate = element.querySelector(".itemtemplate");
      
          // Add the following line of code.
          listViewZoomOut.itemTemplate = element.querySelector(".itemtemplate");
      
          listView.oniteminvoked = this.itemInvoked.bind(this);
      
          // Add the following line of code.
          listViewZoomOut.oniteminvoked = this.groupInvoked.bind(this)
      
          // Change the second and third parameters of the following call as shown.
          this.initializeLayout(listView,listViewZoomOut, semanticZoom, appView.value);
      },
      
      
  2. No GroupedItems.js, atualize a função inializeLayout para aceitar o segundo modo de exibição de lista. A função também manipula o controle de zoom semântico no modo de exibição ajustado.
    
    
    // Add the listViewZoomOut and semanticZoom parameters as shown.
    initializeLayout: function (listView, listViewZoomOut, semanticZoom, viewState) {
        /// <param name="listView" value="WinJS.UI.ListView.prototype" />
    
        if (viewState === appViewState.snapped) {
            listView.itemDataSource = Data.groups.dataSource;
            listView.groupDataSource = null;
            listView.layout = new ui.ListLayout();
    
            // Add the following three lines of code.
            semanticZoom.zoomedOut = false;
            semanticZoom.forceLayout();
            semanticZoom.locked = true;
        } else {
            listView.itemDataSource = Data.items.dataSource;
            listView.groupDataSource = Data.groups.dataSource;
            listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
    
            // Add the following four lines of code.
            listViewZoomOut.itemDataSource = Data.groups.dataSource;
            listViewZoomOut.layout = new ui.GridLayout({ maxRows: 1 });
            semanticZoom.forceLayout();
            semanticZoom.locked = false;
        }
    },
    
    
  3. No GroupedItems.js, atualize a função updateLayout para configurar o novo ListView, de modo que ele exiba a lista de grupos usando a fonte de dados agrupados.

    
    updateLayout: function (element, viewState, lastViewState) {
        /// <param name="element" domElement="true" />
        /// <param name="viewState" value="Windows.UI.ViewManagement.ApplicationViewState" />
        /// <param name="lastViewState" value="Windows.UI.ViewManagement.ApplicationViewState" />
        var listView = element.querySelector(".groupeditemslist").winControl;
    
        // Add the following two lines of code.
        var listViewZoomOut = element.querySelector(".groupeditemslistZoomOut").winControl;
        var semanticZoom = element.querySelector(".sezoDiv").winControl;
    
        if (lastViewState !== viewState) {
            if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
                var handler = function (e) {
                    listView.removeEventListener("contentanimating", handler, false);
                        e.preventDefault();
                }
                listView.addEventListener("contentanimating", handler, false);
    
                // Add the listViewZoomOut and semanticZoom parameters as shown.
                this.initializeLayout(listView, listViewZoomOut, semanticZoom, viewState);
            }
    
            // Add the following four lines of code.
            if (lastViewState === appViewState.snapped) {
                semanticZoom.zoomedOut = true;
                semanticZoom.forceLayout();
            }
        }
    },
    
    
  4. No GroupedItems.js, adicione a seguinte função para lidar com as situações em que o usuário toque ou clica em um item no modo de exibição reduzido.

    
    groupInvoked: function (args) {
       	var group = Data.groups.getAt(args.detail.itemIndex);
        nav.navigate("/pages/groupDetail/groupDetail.html", { groupKey: group.key });
    },
    
    
  5. Agora, este é o momento de adicionar CSS para dar aos itens uma boa aparência.

    Observação  Para implementar as diretrizes da experiência do usuário para o Zoom Semântico, usamos uma grade CSS com apenas uma linha e coluna. Colocamos o cabeçalho e o conteúdo da seção nessa grade, para que possam ser sobrepostos. Isso significa que o controle SemanticZoom pode cobrir toda a tela, incluindo a página de cabeçalho.

    No GroupedItems.css, adicione os seguintes estilos para fazer com que o controle SemanticZoom ocupe o espaço disponível na tela. Isso altera o layout do fragmento geral, permitindo que o conteúdo da página de cabeçalho seja posicionado sob o conteúdo da seção que contém o sezo div.

    
    .groupeditemspage {
        /* Change the display type to have only one row */
        -ms-grid-rows: 1fr;
        display: -ms-grid;
        height: 100%;
        width: 100%;
    }
    
        .groupeditemspage header[role=banner] {
            /* Position this at the top of the screen */
            -ms-grid-row: 1;    
            -ms-grid-columns: 120px 1fr;
            display: -ms-grid;
        }
    
        .groupeditemspage section[role=main] {
            /* Position this at the top of the screen */
            -ms-grid-row: 1;
            height: 100%;
            width: 100%;
        }
    
    .sezoDiv
     {
        height: 100%;
        width: 100%;
    }
    
    
  6. A seguir, precisa resolver alguns problemas que ocorrem porque o controle SemanticZoom foi posicionado com uma margem negativa.

    Para ver o cabeçalho da página, mova o modo de exibição de lista 133 pixels para baixo.

    
    .groupeditemspage .groupeditemslist .win-horizontal.win-viewport .win-surface {
        margin-left: 45px;
        /* Add the following line. */
        margin-top: 133px;
        margin-bottom: 60px;
    }
    
    /* Add the following lines near the end of the CSS file. */
    .groupeditemspage .groupeditemslistZoomOut .win-horizontal.win-viewport .win-surface {
        margin-left: 116px;
        margin-top: 133px;
    }
    
    
  7. Agora, é preciso estilizar o item para mostrá-lo no modo de exibição reduzido. Adicione o seguinte código CSS, mas não se esqueça de declará-lo após o estilo groupeditemslist.win-item, que já faz parte do arquivo:

    
    
        .groupeditemspage .groupeditemslistZoomOut .win-item {
            -ms-grid-columns: 1fr;   
            -ms-grid-rows: 1fr 90px;
            display: -ms-grid;
            height: 250px;
            width: 250px;
        }
    .groupeditemspage .groupeditemslistZoomOut .win-item {
        -ms-grid-rows: 1fr 180px;
        display: -ms-grid;
        height: 580px;
        width: 250px;
    }
    
    
  8. Vamos corrigir os modos de exibição ajustado e retrato porque será necessário fazer alterações que irão afetá-los. Adicione todos os estilos a seguir à seção @media screen and (-ms-view-state: snapped) do GroupedItems.css.

    Adicione o estilo a seguir para realinhar a seção de cabeçalho.

    
    .groupeditemspage header[role=banner] {
        -ms-grid-columns: auto 1fr;
        margin-left: 20px;
    }
    
    

    Adicione uma margem à parte superior da superfície para que a lista não cubra o título.

    
    .groupeditemspage .groupeditemslist .win-vertical.win-viewport .win-surface {
        margin-bottom: 30px;
        /* Add the following line. */
        margin-top: 133px;
        margin-left: 6px;
    }
    
    
  9. Agora, os problemas do modo de exibição ajustado estão corrigidos. Depois disso, é preciso atualizar o modo de exibição retrato.

    No GroupedItems.css, adicione os seguintes estilos à seção @media screen and (-ms-view-state: fullscreen-portrait).

    
    
    .groupeditemspage .groupeditemslistZoomOut .win-horizontal.win-viewport .win-surface {
        margin-left: 96px;
    }
    
    

Apresentando itens de vários tamanhos na grade

A apresentação de uma grade contendo itens de vários tamanhos é uma boa maneira de personalizar a grade e criar um diferencial para o aplicativo. Com itens de vários tamanhos, um aplicativo pode enfatizar alguns itens e reduzir a ênfase de outros, selecionando os tamanhos maiores para os itens mais importantes.

Itens de diferentes tamanhos também podem usar diferentes modelos. Por exemplo, para os itens maiores, pode ser interessante mostrar imagens com um texto sobreposto; e para os itens menores, somente texto.

Na prática

O estudo de caso de aplicativo da Windows Store iPad para Windows 8 mostra como os aplicativos podem usar itens de vários tamanhos e diversos modelos para personalizar o modelo de grade e criar uma identidade visual para o aplicativo. Os seguintes exemplos comparam uma página de aterrissagem de um aplicativo de iPad e uma página de aterrissagem de um aplicativo da Windows Store que personalizaram o modelo de grade.

Capturas de tela comparando páginas de aterrissagem de iPad e do aplicativo da Windows Store

No aplicativo de iPad, todo o conteúdo é apresentado em uma grade uniforme de imagens. No aplicativo da Windows Store, os itens são apresentados em vários tamanhos e com diferentes modelos. O primeiro grupo contém itens com imagens pequenas e texto descritivo lado a lado. O restante dos grupos consistem em imagens grandes e pequenas sobrepostas a texto de vários tamanhos.

Visão geral do exemplo

O exemplo desta seção personaliza a grade na página Itens Agrupados para usar itens de três tamanhos. A grade padrão usa itens de 200 por 200 pixels. Vamos usar itens com 310 por 310 pixels, 310 por 150 pixels e 150 por 150 pixels. Os itens maiores usarão a imagem padrão e o layout de sobreposição de texto e os itens menores conterão somente texto.

Aqui está a página Itens Agrupados com três tamanhos de item:

Captura de tela da página Itens Agrupados mostrando os três tamanhos de item

Implementação

Para conseguir a experiência do usuário desejada para esse cenário, precisamos definir nossa própria função de renderização do modo de exibição de lista. Precisamos também adicionar uma CSS aos itens de diferentes tamanhos.

Para a função de renderização, escrevemos em um modelo HTML predefinido em vez de criar um manualmente na função, mas as duas abordagens são adequadas.

Ao selecionar vários tamanhos de itens, lembre-se de que os tamanhos precisam cumprir esta fórmula: itemSize = ((slotSize + margin) x multiplier) – margin.

  1. No GroupedItems.html, adicione o modelo de item a seguir.

    
    <div class="multisizebaseitemtemplate" data-win-control="WinJS.Binding.Template">
        <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
        <div class="item-overlay">
            <h4 class="item-title" data-win-bind="textContent: title"></h4>
            <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
        </div>
    </div>
    
    
  2. No GroupedItems.js, adicione esta função antes da definição de página (ui.Pages.define).

    
    function multisizeItemTemplateRenderer(itemPromise) {
        return itemPromise.then(function (currentItem) {
            var content;
            // Grab the default item template used on the groupeditems page.
            content = document.getElementsByClassName("multisizebaseitemtemplate")[0];
            var result = content.cloneNode(true);
    
            // Change the CSS class of the item depending on the group, then set the size in CSS.
            switch (currentItem.groupKey) {
                case "group1":
                    {
                        // For the first item, use the largest template.
                        if (currentItem.index == 0) {
                            result.className = "largeitemtemplate"
                        }
                        else {
                            result.className = "mediumitemtemplate"
                        }
                        break;
                    }
                case "group2":
                    {
                        result.className = "mediumitemtemplate"
                        break;
                    }
                default:
                    {
                        result.className = "smallitemtemplate"
                    }
            }
            // Because we used a WinJS template, we need to strip off some attributes 
            // for it to render.
            result.attributes.removeNamedItem("data-win-control");
            result.attributes.removeNamedItem("style");
            result.style.overflow = "hidden";
    
            // Because we're doing the rendering, we need to put the data into the item.
            // We can't use databinding.
            result.getElementsByClassName("item-image")[0].src = currentItem.data.backgroundImage;
            result.getElementsByClassName("item-title")[0].textContent = currentItem.data.title;
            result.getElementsByClassName("item-subtitle")[0].textContent = currentItem.data.subtitle;
            return result;
        });
    }
    
    
  3. No GroupedItems.js, adicione a função groupInfo abaixo, também fora da definição de página. Essa função diz ao ListView que ele deve exibir itens de vários tamanhos e indica o "tamanho base" dos itens. O tamanho base é o menor item mostrado na lista. Os demais itens deverão ser múltiplos desse tamanho para que os layouts funcionem corretamente.

    
    function groupInfo() {
        return {
            enableCellSpanning: true,
            cellWidth: 150,
            cellHeight: 150
        };
    }
    
    
  4. Agora, é preciso conectar essas novas funções com os controles do ListView na página Itens Agrupados. Como não queremos usar imagens de tamanhos variáveis no modo de exibição ajustado, precisamos alterar a função ready e a função updateLayout.

    No GroupedItems.js, altere a função initializeLayout de modo que, quando a página estiver no modo de exibição ajustado, seja exibida uma lista plana de grupos. No modo de exibição paisagem, porém, usamos itens de vários tamanhos.

    
    
    // Add the itemTemplate parameter as shown.
    initializeLayout: function (listView, listViewZoomOut, semanticZoom, viewState, itemTemplate) {
        /// <param name="listView" value="WinJS.UI.ListView.prototype" />
    
        if (viewState === appViewState.snapped) {
            listView.itemDataSource = Data.groups.dataSource;
            listView.groupDataSource = null;
    
            // Add the followign line of code.
            listView.itemTemplate = itemTemplate;
    
            listView.layout = new ui.ListLayout();
            semanticZoom.zoomedOut = false;
            semanticZoom.forceLayout();
            semanticZoom.locked = true;
        } else {
            listView.itemDataSource = Data.items.dataSource;
            listView.groupDataSource = Data.groups.dataSource;
    
            // Add the following two lines of code.
            listView.itemTemplate = multisizeItemTemplateRenderer;
            listView.layout = new ui.GridLayout({ groupInfo: groupInfo, groupHeaderPosition: "top" });
    
            listViewZoomOut.itemDataSource = Data.groups.dataSource;
            listViewZoomOut.layout = new ui.GridLayout({ maxRows: 1 });
            semanticZoom.forceLayout();
            semanticZoom.locked = false;
        }
    },
    
    

    Remova a linha que atribui um modelo de item ao ListView e faça as alterações indicadas pelos comentários deste código.

    
    ready: function (element, options) {
        var listView = element.querySelector(".groupeditemslist").winControl;
        var listViewZoomOut = element.querySelector(".groupeditemslistZoomOut").winControl;
        var semanticZoom = element.querySelector(".sezoDiv").winControl;
    
        // Add the following line of code.
        var itemTemplate = element.querySelector(".itemtemplate");
    
        listView.groupHeaderTemplate = element.querySelector(".headerTemplate");
    
        listView.oniteminvoked = this.itemInvoked.bind(this);
        listViewZoomOut.itemTemplate = element.querySelector(".itemtemplate");
        listViewZoomOut.oniteminvoked = this.groupInvoked.bind(this)
    
        // Change the last argument of the following function to itemTemplate.
        this.initializeLayout(listView,listViewZoomOut, semanticZoom, appView.value, itemTemplate);
        listView.element.focus();
     },
    
    // This function updates the page layout in response to viewState changes.
    updateLayout: function (element, viewState, lastViewState) {
        /// <param name="element" domElement="true" />
        /// <param name="viewState" value="Windows.UI.ViewManagement.ApplicationViewState" />
        /// <param name="lastViewState" value="Windows.UI.ViewManagement.ApplicationViewState" />
        var listView = element.querySelector(".groupeditemslist").winControl;
        var listViewZoomOut = element.querySelector(".groupeditemslistZoomOut").winControl;
        var semanticZoom = element.querySelector(".sezoDiv").winControl;
    
        // Add the following line of code.
        var itemTemplate = element.querySelector(".itemtemplate");
    
        if (lastViewState !== viewState) {
            if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
                var handler = function (e) {
                    listView.removeEventListener("contentanimating", handler, false);
                    e.preventDefault();
                }
                listView.addEventListener("contentanimating", handler, false);
    
                // Change this line to pass through the item template.
                this.initializeLayout(listView, listViewZoomOut, semanticZoom,viewState,itemTemplate);
            }
            if (lastViewState === appViewState.snapped) {
                semanticZoom.zoomedOut = true;
                semanticZoom.forceLayout();
            }
        }
    },
    
    
  5. O código dessa área agora está finalizado. Em seguida, precisamos adicionar estilo aos itens.

    No GroupedItems.css, adicione os seguintes estilos aos modelos de item pequeno, médio e grande.

    
    
    .groupeditemspage .smallitemtemplate
    {
        width: 150px;
        height: 150px;
        overflow: hidden;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 0px 1fr;
        display: -ms-grid;
    }
    .smallitemtemplate .item-overlay .item-title {
        position: absolute; 
        padding-right: 6px;
        bottom: 10px; 
        font-size: 16pt;
    }
    .smallitemtemplate .item-overlay .item-subtitle {
        display: none;
    }
    .groupeditemspage .mediumitemtemplate
    {
        width: 310px;
        height: 150px;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 60px;
        display: -ms-grid;
        overflow: hidden;
    }       
    .groupeditemspage .largeitemtemplate
    {
        width: 310px;
        height: 310px;
        overflow: hidden;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 90px;
        display: -ms-grid;
    }
    
    
    
  6. Remova este código de CSS para impedi-lo de substituir nosso estilo.

    
    .groupeditemspage .groupeditemslistZoomOut .win-item {
        -ns-grid-columns: 1fr;
        -ms-grid-rows: 1fr 90px;
        display: -ms-grid;
        height: 250px;
        width: 250px;
    }
    
    

    Observação  Se não tiver implementado a seção Zoom Semântico, exclua do arquivo a CSS acima para impedi-la de substituir a CSS que acabamos de adicionar aos itens de vários tamanhos.

 

 

Mostrar:
© 2014 Microsoft. Todos os direitos reservados.