我试图解决的问题是:我有一个DetailViewController
,可以显示我的模型的数据UIImageView
,UITextFields
&# 39; s等。
如果用户点击按钮,那些DetailViewController
的视图会移动到不同的位置并开始可编辑。可编辑时,如果用户点按其中一个UITextField
(其中只有一个是特殊的),则UITextField
移动到屏幕顶部,UITableView
似乎会自动填充它(就像当你在谷歌上输入内容时。)
用户也可以点击相同的按钮返回显示状态(无法编辑任何内容)。
所以基本上我在ViewController
中有一些可能具有3种状态的观点:DisplayState
,EditingState
,EditingWithFocusOnSpecialTextFieldsState
。
我希望NSLayoutConstraints
描述所有这些定位状态,如果可能的话,只是在故事板中。
我能做的一件事是Animate to a storyboard state / position,但是这涉及在代码中为每个状态编写每个约束,因此在开发时我无法在故事板中很好地可视化它们(另外,在代码中编写约束)比故事板中的维护要少得多。
我想要的是像创建3个不同的XIB,或者在故事板中我DetailViewController
的不同副本,每个子视图有3个不同的位置,然后在它们之间设置动画。
如果它有所不同,我总是使用最新的iOS版本(现在是iOS 8)和Swift。 如果你不想在Swift中回答,我也很了解Objective-C。
答案 0 :(得分:2)
据我所知,有3种不同的观点无法做到这一点,并得到你想要的结果(至少没有直接的方式)。一种方法是为超级视图的任何一个边缘制作3个约束(每个状态一个),您需要为每个视图调整(除了您需要的任何其他约束,您不会修改)。一个人将具有高优先级(我使用900,它不能是1000),而另外两个将具有较低的优先级(在我的示例中为499)。切换状态时,可以更改3中的哪一个具有高优先级。这确实涉及制定很多约束,我发现在代码中实现切换的最简单方法是在IB中给出约束标识符(您可以在"用户定义的运行时属性"中执行身份检查员)。这种方法意味着我不必为所有这些约束制作IBOutlets。以下是故事板中两个视图的示例
您可以看到文本字段顶部有3个约束,图像视图有3个centerY约束(尽管您不能看到有3个约束)。每个约束(在3个组中)的标识符设置为"显示","编辑"或"焦点"。我给那个被称为"显示"优先级为900,另外2个获得499(因为我希望视图以显示模式启动)。在这个测试应用程序中,我使用3个按钮来改变状态,当然,你可以使用其他方法来实现这一点。这是我用来切换优先级的代码,
enum EditState: String {
case Display = "display" // these strings are the same as the ones assigned to the identifier property of the constraints in IB (in "user defined runtime attributes")
case Editing = "edit"
case EditWithFocus = "focus"
}
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
func updatEditingState(state: EditState) {
var constraintsArray = self.view.constraints() as [NSLayoutConstraint]
constraintsArray += self.imageView.constraints() as [NSLayoutConstraint]
for con in constraintsArray {
if let name = con.identifier? {
if name == "display" || name == "edit" || name == "focus" {
con.priority = (name == state.rawValue) ? 900 : 499
}
}
}
UIView.animateWithDuration(0.5) {self.view.layoutIfNeeded()}
}
@IBAction func EnterEditingState(sender: UIButton) {
updatEditingState(EditState.Editing)
}
@IBAction func enterDisplayStatus(sender: UIButton) {
updatEditingState(EditState.Display)
}
@IBAction func enterFocusStatus(sender: UIButton) {
updatEditingState(EditState.EditWithFocus)
}
}