快速入门:设计适用于不同窗口大小的应用

[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]

设计在任何窗口大小下都外观良好且功能正常的应用时,你必须选择是否创建其他布局来补充默认的水平全屏布局。 你可以将你的应用设计为能够支持最小 320 像素的宽度,而不是默认的最小 500 像素,并使其能够在应用的高度大于宽度时切换为垂直布局。这些是可选的设计选项。

请将此操作功能视为我们的应用功能大全系列的一部分: Windows 应用商店应用 UI 全解

目标: 阅读本文后,你将了解如何将应用的最小宽度从 500 像素更改为 320 像素,以及如何更改你的设计,使其在较窄的宽度下外观良好且功能正常。你还将了解如何将水平平移应用设计为当应用高度大于宽度时更改为垂直布局。

先决条件

使用 JavaScript 创建你的第一个 Windows 应用商店应用

布局和缩放的 UX 指南

示例:适用于高度大于宽度的窗口的布局

本文演示了适用于较高和较窄布局的其他设计选项,描述了它们在适用于高度大于宽度的窗口的布局示例中的实现方式。本示例基于 Microsoft Visual Studio 中的“网格应用”模板。

“网格应用”****模板有以下四个页面:

  • default (default.html),仅在应用启动后加载 groupedItems 页面。
  • groupedItems (pages\groupItems\groupedItems.html),允许用户查看组和项,并且选择组标签导航到组详细信息页面 (groupDetail),或者选择某个项导航到整页项视图 (itemDetail)。
  • groupDetail (pages\groupDetail\groupDetail.html),允许用户查看组详细信息和项,并选择一个项以导航到整页项视图 (itemDetail)。
  • itemDetail (pages\itemDetail\itemDetail.html),表示某个项的整页视图。

在本文中,你会将默认布局用于每个页面。我们仅介绍将 JavaScript 代码隐藏在 groupDetailgroupedItems 页面所需进行的更改。

此处的关键代码技术用于检查页面的 offsetWidthoffsetHeight 属性的更改情况。如果由于用户更改了页面宽度或设备方向而达到某些宽度和高度值,则页面会更改其控件的布局和行为。

若要尝试此操作,请在 Visual Studio 中,创建 JavaScript Windows 应用商店 “网格应用”项目的新实例,然后按照余下这些说明操作。

定义最小宽度

默认情况下,Windows 应用商店应用的最小宽度为 500 像素。应用的高度始终达到屏幕的高度。应用的最小屏幕高度为 768 像素。

如果你的应用在较窄宽度时效果很好,或者如果多任务功能对于你的应用非常重要并且你希望用户将你的应用与其他应用放置在同一屏幕上,则可以将最小宽度更改为 320 像素而不是 500 像素。这样,用户就可以流畅地将你的应用调整为任意大小(从全屏到最小 320 像素宽)。

你可以在 package.appxmanifest 清单文件中更改应用的最小宽度。要执行此操作,请在 Visual Studio 中完成以下步骤。

  1. 打开 package.appxmanifest 清单文件。该清单将自动在 清单设计器中打开。

  2. 打开“应用程序”选项卡并找到“最小宽度”字段。****

  3. 使用下拉列表将最小宽度更改为“320 像素”。****

  4. 如果你在文本编辑器中打开 package.appxmanifest 清单文件,则应该可以看到作为 VisualElements 元素子项的 ApplicationView 元素。例如,清单文件中新的最小宽度如下所示。

    <ApplicationView MinWidth="width320" /> 
    

由于你的应用的大小可缩小到 320 像素,你需要修改你的应用,使其在较窄的宽度下可用。具体做法是切换应用,以便该应用可以垂直而非水平平移。

