如何为viewcontroller的视图设置多个位置状态? [英] How to have multiple position state for viewcontroller's views?

查看:129
本文介绍了如何为viewcontroller的视图设置多个位置状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解决的问题是:我有一个 DetailViewController ,它显示我的模型的数据,带有 UIImageView 's, UITextFields 等等。



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



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



所以基本上我在 ViewController 有3种可能的状态: DisplayState EditingState EditingWithFocusOnSpecialTextFieldsState



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



我能做的一件事是动画到故事板状态/位置,但这涉及在代码中为每个状态编写每个约束因此,在开发过程中,我无法在故事板中很好地将它们可视化(另外,在代码中编写约束比在故事板中更难维护)。



我想要什么例如,在故事板中创建3个不同的XIB,或者我的 DetailViewController 的不同副本,每个子视图有3个不同的位置,然后在它们之间进行动画处理。 / p>

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

解决方案

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





您可以看到文本字段顶部有3个约束,图像视图有3个centerY约束(尽管您看不到有3)。每个约束(在3个组中)的标识符设置为显示,编辑或焦点。我将一个名为display的优先级设为900,另一个设置为499(因为我希望视图以显示模式启动)。在这个测试应用程序中,我使用3个按钮来改变状态,当然,你可以使用其他方法来实现这一点。这是我用来切换优先级的代码,

  enum EditState:String {
case Display =display //这些字符串与分配给IB中约束的identifier属性的字符串相同(在用户定义的运行时属性中)
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 constraintArray {
if let name = con.identifier? {
如果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)
}
}


The problem I'm trying to solve is this: I have a DetailViewController that displays the data for my Model with UIImageView's, UITextFields's, etc.

If the user taps a button, those DetailViewController's views move to different positions and start to be editable. When editable, if the user taps one of the UITextField (just one of them is special) the UITextField moves to the top of the screen and a UITableView appears to autocomplete it (just like when you type something on google).

The user can also tap the same button to go back to the display state (where nothing is editable).

So basically I have some views in a ViewController with 3 possible state: DisplayState, EditingState, EditingWithFocusOnSpecialTextFieldsState.

I'd like to have all those positioning state described by NSLayoutConstraints, and, if possible, just in the storyboard.

One thing I could do is this Animate to a storyboard state / position, but this involves writing every constraint for each state in code, therefore I couldn't visualize them really well in storyboard while developing (Also, writing constraints in code is a lot less maintainable than in storyboard).

What I would like is something like creating 3 different XIBs, for example, or different copies of my DetailViewController in storyboard with the 3 different positions for each of the subviews, and then animate between them.

If it makes any difference, I'm always using the latest iOS version (iOS 8 right now) and Swift. I do know Objective-C very well too if you don't want to answer in Swift.

解决方案

As far as I know, there's no way to do this with 3 different views, and get the result you want (at least no straight forward way). One approach would be to make 3 constraints (one for each state) to any one edge of the superview that you need to adjust for each view (in addition to any other constraints you need that you're not going to modify). One would have a high priority (I'm using 900, it can't be 1000), and the other 2 would have a lower priority (499 in my example). When you switch states, you change which of the 3 has the high priority. This does involve making a lot of constraints, and I found that the easiest way to implement the switching in code was to give the constraints identifiers in IB (which you do in the "User Defined Runtime Attributes" section of the Identity Inspector). This approach means I don't have to make IBOutlets for all those constraints. Here is an example with two views in the storyboard,

You can see the text field has 3 constraints to the top, and the image view has 3 centerY constraints (though you can't see that there are 3). Each constraint (in the groups of 3) has its identifier set to "display", "edit", or "focus". I give the one that's called "display" the priority of 900, and the other 2 get 499 (because I want the view to start in display mode). In this test app, I'm using 3 buttons to change the state, though, of course, you could use other means to accomplish that. Here is the code I use to switch the priorities,

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)
    }
}

这篇关于如何为viewcontroller的视图设置多个位置状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