教程:创建自适应布局Tutorial: Create adaptive layouts

本教程介绍关于使用 XAML 的自适应布局功能的基础知识,利用这些功能,可以创建以任何大小显示均具有良好外观的应用。This tutorial covers the basics of using XAML's adaptive layout features, which let you create apps that look good at any size. 你将了解如何添加窗口断点、创建新的 DataTemplate 以及使用 VisualStateManager 类定制应用的布局。You'll learn how to add window breakpoints, create a new DataTemplate, and use the VisualStateManager class tailor your app's layout. 你将使用这些工具针对较小的窗口大小优化图像编辑程序。You'll use these tools to optimize an image editing program for smaller window sizes.

图像编辑程序有两个页面。The image editing program has two pages. 主页显示照片库视图,以及关于每个图像文件的一些信息。The main page displays a photo gallery view, along with some information about each image file.

Photo lab 主页的屏幕截图。

详细信息页 显示选定的单张照片。The details page displays a single photo after it has been selected. 利用浮出编辑菜单,可以修改、重命名和保存照片。A flyout editing menu allows the photo to be altered, renamed, and saved.

Photo lab 详细信息页的屏幕截图。

必备条件Prerequisites

第 0 部分:从 github 获取起始代码Part 0: Get the starter code from github

在本教程中,我们将从一个简化版的 PhotoLab 示例开始。For this tutorial, you'll start with a simplified version of the PhotoLab sample.

  1. 转到 GitHub 页查看示例:https://github.com/Microsoft/Windows-appsample-photo-labGo to the GitHub page for the sample: https://github.com/Microsoft/Windows-appsample-photo-lab.

  2. 接下来,需要克隆或下载示例。Next, you'll need to clone or download the sample. 单击“克隆或下载” 按钮。Click the Clone or download button. 一个子菜单将出现。A sub-menu appears. PhotoLab 示例在 GitHub 页上的“克隆或下载”菜单The Clone or download menu on the PhotoLab sample's GitHub page

    如果你不熟悉 GitHub:If you're not familiar with GitHub:

    a.a. 单击“下载 ZIP” 并在本地保存文件。Click Download ZIP and save the file locally. 这将下载一个包含你需要的所有项目文件的 .zip 文件。This downloads a .zip file that contains all the project files you need.

    b.b. 将该文件解压缩。Extract the file. 使用文件资源管理器浏览到刚下载的 .zip 文件,右键单击它,然后选择“全部解压缩…”。Use File Explorer to browse to the .zip file you just downloaded, right-click it, and select Extract All....

    c.c. 浏览到示例的本地副本,并转到 Windows-appsample-photo-lab-master\xaml-basics-starting-points\adaptive-layout 目录。Browse to your local copy of the sample and go the Windows-appsample-photo-lab-master\xaml-basics-starting-points\adaptive-layout directory.

    如果你熟悉 GitHub:If you are familiar with GitHub:

    a.a. 在本地克隆 repo 的主分支。Clone the master branch of the repo locally.

    b.b. 浏览到 Windows-appsample-photo-lab\xaml-basics-starting-points\adaptive-layout 目录。Browse to the Windows-appsample-photo-lab\xaml-basics-starting-points\adaptive-layout directory.

  3. 在 Visual Studio 中双击 Photolab.sln 打开解决方案。Double-click Photolab.sln to open the solution in Visual Studio.

第 1 部分:定义窗口断点Part 1: Define window breakpoints

运行应用。Run the app. 它很适合全屏显示,但是当你把窗口缩小得太小时,用户界面 (UI) 就不理想了。It looks good at full screen, but the user interface (UI) isn't ideal when you shrink the window too small. 通过使用 VisualStateManager 类使 UI 适应不同窗口大小,你可以确保最终用户体验始终感觉良好。You can ensure that the end-user experience always looks and feels right by using the VisualStateManager class to adapt the UI to different window sizes.

小窗口:之前

有关应用布局的更多信息,请参阅文档的布局部分。For more info about app layout, see the Layout section of the docs.

添加窗口断点Add window breakpoints

第一步是定义应用不同视觉状态的“断点”。The first step is to define the breakpoints at which different visual states are applied. 请参阅屏幕大小和断点,了解有关小、中和大屏幕断点的详细信息。See Screen sizes and breakpoints for more information about the breakpoints for small, medium, and large screens.

从解决方案资源管理器中打开 App.xaml,并在结束 </ResourceDictionary> 标记之前的 MergedDictionaries 后面添加以下代码。Open App.xaml from the Solution Explorer, and add the following code after the MergedDictionaries, right before the closing </ResourceDictionary> tag.

    <!--  Window width adaptive breakpoints.  -->
    <x:Double x:Key="MinWindowBreakpoint">0</x:Double>
    <x:Double x:Key="MediumWindowBreakpoint">641</x:Double>
    <x:Double x:Key="LargeWindowBreakpoint">1008</x:Double>

