简体   繁体   中英

SideMenu with AutoLayout

I'am trying to make a side menu and i have some problems with setting it with auto layout. I have a rootViewController that i add to it the leftMenuVC as childVC then i set the constraints.

class RootVC: UIViewController, NavigationBarDelegate {
    var leftMenuVC: UIViewController?
    var navigationBar = NavigationBar()
    var isMenuCollapsed = true

    override func viewDidLoad() {
        leftMenuVC = leftVC()
        addChildViewController(leftMenuVC!)
        view.addSubview(leftMenuVC!.view)
        leftMenuVC!.didMove(toParentViewController: self)
    }

    override func viewDidLayoutSubviews() {
        if let v = leftMenuVC?.view {
            v.translatesAutoresizingMaskIntoConstraints = false
            v.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
            v.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
            v.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -140).isActive = true
            v.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        }
    }

    func menuButtonClicked(){

    }
}

So my question is how to change constraints to hide/show the menu with support of orientations

What I usually do when I want to hide a view outside the screen with constraints is:

1 Set all constraints so that the sideview is visible (in active state)

2 Keep in reference the constraint that stick your sideview on one side (here the left one)

leftAnchor = NSLayoutConstraint(item: v, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: 0)
view.addConstraint(leftAnchor)
view.addConstraint(NSLayoutConstraint(item: v, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: v, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: v, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 0.6, constant: 0))

3 Set one more constraint so that the view will be hidden. Usually it's something like that. Note that the priority is set to 999 to avoid constraint conflicts.

var hiddingConstraint = NSLayoutConstraint(item: v, attribute: .right, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: 0)
hiddingConstraint.priority = 999
view.addConstraint(hiddingConstraint)

4 Animate by activating or not your leftAnchor

UIView.animate(withDuration: 0.3) {
       self.leftAnchor.active = false
       self.view.layoutIfNeeded()
}

So you should end up with a code like this:

class RootVC: UIViewController, NavigationBarDelegate {
    var leftMenuVC: UIViewController?
    var navigationBar = NavigationBar()
    var isMenuCollapsed = true {
        didSet {
            UIView.animate(withDuration: 0.3) {
                self.leftAnchor?.isActive = self.isMenuCollapsed
                self.view.layoutIfNeeded()
            }
        }

    }
    var leftAnchor : NSLayoutConstraint?

    override func viewDidLoad() {
        leftMenuVC = leftVC()
        addChildViewController(leftMenuVC!)
        view.addSubview(leftMenuVC!.view)
        leftMenuVC!.didMove(toParentViewController: self)
    }

    override func viewDidLayoutSubviews() {
        if let v = leftMenuVC?.view {

            leftAnchor = NSLayoutConstraint(item: v, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: 0)
            view.addConstraint(leftAnchor!)
            view.addConstraint(NSLayoutConstraint(item: v, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: v, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: v, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 0.6, constant: 0))

            var hiddingConstraint = NSLayoutConstraint(item: v, attribute: .right, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: 0)
            hiddingConstraint.priority = 999
            view.addConstraint(hiddingConstraint)
        }
    }

    func menuButtonClicked(){
        isMenuCollapsed = !isMenuCollapsed
    }
}

PS: I won't put the constraints setting in viewDidLayoutSubviews , maybe in viewWillAppear , as you don't have to set them every time the device is being rotated. That's the purpose of constraints

Instead of writing this code by yourself, save yourself the trouble. Here is MMDrawerController to your rescue. I am using it myself. It's super easy to implement and offers lots of customization options. Hope you find it useful. :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM