如何設計您的 ListView 商標

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

我們已在設計 Windows 市集應用程式的商標中說明如何在遵守 Microsoft 設計原則的同時,在您的應用程式中併入商標的要素。 我們已探討七個品牌設計的層面:色彩、圖示、影像、格線、配置、標誌以及印刷格式。

本文將說明如何使用下列技術來自訂應用程式的登陸頁面:

本主題將教您如何從 Visual Studio [格線應用程式] 範本開始,然後加以修改來建立下列登陸頁面:

Contoso Bakery 登陸頁面

Contoso Food Truck 範例

先決條件

何時使用 ListView

您首先要決定的是要在登陸頁面使用哪些控制項。 如需 HTML 和 JavaScript 適用的 Windows Library 控制項清單,請參閱控制項清單

如果想要以一系列項目的形式顯示資料集合,例如電子郵件清單、搜尋結果或意欲購買的項目型錄,請使用 ListView

ListView 會以清單或格線配置來顯示項目。 大部分顯示項目的登陸頁面都使用 ListView 控制項的格線配置,因為此配置會自動溢位和水平捲動。 您可以修改用來顯示項目的 itemTemplate,以自訂 ListView 中的項目。

CSS3 格線配置和 Windows 8 格線系統

格線系統是 Windows 8 外觀及操作方式的一個重要部分,可協助在不同的應用程式與功能之間保持視覺統一性。 您可以使用格線配置劃分頁面上元素的空間,並且輕鬆地讓元素對齊格線。

我們也在範例中使用階層式樣式表層級 3 (CSS3) 格線配置,這與 ListView 控制項的格線配置不同。 CSS3 格線配置為廣大的使用者提供一般用途的格線樣式設定,而 ListView 只是用於顯示資料集合。您可以使用 CSS3 格線配置俐落地配置應用程式,並且輕鬆地讓元素對齊格線。

Contoso French Bakery 範例

現在看看預設的 Visual Studio Grid App 範本,並與設計 Windows 市集應用程式的商標中的 Contoso French Bakery 範例做比較。 以下為 Grid App 範本的螢幕擷取畫面:

使用「格線應用程式」範本的應用程式

讓我們將此與設計 Windows 市集應用程式的商標中的 Contoso French Bakery 登陸頁面做比較。 Contoso French Bakery 以強調 Contoso 品牌的自訂方式來配置其項目。

Contoso Bakery 登陸頁面

Contoso French Bakery 登陸頁面看起來就與 Grid App 範本非常不同,但不同之處只是修改了一些 HTML/CSS。 在這個範例中,我們假設項目為互動式,使用者選取某個項目後就會被帶到其中有馬卡龍、杯子蛋糕等選項類型的群組詳細資料頁面。 使用格線配置的 ListView 為適合這個登陸頁面的控制項。

