自动布局防止我改变视图的中心

4
我的应用程序之一的功能是自动裁剪图像。
基本思路是:某人拍摄一张纸张(比如:收据)的照片,然后在确定纸张边缘后自动裁剪图像。
我使用OpenCV来确定纸张的边缘。接下来,我会更改每个指南线的"中心"属性(只有2条水平和2条垂直的“线”,可以手动拖动)。
接着,在我完成所有更改4个指南线的调用之后不久,其他东西就会把它们的"中心"再次设置回去。(我已经重写了"setCenter"以证明这一点)。它似乎是被这个方法重新设置的:[UIView(Geometry) _applyISEngineLayoutValues]
我无法弄清楚为什么会发生这种情况,或者如何停止它,但它可能与约束有关。我的视图是一个简单的UIButton。当用户用手指轻点并拖动时,会调用一个动作例程来改变其中心。这很有效。
但在另一种情况下,我正在使用UIImagePickerController。在他们选择图片后,我确定纸张边界,更改了"guides"中心,然后稍后"_applyISEngineLayoutValues"将它们全部设置回来。
对于这种情况,您有什么想法吗?或者我如何设置视图的中心,让它实际上停留在那里呢?

我遇到了类似的问题;我将视图的框架设置为非零大小,但是 _applyISEngineLayoutValues 将边界设置为零。 - Simon
你能展示一些代码吗?你是想通过somView.center = somePoint;改变CGPoint吗?如果是这样,那么你不能使用AutoLayout实现。AutoLayout的第一个规则是你不能改变视图的frame(读作 center)。如果你希望frame改变,那么必须更新任何相关约束的constant值,以便将视图移动到所需位置。 - Fogmeister
2个回答

12

AutoLayout的第一条规则是不能直接更新视图的frameboundscenter。您必须更新与视图相关的约束条件,以便约束条件更新视图。

例如,您的第一条垂直线将具有类似于水平约束条件的东西...

1. Leading edge to superview = some value.
2. Width = some value.

这足以(水平地)将此行放置在屏幕上。

现在,如果您想将此行向右移动,您不能仅更改center,您必须执行以下操作...

1. Create a property in you view controller like this...

@property (nonatomic, weak) IBOutlet NSLayoutConstraint *verticalLine1LeadingConstraint;
// or if you're coding the constraint...
@property (nonatomic, strong) NSLayoutConstraint *verticalLine1LeadingConstraint;

2. Save the constraint in to that property...

// either use IB to CTRL drag the constraint to the property like any other outlet.
// or something like...

self.verticalLine1LeadingConstraint = [NSLayotuConstraint ... // this is the code adding the constraint...

[self.view addConstraint:self.verticalLine1LeadingConstraint];

现在你有一个指向这个约束的属性。

现在,当你需要“更新垂直线1的中心”时...

// Calculate the distance you want the line to be from the edge of the superview and set it on to the constraint...

float distanceFromEdgeOfSuperview = // some calculated value...

self.verticalLine1LeadingConstraint.constant = distanceFromEdgeOfSuperview;

[self.view layoutIfNeeded];

这将更新视图的位置,您不会收到任何错误。


3
您正在使用自动布局,因此Fogmeister的答案是正确的,但不是每个人都可以使用自动布局 - 例如必须支持iPad 1的人 - 所以我会在这里留下这个答案。
如果您需要使用视图的框架但系统正在添加约束,则有一个解决方法;但它并不完美。 _applyISEngineLayoutValues设置了您的视图的centerbounds,但没有触及frame。如果您覆盖setCenter:setBounds:来什么也不做,然后总是在您自己的代码中使用setFrame:,那么_applyISEngineLayoutValues将不会干扰您。
我对这种方法不满意,但这是我迄今为止找到的防止_applyISEngineLayoutValues破坏我的布局逻辑的唯一方法。

AutoLayout的第一条规则是,不要更新视图的frameboundscenter。如果您想要更改这些内容,请更新与该视图相关的自动布局约束。 - Fogmeister
我必须支持iPad 1,所以我不能使用约束。然而,在后来的iOS版本中,一些约束会自动添加;这是我找到的唯一解决方法。 - Simon
啊,抱歉,我没有意识到你没有使用AutoLayout,因为问题标题是关于使用AutoLayout的。除非你编辑答案,否则我无法取消投票。 - Fogmeister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接