动态地将子视图添加到单元格会导致布局约束错误输出

时间:2015-05-26 00:28:03

标签: ios dynamic autolayout

我有一个表单元格视图,包含几个按钮和一些细节。隐藏细节直到触摸其中一个按钮,并在触摸另一个按钮时将其删除。我正在使用自动布局。

以下是添加控件和配置约束的代码(控件已重命名以保护我的客户端)。代码是C#,但等效的Obj-C / Swift应该是相当明显的:

this.ContentView.AddSubviews(this.firstButton, this.secondButton);
this.detailView.AddSubviews(this.textField1, this.textField2, this.textField3, this.textField4, this.textField5);

this.ContentView.ConstrainLayout(() =>
    this.firstButton.Top() == this.ContentView.Top() + Layout.StandardSiblingViewSpacing &&
    this.firstButton.Bottom() <= this.ContentView.Bottom() - Layout.StandardSiblingViewSpacing &&
    this.firstButton.Left() == this.ContentView.Left() + Layout.StandardSuperviewSpacing &&
    this.secondButton.Top() == this.firstButton.Top() &&
    this.secondButton.Bottom() <= this.ContentView.Bottom() - Layout.StandardSiblingViewSpacing &&
    this.secondButton.Left() == this.firstButton.Left());

this.detailView.ConstrainLayout(() =>
    this.textField1.Top() == this.detailView.Top() &&
    this.textField1.Left() == this.detailView.Left() &&
    this.textField1.Right() == this.detailView.Right() &&
    this.textField2.Top() == this.textField1.Bottom() + Layout.StandardSiblingViewSpacing &&
    this.textField2.Left() == this.textField1.Left() &&
    this.textField2.Right() == this.textField1.Right() &&
    this.textField3.Top() == this.textField2.Bottom() + Layout.StandardSiblingViewSpacing &&
    this.textField3.Left() == this.textField2.Left() &&
    this.textField3.Right() == this.textField2.Right() &&
    this.textField4.Top() == this.textField3.Bottom() + Layout.StandardSiblingViewSpacing &&
    this.textField4.Left() == this.textField3.Left() &&
    this.textField4.Right() == this.textField3.Right() &&
    this.textField5.Top() == this.textField4.Bottom() + Layout.StandardSiblingViewSpacing &&
    this.textField5.Bottom() <= this.detailView.Bottom() - Layout.StandardSiblingViewSpacing &&
    this.textField5.Left() == this.textField4.Left() &&
    this.textField5.Right() == this.textField4.Right());

detailView中的动画代码如下所示:

private void AnimateDetailsIn()
{
    this.ContentView.AddSubview(this.detailView);
    this.ContentView.ConstrainLayout(() =>
        this.detailView.Top() == this.ContentView.Top() + Layout.StandardSiblingViewSpacing &&
        this.detailView.Bottom() <= this.ContentView.Bottom() - Layout.StandardSiblingViewSpacing &&
        this.detailView.Left() == this.secondButton.Right() + Layout.StandardSiblingViewSpacing &&
        this.detailView.Right() == this.ContentView.Right() - Layout.StandardSuperviewSpacing);

    var tableView = this.FindParent<UITableView>();

    if (tableView == null)
    {
        return;
    }

    tableView.BeginUpdates();
    tableView.EndUpdates();
}

每当调用AnimateDetailsIn时,屏幕上的所有看起来都很好,但我在输出中看到此错误消息:

Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x7fccb670 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fd8efd0(36)]>",
    "<NSLayoutConstraint:0x7fd94330 V:|-(0)-[UITextField:0x7fd905a0]   (Names: '|':UIView:0x7fd90050 )>",
    "<NSLayoutConstraint:0x7fd943c0 V:[UITextField:0x7fd905a0]-(8)-[UITextField:0x7fd90e90]>",
    "<NSLayoutConstraint:0x7fd94450 V:[UITextField:0x7fd90e90]-(8)-[UITextField:0x7fd91720]>",
    "<NSLayoutConstraint:0x7fd944e0 V:[UITextField:0x7fd91720]-(8)-[UITextField:0x7fd91fb0]>",
    "<NSLayoutConstraint:0x7fd94570 V:[UITextField:0x7fd91fb0]-(8)-[UITextField:0x7fd92850]>",
    "<NSLayoutConstraint:0x7fd945a0 UITextField:0x7fd92850.bottom <= UIView:0x7fd90050.bottom - 8>",
    "<NSLayoutConstraint:0x7fdaa080 V:|-(8)-[UIView:0x7fd90050]   (Names: '|':UITableViewCellContentView:0x7fd8efd0 )>",
    "<NSLayoutConstraint:0x7fdaa200 UIView:0x7fd90050.bottom <= UITableViewCellContentView:0x7fd8efd0.bottom - 8>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fd94570 V:[UITextField:0x7fd91fb0]-(8)-[UITextField:0x7fd92850]>

要进行问题排查,我尝试在整个视图层次结构中包含detailView并删除动画。这工作正常(没有错误输出,一切都正确显示)。很明显,关于我如何处理这里的事情并不是很正确。任何人都可以告诉我如何在不使用错误输出的情况下使用自动布局为detailView设置动画效果吗?

2 个答案:

答案 0 :(得分:0)

将子视图添加到contentview后,您需要在每个子视图上将“translatesautoresizingmaskintoconstraints”设置为NO。你在某个地方做的吗?否则,系统会添加您不想要的一组约束。如果您还没有

,可以尝试一下

答案 1 :(得分:0)

要回答我自己的问题,问题归结为以下突出显示的约束之间的相互作用:

enter image description here

前两位由(我认为)UITableViewCell自动添加。它们具有最高优先级(1000)。另外两个突出显示的约束是我在此代码中添加的前两个(顶部和底部):

this.ContentView.ConstrainLayout(() =>
        this.detailView.Top() == this.ContentView.Top() + Layout.StandardSiblingViewSpacing &&
        this.detailView.Bottom() <= this.ContentView.Bottom() - Layout.StandardSiblingViewSpacing &&
        this.detailView.Left() == this.secondButton.Right() + Layout.StandardSiblingViewSpacing &&
        this.detailView.Right() == this.ContentView.Right() - Layout.StandardSuperviewSpacing);

问题在于我的约束也是以最高优先级添加的。由于我的约束(暂时)与UITableViewCell自动施加的约束冲突,我得到约束错误。

“解决方案”(我认为这有点像黑客攻击)是降低我的约束的优先级,以便没有冲突。

虽然这解决了这个问题,但它确实改变了我的细节视图显示时执行的动画的性质。而不是我的变化“扩展”到位,他们从上到下滑入。当你考虑它时,这是有道理的 - 由于优先级降低,我的细节视图不再受限于内容视图的大小。

唉,我不知道如何解决这个问题,所以现在必须使用subpar动画。

PS。感谢Reuben Scratton让我用this post指向正确的方向。