若要將 Grid App 範本轉換成為 Contoso 登陸頁面,我們需要變更項目範本的大小、增加影像大小以及增加項目描述。

  1. 在 Visual Studio 中,建立一個使用 Grid App 範本的新應用程式。

  2. 更新 groupedItems.html 中的 HTML itemtemplate。 預設 itemtemplate 的主要變更是增加了第三個標題元素,以顯示每個項目描述。

        <div class="itemtemplate" data-win-control="WinJS.Binding.Template">
            <div class="item">
                <img class="item-image" src="#" 
                     data-win-bind="src: backgroundImage; alt: title" />
                <div class="item-text">
                    <h3 class="item-title" data-win-bind="textContent: title"></h3>
                    <h6 class="item-subtitle win-type-ellipsis" 
                        data-win-bind="textContent: subtitle"></h6>
                    <h6 class="item-detail" data-win-bind="textContent: description"></h6>
                </div>
            </div>
        </div>
    
  3. 現在我們更新 groupedItems.css 中的樣式。groupedItems.css 的主要變更是將文字 div 移到影像下方,而不是重疊在影像上方,以及在格線新增另一個項目詳細資料元素列。

    .groupeditemspage .groupeditemslist .win-horizontal.win-viewport .win-surface {
            margin-bottom: 60px;
            /* Decreased margin */
            margin-left: 35px;
            margin-right: 115px;
    }   
    .groupeditemspage .groupeditemslist .item {
           /* Changed row size and item size, centered text and changed text color */ 
            -ms-grid-columns: 1fr;
            -ms-grid-rows: 1fr 1280px;
            display: -ms-grid;
            height: 600px500px;
            width: 350px;
            text-align: center;
            color: rgb(160,160,160);
    
        }
    
            .groupeditemspage .groupeditemslist .item .item-image {
                   /* Increased image size and altered padding */
                height: 340px;
                width: 340px;
                padding: 0px 5px 20px 5px;
            }
    
            .groupeditemspage .groupeditemslist .item .item-text {
                /* Added a row to the grid and changed height and padding */
                -ms-grid-row: 2;
                -ms-grid-rows: 30px 21px 1fr;
                display: -ms-grid;
                padding: 30px 15px 2px 15px;
                height: 150px;
            }
    
                .groupeditemspage .groupeditemslist .item .item-text .item-title {
                    /* Changed font color */
                    -ms-grid-row: 1;
                    overflow: hidden;
                    font-size: 16pt;
                    color: rgb(200,200,200);
                }
    
                .groupeditemspage .groupeditemslist .item .item-text .item-subtitle {
                    -ms-grid-row: 2;
                }
                .groupeditemspage .groupeditemslist .item .item-text .item-detail {
                    /* All new CSS for the detail text */
                    -ms-grid-row: 3;
                    overflow:hidden;
                    padding-top: 20px;
                    height: 60px;
                    margin-left: 30px;
                    margin-right: 30px;
                }
    
  4. 移除 data.js 的群組標頭。 (最簡單的方法是直接刪除每個群組的標題)。

做了上述變更之後,您的應用程式現在看起來會像這樣:

更新過的應用程式

增加了一些影像並且變更背景與標題,就完成了建立 Contoso French Bakery 登陸頁面!

Contoso Food Truck 範例

在下一個範例中,我們將從 Grid App 範本建立 Contoso Food Truck 登陸頁面。

Contoso Food Truck 範例

Contoso Food Truck 登陸頁面主要以各種不同大小且引人注目的影像來吸引使用者。

與先前的範例不一樣,這個登陸頁面需要在範本增加一些 JavaScript,主要為增加讓 ListView 中的項目能有不同大小的邏輯。 我們同樣假設登陸頁面中的是互動式項目,而且選擇一個項目就會將使用者帶到該項目的詳細資料檢視。 使用格線配置的 ListView 為用來執行此工作的正確工具。 我們再次使用 Grid App 範本作為起點。

若要使用多重大小的項目,我們必須先決定最小的基本單位。 我們將使用這個單位來建立所有格線項目,而且所有格線項目都必須是這個格線大小的倍數。 下一個影像中之其中一個項目的最小尺寸是 “Near Me” 區段中項目的高度 (約為 80px)。 水平維度更具有彈性。 為了簡單起見,水平維度也是 80px。

這個影像顯示基本單位 (紅色方塊) 與數個實際項目的外觀比較。

基本項目大小

計算項目大小時,每個項目的大小均必須等於基本單位的倍數加上單位之間的邊框距離。 公式如下:

item sizeₓ = m * base unit sizeₓ + (m -1) * item padding

item sizey = m * base unit sizey + (m -1) * item paddingy

其中 m 是正整數,而 x 和 y 代表項目大小的 x 與 y 維度和項目邊框距離。

