动态添加子视图到单元格导致布局约束错误输出
Adding subview to cell dynamically is causing layout constraint error output
我有一个 table 单元格视图,其中包含几个按钮和一些细节。在触摸其中一个按钮之前,细节会隐藏起来,而在触摸另一个按钮时会被移除。我正在使用自动布局。
这是添加控件和配置约束的代码(控件已重命名以保护我的客户端)。代码是 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
设置动画而不会出现错误输出?
将子视图添加到内容视图后,您需要在每个子视图上将 'translatesautoresizingmaskintoconstraints' 设置为 NO。你在某个地方这样做吗?否则系统会添加自己的一堆你不想要的约束。如果你还没有,你能试试吗
为了回答我自己的问题,问题归结为以下突出显示的约束之间的相互作用:
前两个是(我认为)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
自动施加的约束冲突,我收到约束错误。
"solution"(我认为这有点 hack)是为了降低我的约束的优先级,这样就不会有冲突。
虽然这解决了问题,但它确实改变了显示细节视图时执行的动画的性质。它们不是我的 "expanding" 更改,而是从上到下滑动。当您考虑时,这是有道理的 - 由于优先级降低,我的详细信息视图不再受限于内容视图的大小。
唉,我还不知道解决这个问题的办法,所以现在只能凑合着用低于标准的动画。
PS。感谢 Reuben Scratton,他用 this post.
为我指明了正确的方向
我有一个 table 单元格视图,其中包含几个按钮和一些细节。在触摸其中一个按钮之前,细节会隐藏起来,而在触摸另一个按钮时会被移除。我正在使用自动布局。
这是添加控件和配置约束的代码(控件已重命名以保护我的客户端)。代码是 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
设置动画而不会出现错误输出?
将子视图添加到内容视图后,您需要在每个子视图上将 'translatesautoresizingmaskintoconstraints' 设置为 NO。你在某个地方这样做吗?否则系统会添加自己的一堆你不想要的约束。如果你还没有,你能试试吗
为了回答我自己的问题,问题归结为以下突出显示的约束之间的相互作用:
前两个是(我认为)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
自动施加的约束冲突,我收到约束错误。
"solution"(我认为这有点 hack)是为了降低我的约束的优先级,这样就不会有冲突。
虽然这解决了问题,但它确实改变了显示细节视图时执行的动画的性质。它们不是我的 "expanding" 更改,而是从上到下滑动。当您考虑时,这是有道理的 - 由于优先级降低,我的详细信息视图不再受限于内容视图的大小。
唉,我还不知道解决这个问题的办法,所以现在只能凑合着用低于标准的动画。
PS。感谢 Reuben Scratton,他用 this post.
为我指明了正确的方向