这将创建 3 个断点,使你能够为 3 个窗口大小范围创建新的视觉状态:This creates 3 breakpoints, which lets you create new visual states for 3 ranges of window sizes:

  • 小(宽度为 0 - 640 像素)Small (0 - 640 pixels wide)
  • 中等(宽度为 641 - 1007 像素)Medium (641 - 1007 pixels wide)
  • 大(宽度大于 1007 像素)Large (> 1007 pixels wide)

在本例中,只为小窗口大小创建新外观。In this example, you create a new look only for the small window size. 中窗口和大窗口大小使用相同的外观。The medium and large sizes use the same look.

第 2 部分:为小窗口大小添加数据模板Part 2: Add a data template for small window sizes

若要使此应用即使在小窗口中也外观良好,你可以创建一个新的数据模板,以优化用户缩小窗口时图像库视图中图像的显示方式。To make this app look good even when it's shown in a small window, you can create a new data template that optimizes how the images in the image gallery view are shown when the user shrinks the window.

创建新的 DataTemplateCreate a new DataTemplate

从解决方案资源管理器中打开 MainPage.xaml,并在 Page.Resources 标记内添加以下代码。Open MainPage.xaml from the Solution Explorer, and add the following code within the Page.Resources tags.

<DataTemplate x:Key="ImageGridView_SmallItemTemplate"
              x:DataType="local:ImageFileInfo">

    <!-- Create image grid -->
    <Grid Height="{Binding ItemSize, ElementName=page}"
          Width="{Binding ItemSize, ElementName=page}">

        <!-- Place image in grid, stretching it to fill the pane-->
        <Image x:Name="ItemImage"
               Source="{x:Bind ImageSource, Mode=OneWay}"
               Stretch="UniformToFill">
        </Image>

    </Grid>
</DataTemplate>

此库模板通过消除图像周围的边框、除去每个缩略图下方的图像元数据(文件名、分级等),从而节省屏幕空间。This gallery template saves screen real estate by eliminating the border around images, and getting rid of the image metadata (filename, ratings, and so on.) below each thumbnail. 每个缩略图改为以简单的正方形显示。Instead, you show each thumbnail as a simple square.

将元数据添加到工具提示Add metadata to a tooltip

你仍然希望用户能够访问每个图像的元数据,因此将为每个图像项目添加一个工具提示。You still want the user to be able to access the metadata for each image, so add a tooltip to each image item. 在刚刚创建的 DataTemplate 的 Image 标记中添加以下代码。Add the following code within the Image tags of the DataTemplate you just created.

    <!-- Add a tooltip to the image that displays metadata -->
    <ToolTipService.ToolTip>
        <ToolTip x:Name="tooltip">

            <!-- Arrange tooltip elements vertically -->
            <StackPanel Orientation="Vertical"
                        Grid.Row="1">

                <!-- Image title -->
                <TextBlock Text="{x:Bind ImageTitle, Mode=OneWay}"
                           HorizontalAlignment="Center"
                           Style="{StaticResource SubtitleTextBlockStyle}" />

                <!-- Arrange elements horizontally -->
                <StackPanel Orientation="Horizontal"
                            HorizontalAlignment="Center">

                    <!-- Image file type -->
                    <TextBlock Text="{x:Bind ImageFileType}"
                               HorizontalAlignment="Center"
                               Style="{StaticResource CaptionTextBlockStyle}" />

                    <!-- Image dimensions -->
                    <TextBlock Text="{x:Bind ImageDimensions}"
                               HorizontalAlignment="Center"
                               Style="{StaticResource CaptionTextBlockStyle}"
                               Margin="8,0,0,0" />
                </StackPanel>
            </StackPanel>
        </ToolTip>
    </ToolTipService.ToolTip>

将鼠标悬停在缩略图上(或者长按触摸屏)时,会显示图像的标题、文件类型和尺寸。This will show the title, file type, and dimensions of an image when you hover the mouse over the thumbnail (or press and hold on a touch screen).

第 3 部分:定义视觉状态Part 3: Define visual states

你现在已经为你的数据创建了新布局,但该应用目前无法知道何时使用此布局而非默认样式。You've now created a new layout for your data, but the app currently has no way of knowing when to use this layout over the default styles. 若要解决此问题,需要添加 VisualStateManagerVisualState 定义。To fix this, you need to add a VisualStateManager and VisualState definitions.

添加 VisualStateManagerAdd a VisualStateManager

将以下代码添加到 RelativePanel 页面根元素中。Add the following code to the root element of the page, RelativePanel.

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
    ...

        <!-- Large window VisualState -->
        <VisualState>

        </VisualState>

        <!-- Medium window VisualState -->
        <VisualState>

        </VisualState>

        <!-- Small window VisualState -->
        <VisualState>

        </VisualState>

    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