如果基本大小對於項目而言太小,將會降低應用程式的效能。 首要規則就是,任何項目的大小在任一方向的基本單位數不可以相差太多。

  1. 在 Visual Studio 中,建立一個使用 Grid App 範本的新應用程式。

  2. 在 groupedItems.html 中,建立一個名為 multisizebaseitemtemplate 的新項目範本。 這個項目範本和預設的項目範本大致相同,但是多了一個 “item-description” 標頭,所以除了登陸頁面中的標題和副標題之外,我們還可以納入項目描述。

      <!-- Template tutorial HTML -->
        <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>
                <h6 class="item-description" data-win-bind="textContent: description"></h6>
            </div>
        </div>
    
  3. 在 groupedItems.js 中的 PageControl 定義 (ui.Pages.define) 前面,建立一個名為 multisizeItemTemplateRenderer 的範本函式。

    我們將使用此函式來轉譯 ListView 項目。這個函式會判斷哪個項目要使用哪個項目範本。我們會在稍後的步驟中,將它指派給 ListView 控制項的 itemTemplate 屬性。

     function multisizeItemTemplateRenderer(itemPromise) {
            return itemPromise.then(function (currentItem) {
                var content;
                // Grab the default item template used on the groupeditems page.
                content = document.querySelector(".multisizebaseitemtemplate");
                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"
                            }
                            // Use the mediumlarge template for the second item
                            else if (currentItem.index == 2) {
                                result.className = "mediumlargeitemtemplate"
                            }
                            // Use the medium template for the third item, and any other items
                            else {
                                result.className = "mediumitemtemplate"
                            }
                            break;
                        }
                    default:
                        {
                            // Use the small template for the second group
                            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 data binding.
                result.querySelector(".item-image").src = currentItem.data.backgroundImage;
                result.querySelector(".item-title").textContent = currentItem.data.title;
                result.querySelector(".item-subtitle").textContent = currentItem.data.subtitle;
                result.querySelector(".item-description").textContent = currentItem.data.description;
                return result;
            });
        }
    
  4. 在 groupedItems.js 中,新增 groupInfo 函式 (也在頁面定義之外)。這個函式會告訴 ListView 在檢視中使用多重大小的項目,並且指出項目的基本大小。基本大小是清單中顯示的最小項目。其他項目必須是這個大小的倍數,配置才能正常運作。

     function groupInfo() {
        return {
            enableCellSpanning: true,
            cellWidth: 80,
            cellHeight: 80
        };
     }
    
  5. 現在我們必須將這些新函式連結至 ListView 控制項。

    1. 在 groupedItems.js 中,變更 _initializeLayout 函式,就可以顯示一般清單的群組。

      // Add the itemTemplate parameter as shown.
      _initializeLayout: function (listView, viewState, itemTemplate) {
          if (viewState === appViewState.snapped) {
              listView.itemDataSource = Data.groups.dataSource;
              listView.groupDataSource = null;
      
              // Add the following line of code.
              listView.itemTemplate = itemTemplate;
      
              listView.layout = new ui.ListLayout();
          } else {
      
                      listView.itemDataSource = Data.items.dataSource;
                      listView.groupDataSource = Data.groups.dataSource;
                      listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
      
              // Add the following two lines of code.
              listView.itemTemplate = multisizeItemTemplateRenderer;
              listView.layout = new ui.GridLayout({ groupInfo: groupInfo, groupHeaderPosition: "top" });
          }
      },
      
    2. 移除指派項目範本給 ListView 的那一行,並進行此程式碼中的註解所指出的變更。

      ready: function (element, options) {
          var listView = element.querySelector(".groupeditemslist").winControl;
      
          // Add the next line of code to retrieve the item template. 
          var itemTemplate = element.querySelector(".itemtemplate");
      
          listView.groupHeaderTemplate = element.querySelector(".headerTemplate");
      
          listView.oniteminvoked = this.itemInvoked.bind(this);
              listView.itemTemplate = element.querySelector(".itemtemplate");
      
          // Change the last argument of the _initializeLayout function to itemTemplate.
          this._initializeLayout(listView, appView.value, itemTemplate);
          listView.element.focus();
       },
      
      // This function updates the page layout in response to viewState changes.
      updateLayout: function (element, viewState, lastViewState) {
          var listView = element.querySelector(".groupeditemslist").winControl;
      
          // Add the next line of code to retrieve the item template.
          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, viewState, itemTemplate);
              }
          }
      },
      
      
  6. 接下來,我們必須將項目的樣式設定加到 groupedItems.css。 若要如上一個影像所示設定項目的樣式,我們需要 4 個 CSS 類別,供登陸頁面上的 4 個不同項目範本使用。 將 4 個類別分別命名為 smallitemtemplatemediumitemtemplatemediumlargeitemtemplate 以及 largeitemtemplate。 下一個 CSS 通常會將重疊與文字放在相對於影像的位置,並適當調整每個項目的大小。 因為並非所有範本都會使用項目範本中的所有元素,所以在一些情況下,會摺疊某些元素。 只在第一個 @media screen CSS 行之前新增此 CSS。

    /* Generic styling */
    .groupeditemspage .groupeditemslist .item-overlay {
        -ms-grid-row: 2;
    }
    .groupeditemspage .groupeditemslist .item-overlay .item-description {
        visibility:collapse;
    }
    
    /* Small item template */
    .groupeditemspage .groupeditemslist .smallitemtemplate {
        width: 440px;
        height: 80px;
        overflow: hidden;
    
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-image {
        height: 80px;
        width: 80px;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay {
       opacity: 0;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay .item-title {
        position: absolute; 
        top: -5px;
        padding-left: 90px;
        font-size: 11pt;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay .item-subtitle {
        position: absolute; 
        top: 15px;
        padding-left: 90px;
        font-size: 9pt;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay .item-description {
        position: absolute; 
        top: 35px;
        padding-left: 90px;
        font-size: 9pt;
        visibility: visible;
        width: 360px;
        overflow-wrap: normal;
        text-overflow: initial;
    }
    
    /* Medium item template */
    .groupeditemspage .groupeditemslist .mediumitemtemplate {
        width: 260px;
        height: 170px;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 30px;
        display: -ms-grid;
        overflow: hidden;
    }      
    .groupeditemspage .groupeditemslist .mediumitemtemplate .item-overlay .item-title {
        padding-top: 5px;
        padding-left: 10px;
    }
    .groupeditemspage .groupeditemslist .mediumitemtemplate .item-overlay .item-title {
        font-size: 14px;
    }
    .groupeditemspage .groupeditemslist .mediumitemtemplate .item-overlay .item-subtitle {
        visibility: collapse;
    }   
    
    /* Medium-large item template */
    .groupeditemspage .groupeditemslist .mediumlargeitemtemplate {
        width: 260px;
        height: 350px;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 30px;
        display: -ms-grid;
        overflow: hidden;
    }
    .groupeditemspage .groupeditemslist .mediumlargeitemtemplate .item-overlay .item-title {
        padding-top: 5px;
        padding-left: 10px;
        font-size: 14px;
    }
    
    .groupeditemspage .groupeditemslist .mediumlargeitemtemplate .item-overlay .item-subtitle {
        visibility: collapse;
    }   
    
    /* Large item template */
    .groupeditemspage .groupeditemslist .largeitemtemplate {
        width: 440px;
        height: 530px;
        overflow: hidden;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 90px;
        display: -ms-grid;
    }
    .groupeditemspage .groupeditemslist .largeitemtemplate .item-overlay {
        -ms-grid-row: 2;
        -ms-grid-rows: 1fr 21px;
        display: -ms-grid;
        padding: 6px 15px 2px 15px;
    }
    .groupeditemspage .groupeditemslist .largeitemtemplate .item-subtitle{
        -ms-grid-row: 2;
    }
    
    
  7. @media screen and (-ms-view-state: fullscreen-landscape), screen and (-ms-view-state: fullscreen-portrait), screen and (-ms-view-state: filled) 規則中,將第一個 CSS 樣式變更如下。此 CSS 程式碼會產生不透明的重疊,並且移除 "item" 類別。

     .groupeditemspage .groupeditemslist .item-overlay {
            background: rgba(0,0,0,1);
        }
    
  8. 將 groupedItems.css 中的第一個 .groupeditemspage .groupeditemslist .win-horizontal.win-viewport .win-surface 樣式變更成這樣。

        .groupeditemspage .groupeditemslist .win-horizontal.win-viewport .win-surface {
            margin-bottom: 60px;
            margin-left: 45px;
            margin-right: 115px;
        }
    

    此 CSS 程式碼會將 margin-bottom 變更為 "50px",以說明稍微大一點的項目。

完成上述變更之後,請啟動您的應用程式。應用程式將看起來如下:

更新過的應用程式

新增圖片及變更背景、文字與重疊色彩,就完成建立 Contoso Food Truck 登陸頁面。

更有創意的大小與範本

除了此處所示的方法之外,還有許多方法可以自訂您的項目範本。 例如,此登陸頁面可以使用兩個項目大小和三個不同的範本,讓外觀達到對稱。

另一個自訂的登陸頁面

此登陸頁面的基本單位為最小項目的大小。 每個群組中第一個項目的基本單位都是 2x3 個,而其範本中會將標題與描述放在影像下方。 群組中接下來項目的單位都是 1x1 個,而且標題與描述重疊於影像之上。第三個範本適用於沒有影像的項目。

新增 ListView 項目動畫

在 [開始] 畫面中,以動態磚顯示最新的圖片,以及資訊一目了然的文字。 如果適當,應用程式的登陸頁面也可以使用 WinJS 動畫庫,達到相同的效果。

這個範例中登陸頁面上的第一個項目每隔 4 秒就會更新一次新影像,與 [開始] 畫面中使用的時間相同。 我們使用 WinJS 查看動畫,與 [開始] 畫面中的磚使用的動畫相同。

  1. 在 Visual Studio 中,建立一個使用 Grid App 範本的新應用程式。

  2. 在 groupedItems.html 中,修改項目範本以納入將用於動畫的第二個影像。

        <div class="itemtemplate" data-win-control="WinJS.Binding.Template">
            <div class="item">
                <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
                <img class="item-image-new" 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>
        </div>
    
  3. 在 groupedItems.css 中,修改 CSS 以將第二個影像放在第一個影像下方。 這樣就可以從項目的底部開始,在位置中產生新影像的動畫。 我們必須讓兩個項目使用相對位置,這樣我們才可以在啟動動畫 之前變更它們的位置。 groupedItems.css 中已經有第一個和第三個 CSS 樣式,只需要做修改就可以了。第二個 CSS 樣式是新的。

            /* Update this CSS style. */
            .groupeditemspage .groupeditemslist .item .item-image {
                -ms-grid-row-span: 2;
                position:relative;
            }
    
            /* Add this CSS style. */
            .groupeditemspage .groupeditemslist .item .item-image-new {
                -ms-grid-row-span: 2;
                position:relative;
                top: 250px;
            }
    
            /* Update this CSS style. */
            .groupeditemspage .groupeditemslist .item .item-overlay {
                -ms-grid-row: 2;
                -ms-grid-rows: 1fr 21px;
                display: -ms-grid;
                padding: 6px 15px 2px 15px;
                position:relative;
            }
    
  4. 在 groupedItems.js 中,將此程式碼加到 ready 函式,就可以每隔四秒觸發一個新的項目動畫。

                setInterval(function () { changeImage() } , 4000);
    
  5. 在 groupedItems.js 中,於頁面定義之外新增此程式碼。 第一個變數定義會指向 Grid App 範本使用的不同影像。新增 peekTile 函式,以播放 JavaScript 適用的 Windows Library 查看動畫。 新增 changeImage 函式,以在播放動畫之前更新影像。 在本範例中,我們只針對 ListView 中的第一個項目播放動畫。

        // Define images
        var darkGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY3B0cPoPAANMAcOba1BlAAAAAElFTkSuQmCC";
        var lightGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
        var mediumGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
    
        // Play the Peek animation
        function peekTile(tile1, tile2) {
            // Create peek animation
            var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
    
            // Reposition tiles to their desired post-animation position
            tile1.style.top = "-250px";
            tile2.style.top = "0px";
    
            // Execute animation
            peekAnimation.execute();
        }
    
       function changeImage() {
            // Get the two image elements
            var images = document.querySelector(".item-image");
            var imagesNew = document.querySelector(".item-image-new"); 
    
            // Swap out the old image source and choose the new image source
            images.src = imagesNew.src;
            if (images.src == lightGray)
                imagesNew.src = mediumGray;
            else if (images.src == mediumGray)
                imagesNew.src = darkGray;
            else
                imagesNew.src = lightGray;
    
            // Reset the elements for the pre-animation position and trigger the animation
            images.style.top = "0px";
            imagesNew.style.top = "250px";
            peekTile(images, imagesNew);
        };
    

    恭喜您,您已完成在您的 ListView 增加自訂項目動畫!

相關主題

ListView

快速入門:新增 ListView

設定 ListView 及其項目的樣式