iOS 具有 VFL 约束的动态自动布局
iOS Dynamic Autolayout with VFL 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));
}
体验过的行为:我们在视图的初始加载以及转向横向模式时看到了纵向模式所需的行为。但是,当返回到纵向模式时,此后每次当设备转到 portent 模式但横向模式继续运行时,视图控件都会消失。简而言之,人像模式仅在第一次使用时有效。
我进行了相当广泛的研究,但无法确定问题所在。如果对解决方案有任何见解,我将不胜感激。
这里是完整的代码以防万一:
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));
}
}
}
}
问题是您正在删除您未创建的约束,这些约束有助于视图控制器视图自行布局和子视图。
无需从您的视图中删除所有约束,只需删除您创建的约束(保存从 FromVisualFormat
返回的约束数组)。
具体来说,视图控制器视图中添加了一些约束,这些约束基于其自动调整掩码来控制其高度(在自动布局引擎中)。当这些被删除时,它会导致您的视图控制器在自动布局时的高度为零(尽管它绘制得很好,因为它仍在根据其自动调整大小的掩码绘制)。因此,当您的子视图试图填充整个垂直方向 space 时,它只是填充垂直高度 0。
如果您想看到差异,只需在每次清除之前记录您的视图约束数组的内容。
我在尝试根据设备方向在单个视图控制器中动态分配约束时遇到意外行为。
期望的行为: 如下面的代码所示,我使用 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));
}
体验过的行为:我们在视图的初始加载以及转向横向模式时看到了纵向模式所需的行为。但是,当返回到纵向模式时,此后每次当设备转到 portent 模式但横向模式继续运行时,视图控件都会消失。简而言之,人像模式仅在第一次使用时有效。
我进行了相当广泛的研究,但无法确定问题所在。如果对解决方案有任何见解,我将不胜感激。
这里是完整的代码以防万一:
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));
}
}
}
}
问题是您正在删除您未创建的约束,这些约束有助于视图控制器视图自行布局和子视图。
无需从您的视图中删除所有约束,只需删除您创建的约束(保存从 FromVisualFormat
返回的约束数组)。
具体来说,视图控制器视图中添加了一些约束,这些约束基于其自动调整掩码来控制其高度(在自动布局引擎中)。当这些被删除时,它会导致您的视图控制器在自动布局时的高度为零(尽管它绘制得很好,因为它仍在根据其自动调整大小的掩码绘制)。因此,当您的子视图试图填充整个垂直方向 space 时,它只是填充垂直高度 0。
如果您想看到差异,只需在每次清除之前记录您的视图约束数组的内容。