具有VFL约束的iOS动态Autolayout

时间:2015-05-15 18:27:01

标签: ios iphone xcode xamarin constraints

尝试根据设备方向在单个视图控制器中动态分配约束时,我遇到意外行为。

所需行为:如下面的代码所示,我使用VFL将视图附加到超级视图的右边,上边和左边,在纵向模式下高度为300,然后在横向模式下,切换到左侧和上边缘相同的视图,高度为90,宽度为160.

if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
{
    View.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[green(300)]", 0, metrics, views));
    View.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[green]|", 0, new NSDictionary(), views));
} 
else
{
    View.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[green(90)]", 0, metrics, views));
    View.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[green(160)]", 0, metrics, views));
}  

有经验的行为:我们会在视图的初始加载时以及转到横向模式时看到纵向模式的所需行为。但是,当恢复到纵向模式时,当设备转到预设模式但横向模式继续起作用时,视图控制每次都会消失。简而言之,纵向模式仅适用于第一次。

我做了相当广泛的研究,无法确定问题所在。我非常感谢对解决方案的任何见解。

以下是完整的代码:

using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System;
using System.CodeDom.Compiler;

namespace iOS.UI
{
    partial class TestConstraintsController : UIViewController
    {
        public TestConstraintsController (IntPtr handle) : base (handle)
        {

        }

        public override void ViewWillAppear (bool animated)
        {
            base.ViewWillAppear (animated);
            AdjustGeometry ();
        }


        public override void DidRotate (UIInterfaceOrientation fromInterfaceOrientation)
        {
            base.DidRotate (fromInterfaceOrientation);
            AdjustGeometry ();
        }

        public void AdjustGeometry()
        {
            UIInterfaceOrientation orientation = UIApplication.SharedApplication.StatusBarOrientation;

            NSDictionary views = NSDictionary.FromObjectsAndKeys (
                                                new NSObject[] { greenBox }, 
                                                new NSObject[] { new NSString ("green") }
                                            );

            View.RemoveConstraints (View.Constraints);

            if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
            {
                View.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[green(boxHeightPortrait)]", 0, new NSDictionary(), views));
                View.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[green]|", 0, new NSDictionary(), views));
            } 
            else
            {
                View.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[green(90)]", 0, new NSDictionary(), views));
                View.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[green(160)]", 0, new NSDictionary(), views));
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

问题在于,您正在删除未创建的约束,这些约束有助于视图控制器查看自己和子视图。

不要从视图中删除所有约束,只需删除您创建的约束(保存从FromVisualFormat返回的约束数组。)

具体来说,视图控制器视图中添加了一些约束,这些约束基于其自动调整遮罩控制其高度(在自动布局引擎中)。当这些被删除时,它导致你的视图控制器在自动布局时的高度为零(虽然它绘制得很好,因为它仍然是基于其自动调整蒙版绘制的)。因此,当您的子视图尝试填充整个垂直空间时,它只是填充垂直高度0。

如果要查看差异,只需在每次清除之前记录视图约束数组的内容。