How do I have multiple position states for the viewcontroller views?

The problem I am trying to solve is this: I have DetailViewController

one that displays data for my model with UIImageView

, UITextFields

etc.

If the user clicks the button, these DetailViewController

views move to different positions and start being edited. When edited, if the user deletes one of them UITextField

(only one of them is special), it UITextField

moves to the top of the screen, and appears UITableView

to autocomplete it (just like when you type something into google).

The user can also press the same button to return to the display state (where nothing is being edited).

Thus, basically, I have some ideas in ViewController

three possible states: DisplayState

, EditingState

, EditingWithFocusOnSpecialTextFieldsState

.

I would like to have all of these positioning states described NSLayoutConstraints

, and if possible only in a storyboard.

One thing I can do is Animate to the state / position of the storyboard , but this involves recording each constraint for each state in the code, so I couldn't visualize they work very well in the storyboard during design (also, the constraint recording much less convenient in code than in storyboard).

What I would like is something like creating 3 different XIBs, for example, or different copies of mine DetailViewController

in the storyboard with 3 different positions for each of the subzones, and then animating between them.

If it matters, I always use the latest iOS (iOS 8 right now) and Swift. I really know Objective-C well too if you don't want to respond in Swift.

+3


source to share


1 answer


As far as I know, there is no way to do this with three different views and get the desired result (at least there is no direct way). One approach would be to make 3 constraints (one for each state) on any one edge of the supervisor that you need to adjust for each view (in addition to any other constraints you need that you are not going to change) ... One of them would have a high priority (I use 900, it can't be 1000) and the second 2 would have a lower priority (499 in my example). When you toggle states, you change which of the 3 has high priority. This comes with a lot of constraints, and I found that the easiest way to implement toggle in code is to provide constraint IDs in IB (which you do in "Runtime User Defined Attributes "in Identity Inspector). This approach means I don't need to do IBOutlets for all these constraints. Here is an example with two views in a storyboard,

enter image description here



You can see that the textbox has 3 constraints at the top, and the image has 3 constraints in the center (although you can't see that there are 3 of them). Each constraint (in groups of 3) has its own identifier set for "display", "edit" or "focus". I give the one called "display" a priority of 900 and the second 2 gets 499 (because I want the view to start in display mode). In this test app I use 3 buttons to change state, although of course you can use other means to achieve this. Here is the code I am using to switch 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)
    }
}

      

+2


source







All Articles