如何解锁Snapped应用?

时间:2013-05-07 14:04:27

标签: windows-8 windows-store-apps winrt-xaml

我注册了我的Page的OnSizeChanged事件,如下:

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
    ApplicationViewState myViewState = ApplicationView.Value;
    if (myViewState == ApplicationViewState.Snapped)
    {
         Windows.UI.ViewManagement.ApplicationView.TryUnsnap();                
    }
}  

当用户尝试(手动....)将其大小调整为捕捉视图时,我正在设置应用程序视图为Filled / Portrait状态。 但TryUnsnap方法失败并且它处于捕捉状态......

帮助!

感谢。

2 个答案:

答案 0 :(得分:3)

要了解TryUnsnap(),我们需要了解两种类型的Windows 8事件:

  1. 计划活动

    程序化事件不要求用户做任何事情。例如,Page的Loaded事件或Timer的Tick事件。

  2. 用户启动的活动

    用户启动的事件要求用户执行某些操作。例如Button的Click事件或Control的Tapped事件。

  3. 重要部分

    根据事件的类型,只能调用某些Windows 8 API。例如,添加辅助磁贴。并且(正如您可能已经猜到的那样)取消应用程序。

    这意味着您可以从程序化事件中调用所有这些API,但它们永远不会提供您想要的结果。在StateChanged事件中解除绑定,因此会失败。在Button.Click事件中取消禁用,因此会成功。

    此行为背后的基本原理是用户体验。如果应用程序可以在没有用户交互的情况下更改用户的'方向',那么应用程序的行为将变得混乱和不可预测。 Windows 8是一个支持用户的操作系统。当你发现开发者的“约束”时,99%的时间背后都是这种哲学。

    让我演示:

    如果您附加了StateChanged事件,您的代码将如下所示:

    this.ApplicationViewStates.CurrentStateChanged += (s, args) =>
    {
        System.Diagnostics.Debug.WriteLine("After StateChanged: {0}", this.ApplicationViewStates.CurrentState.Name);
        if (this.ApplicationViewStates.CurrentState == this.Snapped)
        {
            System.Diagnostics.Debug.WriteLine("Before Unsnap: {0}", this.ApplicationViewStates.CurrentState.Name);
            Unsnap();
        }
    };
    

    但是,结果输出(在调试器中)将如下所示:

    After StateChanged: FullScreenLandscape
    After StateChanged: Snapped
    Before Unsnap: Snapped
    After TryUnsnap: Snapped
    

    对于不了解Windows 8中 programmatic 用户启动的事件之间差异的开发人员来说,这是令人沮丧的。当API时,API似乎“无效”事实上,它完美地运作。只是不喜欢他们想要它。

    如果您附加了Click事件,您的代码将如下所示:

    MyButton.Click += (s, args) =>
    {
        System.Diagnostics.Debug.WriteLine("After Button.Click: {0}", this.ApplicationViewStates.CurrentState.Name);
        if (this.ApplicationViewStates.CurrentState == this.Snapped)
        {
            System.Diagnostics.Debug.WriteLine("Before Unsnap: {0}", this.ApplicationViewStates.CurrentState.Name);
            Unsnap();
        }
    };
    

    然后,结果输出如下所示:

    After Button.Click: Snapped
    Before Unsnap: Snapped
    After TryUnsnap: Snapped
    After StateChanged: FullScreenLandscape
    

    这可以让你得到你想要的东西,但它提出了一个重要的观点。看看After TryUnsnap状态REMAINS“Snapped”后怎么样?视觉状态从一个转换到另一个不是同步事件。呼吁改变需要不可预测的时间。 这可能是通过发送邮件完成的,但我必须检查以确定。

    说了这么多,状态确实改变了。并且,在更改之后,将引发CurrentStateChanged事件,您可以处理新的Snapped状态。顺便说一下,如果有另一个抢购的应用程序无关紧要,这种方式都可以。

      

    MSDN文档说它只有在前台时才有效。这是非常愚蠢的,因为用户交互不能在后台应用程序上发生,并且后台应用程序无论如何都要暂停其线程。但是,为了公平对待MSDN,当您的应用程序处于后台时,此API不起作用 - 无论值得多少。

    我希望这有助于澄清它。

    现在问你的问题:

    你想从Snapped转到Portrait吗?当然在Portrait中,Snapped是不可能的,所以这不是你编码的可能性。一旦应用程序被捕捉,您希望从Snapped变为Filled。 Snapped动作引发的事件是一个程序性事件。因此,您必须首先引诱用户在您的UI中执行某些操作。所以,不,你不能做你要求的。在用户以某种方式与您的应用交互之前(例如按钮点击事件),您不能解除()。

    哦,如果你想引用我的所有代码,这里是Unsnap()方法。我没有做任何特别的事,但你可能会感兴趣:

    void Unsnap()
    {
        if (Windows.UI.ViewManagement.ApplicationView.TryUnsnap())
            // successfully unsnapped
            System.Diagnostics.Debug.WriteLine("After TryUnsnap: {0}", this.ApplicationViewStates.CurrentState.Name);
        else
            // un-successfully unsnapped
            System.Diagnostics.Debug.WriteLine("After TryUnsnap: {0}", this.ApplicationViewStates.CurrentState.Name);
    }
    

    度过美好的一天,祝你好运!

答案 1 :(得分:0)

            var CurrentSnappedState = ApplicationView.Value;
            if (CurrentSnappedState == ApplicationViewState.Snapped && !ApplicationView.TryUnsnap())
            {
                return;
            }

应该做的伎俩。请记住,您仍然可以对页面进行捕捉,但是当您尝试在捕捉的页面中执行任何操作时,您将被重定向到全视图。