在 Windows 8.1 Store 应用程序中处理方向 [英] Handling Orientation in Windows 8.1 Store app

查看:34
本文介绍了在 Windows 8.1 Store 应用程序中处理方向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个 Win Store 应用程序,并面临着处理方向的问题.

I am making a Win Store App, and facing the issue to handle orientation.

有一个网格,我想在改变方向时修改它的设计.两侧的堆栈面板(在横向视图中)应在纵向视图中转到顶部和底部.

There is a grid, I want to modify the design of it when the orientation is changed. The stack Panels in both the sides (in Landscape View) should goto Top and Bottom in Portrait View.

目前我已经创建了两个包含所有控件的网格,并根据方向调整它们,并使用 VisualStateManager 切换可见性属性.

Currently I have created two grids with all the controls and adjust them according to the orientation, and switching the visibility property, using VisualStateManager.

但我想用一个网格来实现这一点,任何建议对我都有很大帮助.

But I want to achieve this with a single grid, any suggestion will be a great help for me.

下图是应用的概念设计:

The below image is the concept design of the app:

推荐答案

用单个 Grid 做到这一点很困难,但可能.

Doing this with a single Grid is difficult, but possible.

首先,您可能想要做的是少担心方向,多担心水平宽度.这样,如果用户以没有太多水平空间(类似于纵向模式)的方式捕捉应用,您可以显示类似的体验.

Firstly, what you probably want to do is worry less about orientation and more about horizontal width. That way, if the user snaps the app in such a way that there isn't much horizontal space (similar to portrait mode), you can display a similar experience.

现在,进入网格.

这里的关键是您正在从本质上具有 3 列的 Grid 移动到具有 1 列的网格.因此,您需要修改单元格的 ColumnSpan 属性.

The key here is that you are moving from a Grid with, in essence, 3 Columns to one with 1 Column. As such, you will need to modify the ColumnSpan Property of your cells.

到目前为止您绘制的内容有 3 个 Columns,每个的 WidthGridLength *.从那里开始.

What you have drawn so far has 3 Columns, each with a Width of GridLength *. Start there.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>    
</Grid>

接下来,我们要设置Rows.最好使行数成为您需要的最大数量,这是我的计数 6.如果将它们全部设置为 Auto,则空 Rows (在横向)将消失.

Next, we want to set up the Rows. It's better to make the number of Rows the largest that you'll need, which is by my count 6. If you set them all to Auto, then the empty Rows (in the Landscape orientation) will disappear.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>    
    <Grid.RowDefinitions>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>    
</Grid>

现在,创建一些基本内容.我只是要创建一堆不同的 StackPanel 并命名它们包含在其中的内容.

Now, to create some basic contents. I'm just going to create a bunch of different StackPanels and name them what you have contained in them.

我将默认的 Grid/Row 值设置为 Landscape 的值.我还为第二行"使用了两行(包含 StackPanels 1 和 2).两个 StackPanel 都将有一个 RowSpan 为 2 来补偿.

I am setting the default Grid/Row values to that of Landscape. I am also using two rows for the 'Second Row' (containing StackPanels 1 and 2). Both StackPanels will have a RowSpan of 2 to compensate.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>    
    <Grid.RowDefinitions>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
        <RowDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>    
    <StackPanel Name="HeaderRow" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"/>
    <StackPanel Name="StackPanel1" Grid.Row="1" Grid.Column="0" Grid.RowSpan="2"/>
    <StackPanel Name="Content" Grid.Row="1" Grid.Column="1"/>
    <StackPanel Name="BlueSection" Grid.Row="2" Grid.Column="1"/>
    <StackPanel Name="StackPanel2" Grid.Row="1" Grid.Column="2" Grid.RowSpan="2"/>
    <StackPanel Name="FooterRow" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3"/>
</Grid>

现在我们对 Landscape 方向有了一个很好的定义.它也会根据其中的内容自动调整垂直大小,但您可以随意调整所需的最小大小.

Now we have a nice definition for your Landscape orientation. It will automatically size vertically based on the content within it as well, though you are free to do whatever minimum sizing you want.

既然我们已经做到了这一点,我们只需要为不同的尺寸创建一些VisualStates.在一个 VisualState 中,我们将准确定义我们已经完成的工作.另一方面,我们将创建一个新的.我现在将它们命名为横向"和纵向",但我建议做一些类似中"和宽"的事情,然后根据给定的 Bounds 定义使用哪个.为了篇幅,我省略了之前的定义.