定义组和项视图的行为

  1. pages\groupedItems\groupedItems.js 文件中,将代码添加到 ui.Pages.define 函数的 ready 方法中。此方法会在所有页面初始化和调色完成后调用。在此方法中,调用 _initializeLayout 函数(以后会定义)。(若要引用,将需要添加的代码加上 *** START ****** END *** 注释。)

    ui.Pages.define("/pages/groupedItems/groupedItems.html", {
        // ...
        ready: function (element, options) {
            var listView = element.querySelector(".groupeditemslist").winControl;
            listView.element.focus();
            // *** START ***
            this._initializeLayout(listView);
            // *** END ***
        },
        // ...
    
  2. groupedItems.js 文件中,将代码添加到 ui.Pages.define 函数的 updateLayout 方法中。无论用户何时在布局状态(如窄、纵向和横向)之间切换应用,都可以调用此方法。在此方法中,引用页面的 ListView 控件,临时禁用页面动画,然后调用 _initializeLayout 函数(以后会定义)。

    ui.Pages.define("/pages/groupedItems/groupedItems.html", {
        // ...
        updateLayout: function (element) {
            /// <param name="element" domElement="true" />
    
            // TODO: Respond to changes in layout.
            // *** START ***
            var listView = element.querySelector(".groupeditemslist").winControl;
    
            // Don't show page entrance animations when the app switches layouts.
            var handler = function (e) {
                listView.removeEventListener("contentanimating", handler, false);
                e.preventDefault;
            }
            listView.addEventListener("contentanimating", handler, false);
    
            this._initializeLayout(listView);
            // *** END ***
        },
        // ...
    
  3. groupedItems.js 文件中,将代码添加到 ui.Pages.define 函数以定义 _initializeLayout 函数。此函数确定页面是处于窄、纵向还是横向布局,并相应调整页面的 ListView 控件。readyupdateLayout 方法都会调用此函数。此函数将执行以下操作。

    • 如果页面宽度大于 320 像素小于 500 像素,则页面的 ListView 控件会仅将数据显示为组的垂直滚动列表。(500 像素为示例宽度。你可以决定更改布局时你要使用的宽度。在本示例中,我们选择 500 像素来作为应用切换其布局的点。对于任何低于 500 像素的宽度,应用都将使用较窄布局。)
    • 如果页面的宽度小于高度,则 ListView 控件会将数据显示为包含项的组的垂直滚动列表。
    • 否则,ListView 控件会将数据显示为包含项的组的水平滚动网格。
    ui.Pages.define("/pages/groupedItems/groupedItems.html", {
        // ...
        // *** START ***
        _initializeLayout: function (listView) {
            // Narrow layout.
            if (document.documentElement.offsetWidth < 500) {
                // Show data as a vertically-scrolling list of groups only.
                listView.itemDataSource = Data.groups.dataSource;
                listView.groupDataSource = null;
                listView.layout = new ui.ListLayout();                
            }
            // Portait layout.
            else if (document.documentElement.offsetWidth < document.documentElement.offsetHeight) {
                // Show data as as a vertically-scrolling list of groups that contain items.
                listView.itemDataSource = Data.items.dataSource;
                listView.groupDataSource = Data.groups.dataSource;
                listView.layout = new ui.ListLayout();                                
            }
            // Landscape layout.
            else {
                // Show data as a horizontally-scrolling grid of groups contain items.
                listView.itemDataSource = Data.items.dataSource;
                listView.groupDataSource = Data.groups.dataSource;
                listView.layout = new ui.GridLayout();
            }
        },
        // *** END ***
        // ...
    

定义组详细信息和项详细信息视图的行为

  1. pages\groupDetail\groupDetail.js 文件中,将代码添加到 ui.Pages.define 函数的 updateLayout 方法中。无论何时用户在纵向和横向布局之间切换应用,都会调用此方法。在此方法中,引用页面的 ListView 控件,临时禁用页面动画,然后调用 _initializeLayout 函数(以后会定义)。而且滚动 ListView 控件以便正确项为第一个可见项。

    ui.Pages.define("/pages/groupDetail/groupDetail.html", {
        // ...
        updateLayout: function (element) {
            /// <param name="element" domElement="true" />
    
            // TODO: Respond to changes in layout.
            // *** START ***
            var listView = element.querySelector(".itemslist").winControl;
    
            // Don't show page entrance animations when the app switches layouts.
            var handler = function (e) {
                listView.removeEventListener("contentanimating", handler, false);
                e.preventDefault();
            }
            listView.addEventListener("contentanimating", handler, false);
    
            var firstVisible = listView.indexOfFirstVisible;
    
            this._initializeLayout(listView);
    
            if (firstVisible >= 0 && listView.itemDataSource.list.length > 0) {
                listView.indexOfFirstVisible = firstVisible;
            }
            // *** END ***
        },
        // ...
    
  2. groupDetail.js 文件中,将代码添加到 ui.Pages.define 函数以定义 _initializeLayout 函数。此函数确定页面是处于纵向还是横向布局,并相应调整页面的控件。updateLayout 方法会调用此函数。此函数将执行以下操作。

    • 如果页面宽度大于 320 像素小于 500 像素,则页面的 ListView 控件会仅将数据显示为组的垂直滚动列表。(500 像素为示例宽度。你可以决定更改布局时你要使用的宽度。在本示例中,我们选择 500 像素来作为应用切换其布局的点。对于任何低于 500 像素的宽度,应用都将使用较窄布局。)
    • 如果页面的宽度小于高度,则 ListView 控件会将数据显示为不显示组标题的垂直滚动列表。
    • 否则,ListView 控件会将数据显示为水平滚动网格,其组标题显示在右侧。
    ui.Pages.define("/pages/groupDetail/groupDetail.html", {
        // ...
        // *** START ***
        _initializeLayout: function (listView) {
            // Portrait layout.
            if (document.documentElement.offsetWidth < document.documentElement.offsetHeight) {
                listView.layout = new ui.ListLayout();
                var header = document.getElementsByTagName("header");
                header.item(0).style.display = "none";
            }
            // Landscape layout.
            else {
                listView.layout = new ui.GridLayout({ groupHeaderPosition: "left" });
                var header = document.getElementsByTagName("header");
                header.item(0).style.display = "inherit";
            }
        },
        // *** END ***
        // ...
    

切换布局

现在你可以看到当切换窗口大小时应用布局所发生的变化。

  1. 在 Visual Studio 中的仿真程序中启动应用。(若要了解方法,请参阅在仿真程序中运行 Windows 应用商店应用
  2. 单击“基本触摸模式”。
  3. 将页面顶部拖动到一边,然后移动分隔线,以使页面的宽度为 500 像素。 将数据显示为包含项的组的垂直滚动列表。
  4. 移动分隔线以使页面的宽度为 320 像素。仅将数据显示为组的垂直滚动列表。
  5. 单击“顺时针旋转”****。将数据显示为包含项的组的垂直滚动列表。
  6. 使用以下操作进行试验:点击组标题、项标题和后退按钮,以及更改页面宽度和设备方向。

摘要

你现在应该已了解如何设计你的应用,使其在 较窄的宽度下以及在高度大于宽度的布局下外观良好且功能正常。

相关主题

快速入门:定义应用布局