如何为viewcontroller的视图设置多个位置状态?

时间:2014-12-20 19:10:28

标签: ios xcode swift ios8 storyboard

我试图解决的问题是:我有一个DetailViewController,可以显示我的模型的数据UIImageViewUITextFields&# 39; s等。

如果用户点击按钮,那些DetailViewController的视图会移动到不同的位置并开始可编辑。可编辑时,如果用户点按其中一个UITextField(其中只有一个是特殊的),则UITextField移动到屏幕顶部,UITableView似乎会自动填充它(就像当你在谷歌上输入内容时。)

用户也可以点击相同的按钮返回显示状态(无法编辑任何内容)。

所以基本上我在ViewController中有一些可能具有3种状态的观点:DisplayStateEditingStateEditingWithFocusOnSpecialTextFieldsState

我希望NSLayoutConstraints描述所有这些定位状态,如果可能的话,只是在故事板中。

我能做的一件事是Animate to a storyboard state / position,但是这涉及在代码中为每个状态编写每个约束,因此在开发时我无法在故事板中很好地可视化它们(另外,在代码中编写约束)比故事板中的维护要少得多。

我想要的是像创建3个不同的XIB,或者在故事板中我DetailViewController的不同副本,每个子视图有3个不同的位置,然后在它们之间设置动画。

如果它有所不同,我总是使用最新的iOS版本(现在是iOS 8)和Swift。 如果你不想在Swift中回答,我也很了解Objective-C。

1 个答案:

答案 0 :(得分:2)

据我所知,有3种不同的观点无法做到这一点,并得到你想要的结果(至少没有直接的方式)。一种方法是为超级视图的任何一个边缘制作3个约束(每个状态一个),您需要为每个视图调整(除了您需要的任何其他约束,您不会修改)。一个人将具有高优先级(我使用900,它不能是1000),而另外两个将具有较低的优先级(在我的示例中为499)。切换状态时,可以更改3中的哪一个具有高优先级。这确实涉及制定很多约束,我发现在代码中实现切换的最简单方法是在IB中给出约束标识符(您可以在"用户定义的运行时属性"中执行身份检查员)。这种方法意味着我不必为所有这些约束制作IBOutlets。以下是故事板中两个视图的示例

enter image description here

您可以看到文本字段顶部有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)
    }
}