创建 StateTriggers 以应用视觉状态Create StateTriggers to apply the visual state

接下来,创建对应于每个吸附点的 StateTriggersNext, create the StateTriggers that correspond to each snap point. 在 MainPage.xaml 中,向每个 VisualState 添加以下代码。In MainPage.xaml, add the following code to each VisualState.

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
    ...

        <!-- Large window VisualState -->
        <VisualState>

            <!-- Large window trigger -->
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="{StaticResource LargeWindowSnapPoint}"/>
            </VisualState.StateTriggers>

        </VisualState>

        <!-- Medium window VisualState -->
        <VisualState>

            <!-- Medium window trigger -->
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="{StaticResource MediumWindowSnapPoint}"/>
            </VisualState.StateTriggers>

        </VisualState>

        <!-- Small window VisualState -->
        <VisualState>

            <!-- Small window trigger -->
            <VisualState.StateTriggers >
                <AdaptiveTrigger MinWindowWidth="{StaticResource MinWindowSnapPoint}"/>
            </VisualState.StateTriggers>

        </VisualState>

    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

当每个视觉状态触发时,该应用将使用分配到活动 VisualState 的任何布局属性。When each visual state is triggered, the app will use whatever layout attributes are assigned to the active VisualState.

为每个视觉状态设置属性Set properties for each visual state

最后,为每个视觉状态设置属性,以告诉 VisualStateManager 在触发状态时要应用哪些属性。Finally, set properties for each visual state to tell the VisualStateManager what attributes to apply when the state is triggered. 每个资源库都以特定 XAML 元素的一个属性为目标,并将其设置为给定值。Each setter targets one property of a particular XAML element and sets it to the given value. StateTriggers 之后,将此代码添加到刚刚创建的 SmallWindow 视觉状态中。Add this code to the SmallWindow visual state you just created, after the StateTriggers.

    <!-- Small window setters -->
    <VisualState.Setters>

        <!-- Apply small template and styles -->
        <Setter Target="ImageGridView.ItemTemplate"
                Value="{StaticResource ImageGridView_SmallItemTemplate}" />
        <Setter Target="ImageGridView.ItemContainerStyle"
                Value="{StaticResource ImageGridView_SmallItemContainerStyle}" />

        <!-- Adjust the zoom slider to fit small windows-->
        <Setter Target="ZoomSlider.Minimum"
                Value="80" />
        <Setter Target="ZoomSlider.Maximum"
                Value="180" />
        <Setter Target="ZoomSlider.TickFrequency"
                Value="20" />
        <Setter Target="ZoomSlider.Value"
                Value="100" />
    </VisualState.Setters>

这些资源库将图像库的 ItemTemplate 设置为在上一部分中创建的新的 DataTemplateThese setters set the ItemTemplate of the image gallery to the new DataTemplate that you created in the previous section. 它们还会调整缩放滑块以更好地适应小屏幕。They also tweak the zoom slider to better fit the small screen.

运行应用Run the app

运行应用。Run the app. 加载该应用时,请尝试更改窗口的大小。When the app loads, try changing the size of the window. 将窗口缩小为小尺寸时,你应该会看到应用切换为你在第 2 部分中创建的小布局。When you shrink the window to a small size, you should see the app switch to the small layout you created in Part 2.

小窗口:之后

深入探索Going further

现在,你已完成本实验,并且拥有足够的自适应布局知识,可以自行进行进一步的实验。Now that you've completed this lab, you have enough adaptive layout knowledge to experiment further on your own. 作为一项更大的挑战,请尝试针对较大的屏幕大小优化布局(例如 Surface Hub)。For a bigger challenge, try optimizing the layout for larger screen sizes, like Surface Hub. 若要测试 Surface Hub 布局,请参阅使用 Visual Studio 测试 Surface Hub 应用See Test Surface Hub apps using Visual Studio if you'd like to test a Surface Hub layout.

如果遇到问题,可在采用 XAML 的响应式布局的以下部分中找到更多指南。If you get stuck, you can find more guidance in these sections of Responsive layouts with XAML.

或者,如果你想要了解有关如何构建初始照片编辑应用的详细信息,请查看这些有关 XAML 用户界面数据绑定的教程。Alternatively, if you want to learn more about how the initial photo editing app was built, check out these tutorials on XAML user interfaces and data binding.

获取 PhotoLab 示例的最终版本Get the final version of the PhotoLab sample

本教程并不生成完整的照片编辑应用,因此,请务必查看最终版本以了解诸如自定义动画和样式等其他功能。This tutorial doesn't build up to the complete photo editing app, so be sure to check out the final version to see other features such as custom animations and styles.