Now that we've done this, we just need to create some VisualStates for our different sizes. In one VisualState we will be defining exactly what we've already done. In the other, we will be creating a new one. I am naming them 'Landscape' and 'Portrait' for now, but I suggest doing something like 'Mid' and 'Wide', and then defining which is used based on the Bounds given. I have omitted the previous definitions for the sake of space.

从技术上讲,我们不需要包含 Landscape 定义,但我将其作为附加示例包含在内.

Technically, we don't need to include the Landscape definition, but I'm including it as an additional example.

注意:在第二张图片中,您有 StackPanel2 下面 Footer.我在下面反映了这一点.如果需要更改,只需将 StackPanel2 的行定义更改为 4,将 Footer 的行定义更改为 5.

Note: In the second picture, you have StackPanel2 below Footer. I have reflected this below. If you need that changed, just change the row definitions of StackPanel2 to 4 and of Footer to 5.

<Grid>
    ...
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="OrientationStates">
            <!-- What we've already defined -->
            <VisualState x:Name="Landscape">
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel1">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel1">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>

                <!-- Stack Panel 2 -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
                 </ObjectAnimationUsingKeyFrames>

                <!-- Content -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Content">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="Content">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="Content">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>

                <! -- Blue Section -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="BlueSection">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="BlueSection">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="BlueSection">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>

                <!-- Footer -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Footer">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
                 </ObjectAnimationUsingKeyFrames>
            </VisualState>

            <!-- The New Section -->
            <VisualState x:Name="Portrait">
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel1">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel1">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
                 </ObjectAnimationUsingKeyFrames>

                <!-- Stack Panel 2 -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="5"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="StackPanel2">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                 </ObjectAnimationUsingKeyFrames>

                <!-- Content -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Content">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="Content">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="Content">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
                 </ObjectAnimationUsingKeyFrames>

                <! -- Blue Section -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="BlueSection">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="BlueSection">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                 </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="BlueSection">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
                 </ObjectAnimationUsingKeyFrames>

                <!-- Footer -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Footer">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="4"/>
                 </ObjectAnimationUsingKeyFrames>
            </VisualState>
        </VisualStateGroup>
    <VisualStateManager.VisualStateGroups>
</Grid>

你快完成了.您所需要的只是让您的 Page 监听 WindowSizeChanged 并响应它!它需要获得对您的 Grid 的引用.因此,我建议添加 x:Name="ContentGrid" 或类似于基本 Grid 定义的内容.如:

You're almost done. All you need left is for your Page to listen for WindowSizeChanged and respond to it! It needs to get a reference to your Grid. As such, I suggest adding x:Name="ContentGrid" or something similar to the base Grid definition. Such as:

<Grid x:Name="ContentGrid">

我的 WindowSizeChanged 示例将假设您已完成此操作.

My example for WindowSizeChanged will assume you have done this.

private void WindowSizeChanged(object sender, WindowSizeChangedEventArgs windowSizeChangedEventArgs)
{
    if (windowSizeChangedEventArgs.Size.Width < 800)
    {
        VisualStateManager.GoToState(ContentGrid, "Portrait", true);
    }
    else
    {
        VisualStateManager.GoToState(ContentGrid, "Landscape", true);
    }
}

然后,在您的 PageOnNavigatedToOnNavigatedFrom...

Then, in your Page's OnNavigatedTo and OnNavigatedFrom...

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    Window.Current.SizeChanged += WindowSizeChanged;
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    Window.Current.SizeChanged -= WindowSizeChanged;
}

确保在从页面导航时删除 SizeChanged event 处理程序,否则您的应用程序将无限期地在内存中保留您的页面副本.这是如何创建有趣的内存泄漏.

Make sure you remove the SizeChanged event handler on navigating from the page, otherwise your app will retain a copy of your page in memory indefinitely. This is how to create a fun memory leak.

就是这样!在大小改变时,您的主页将通知您的网格它需要重新配置自己,并且它将按照描述的方式进行.显然你不能直接粘贴它,但你应该可以使用很多.确保将 TargetNames 更改为您命名的控件.

And that's it! On size changed, your main page will notify your Grid that it needs to reconfigure itself and it will do so in the way described. Obviously you won't be able to directly paste this in, but you should be able to use a lot of it. Make sure to change the TargetNames to your named controls.

希望这会有所帮助并祝您编码愉快!

Hope this helps and happy coding!

这篇关于在 Windows 8.1 Store 应用程序中处理方向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