ExpandingMenu icon indicating copy to clipboard operation
ExpandingMenu copied to clipboard

Add support for Autolyout

Open ogezue opened this issue 10 years ago • 3 comments

It would be great if you could add support for Autolayout.

Currently I'm trying something like this, but it is not working with conditions you have made inside your code.

private func configureAutolayoutConstraints(buttonView: UIView, parentView: UIView){

        buttonView.translatesAutoresizingMaskIntoConstraints = false

        let bottomConstraint = NSLayoutConstraint(item: buttonView, attribute:
            .Bottom, relatedBy: .Equal, toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: -30)

        parentView.addConstraint(bottomConstraint)


        let trailingConstraint = NSLayoutConstraint(item: buttonView, attribute:
            .Trailing, relatedBy: .Equal, toItem: parentView, attribute: .Trailing, multiplier: 1.0, constant: -30)
        parentView.addConstraint(trailingConstraint)



        let widthConstraint = NSLayoutConstraint(item: buttonView, attribute:
            .Width , relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 80)

        parentView.addConstraint(widthConstraint)

        let heightConstraint = NSLayoutConstraint(item: buttonView, attribute:
            .Height , relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 80)

        parentView.addConstraint(heightConstraint)

    }

ogezue avatar Feb 11 '16 10:02 ogezue

Perhaps my adoption (very basic) is a starting point:

class SocialButton: NSObject {

    private weak var parentController : UIViewController?
    private var dimmedView : UIView?
    private var mainButton : UIButton?
    private var menuButtons = [SocialMenuButton]()
    private var menuIsVisible = false


    var dimmedViewTopConstraint: NSLayoutConstraint?
    var dimmedViewBottomConstraint: NSLayoutConstraint?
    var dimmedViewTrailingConstraint: NSLayoutConstraint?
    var dimmedViewLeadingConstraint: NSLayoutConstraint?


    func configureSocialButtonForViewController(controller: UIViewController) {

        self.parentController = controller

        self.addDimmedView(controller.view)
        self.addButtonView(controller.view)
        self.addMenuItems(self.parentController!.view)
        self.parentController?.view.layoutIfNeeded()
        self.parentController?.view.bringSubviewToFront(mainButton!)
    }

    func addMenuItems(parentView: UIView){
        let socialMenuButton1 = SocialMenuButton(parentView: parentView, referenceView: mainButton!, index: 0, title: "Menu1", image: UIImage(named: "logo")!, highlightedImage: UIImage(named: "logo")!) { () -> Void in
            self.showAlert("Menu1")
            self.mainButtonTapped()
        }
        self.menuButtons.append(socialMenuButton1)

        let socialMenuButton2 = SocialMenuButton(parentView: parentView, referenceView: mainButton!, index: 1, title: "Menu2", image: UIImage(named: "logo")!, highlightedImage: UIImage(named: "logo")!) { () -> Void in
            self.showAlert("Menu2")
            self.mainButtonTapped()
        }
        self.menuButtons.append(socialMenuButton2)

        let socialMenuButton3 = SocialMenuButton(parentView: parentView, referenceView: mainButton!, index: 2, title: "Menu3", image: UIImage(named: "logo")!, highlightedImage: UIImage(named: "logo")!) { () -> Void in
            self.showAlert("Menu3")
            self.mainButtonTapped()
        }
        self.menuButtons.append(socialMenuButton3)

        let socialMenuButton4 = SocialMenuButton(parentView: parentView, referenceView: mainButton!, index: 3, title: "Menu4", image: UIImage(named: "logo")!, highlightedImage: UIImage(named: "logo")!) { () -> Void in
            self.showAlert("Menu4")
            self.mainButtonTapped()
        }
        self.menuButtons.append(socialMenuButton4)
    }

    func hideMenuItems(){

        for item in menuButtons{
            item.hideItem()
        }
    }

    func showAlert(title: String) {
        let alert = UIAlertController(title: title, message: nil, preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
        self.parentController?.presentViewController(alert, animated: true, completion: nil)
    }

    func addDimmedView(parentView: UIView){

        dimmedView = UIView(frame: CGRect(x: 0,y: 0,width: 10,height: 10))
        if let dimmedView = self.dimmedView{
            dimmedView.backgroundColor = UIColor.darkGrayColor()

            let tap = UITapGestureRecognizer(target: self, action: Selector("mainButtonTapped"))
            dimmedView.addGestureRecognizer(tap)
            dimmedView.userInteractionEnabled = true
            parentView.addSubview(dimmedView)


            //Configure autolayout
            dimmedView.translatesAutoresizingMaskIntoConstraints = false

            let y = UIScreen.mainScreen().bounds.size.height
            let x = UIScreen.mainScreen().bounds.size.width

            dimmedViewTopConstraint = NSLayoutConstraint(item: dimmedView, attribute:
                .Top , relatedBy: .Equal, toItem: parentView, attribute: .Top, multiplier: 1.0, constant: y)
            parentView.addConstraint(dimmedViewTopConstraint!)

            dimmedViewBottomConstraint = NSLayoutConstraint(item: dimmedView, attribute:
                .Bottom , relatedBy: .Equal, toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: 0)
            parentView.addConstraint(dimmedViewBottomConstraint!)

            dimmedViewTrailingConstraint = NSLayoutConstraint(item: dimmedView, attribute:
                .Trailing , relatedBy: .Equal, toItem: parentView, attribute: .Trailing, multiplier: 1.0, constant: 0)
            parentView.addConstraint(dimmedViewTrailingConstraint!)

            dimmedViewLeadingConstraint = NSLayoutConstraint(item: dimmedView, attribute:
                .Leading , relatedBy: .Equal, toItem: parentView, attribute: .Leading, multiplier: 1.0, constant: x)
                parentView.addConstraint(dimmedViewLeadingConstraint!)
        }
    }




    func addButtonView(parentView: UIView){

        mainButton = UIButton(frame: CGRect(x:0, y:0, width: 60, height: 60))
        if let mainButton = self.mainButton{
            mainButton.setImage(UIImage(named: "chooser-button-tab"), forState: UIControlState.Normal)
            mainButton.setImage(UIImage(named: "chooser-button-tab-highlighted"), forState: UIControlState.Highlighted)
            mainButton.addTarget(self, action: "mainButtonTapped", forControlEvents: UIControlEvents.TouchUpInside)
            //mainButton.backgroundColor = UIColor.blueColor()

            parentView.addSubview(mainButton)

            //Configure autolayout
            mainButton.translatesAutoresizingMaskIntoConstraints = false

            let bottomConstraint = NSLayoutConstraint(item: mainButton, attribute:
                .Bottom, relatedBy: .Equal, toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: -50)

            parentView.addConstraint(bottomConstraint)


            let trailingConstraint = NSLayoutConstraint(item: mainButton, attribute:
                .Trailing, relatedBy: .Equal, toItem: parentView, attribute: .Trailing, multiplier: 1.0, constant: 0)
            parentView.addConstraint(trailingConstraint)


            let widthConstraint = NSLayoutConstraint(item: mainButton, attribute:
                .Width , relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 60)

            parentView.addConstraint(widthConstraint)

            let heightConstraint = NSLayoutConstraint(item: mainButton, attribute:
                .Height , relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 60)

            parentView.addConstraint(heightConstraint)
        }
    }

    func mainButtonTapped(){

            if self.menuIsVisible{

                //hide
                self.hideMenuItems()
                self.menuIsVisible = !self.menuIsVisible
                self.dimmedView?.alpha = 0.0
                self.dimmedViewTopConstraint?.constant = (self.mainButton?.frame.origin.y)!
                self.dimmedViewLeadingConstraint?.constant = (self.mainButton?.frame.origin.x)!
                self.parentController?.view.layoutIfNeeded()
            }
            else{
                //show
                self.dimmedView?.alpha = 0.7
                self.dimmedViewTopConstraint?.constant = 0
                self.dimmedViewLeadingConstraint?.constant = 0
                self.parentController?.view.layoutIfNeeded()

                UIView.animateWithDuration(0.3, animations: { () -> Void in

                for item in self.menuButtons{
                    item.showItem()
                    self.parentController?.view.layoutIfNeeded()
                }
                }, completion: { (finished) -> Void in
                    self.menuIsVisible = !self.menuIsVisible
                    })
            }
    }

    // MARK: - Menu Item Tapped Action
    func menuItemTapped(item: SocialMenuButton) {
        mainButtonTapped()
    }


}
class SocialMenuButton: UIView {


    private var menuButton : UIButton?
    private var textLabel : UILabel?
    weak private var delegate: SocialButton?
    private var tappedAction: (() -> Void)?
    private var bottomConstraint: NSLayoutConstraint?
    private var index = 0


    init(parentView: UIView, referenceView: UIView, index: Int, title: String, image: UIImage, highlightedImage: UIImage, itemTapped: (() -> Void)?) {

        let itemFrame = CGRect(x: 0.0, y: 0.0, width: image.size.width, height: image.size.height)

        super.init(frame: itemFrame)

        self.index = index
        addButton(parentView, referenceView: referenceView, index: index, image: image, highlightedImage: highlightedImage, itemTapped: itemTapped)

        addTextLabel(parentView, title: title)

        self.tappedAction = itemTapped
        self.hideItem()
    }


    private func addButton(parentView: UIView, referenceView: UIView, index: Int, image: UIImage, highlightedImage: UIImage, itemTapped: (() -> Void)?){

        menuButton = UIButton(frame: CGRect(x:0, y:0, width: 30, height: 30))

        if let menuButton = menuButton {
            menuButton.setImage(image , forState: UIControlState.Normal)
            menuButton.setImage(highlightedImage , forState: UIControlState.Highlighted)
            menuButton.addTarget(self, action: "tapped", forControlEvents: UIControlEvents.TouchUpInside)
            //menuButton.backgroundColor = UIColor.greenColor()
            parentView.addSubview(menuButton)

            menuButton.translatesAutoresizingMaskIntoConstraints = false

            let widthConstraint = NSLayoutConstraint(item: menuButton, attribute:
                .Width , relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 45)
            parentView.addConstraint(widthConstraint)

            let heightConstraint = NSLayoutConstraint(item: menuButton, attribute:
                .Height , relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 45)
            parentView.addConstraint(heightConstraint)

            bottomConstraint = NSLayoutConstraint(item: menuButton, attribute:
                .Bottom, relatedBy: .Equal, toItem: referenceView, attribute: .Top, multiplier:  1.0, constant:menuButton.bounds.height )

            parentView.addConstraint(bottomConstraint!)

            let trailingConstraint = NSLayoutConstraint(item: menuButton, attribute:
                .Trailing, relatedBy: .Equal, toItem: referenceView, attribute: .Trailing, multiplier: 1.0, constant: -10)
            parentView.addConstraint(trailingConstraint)
        }
    }

    private func addTextLabel(parentView: UIView, title: String){
        textLabel = UILabel(frame: CGRect(x:0, y:0, width: 100, height: 30))

        if let textLabel = textLabel{
            textLabel.text = title
            //textLabel.backgroundColor = UIColor.greenColor()
            textLabel.font = UIFont.systemFontOfSize(22)
            textLabel.textColor = UIColor.whiteColor()

            let tap = UITapGestureRecognizer(target: self, action: Selector("tapped"))
            textLabel.addGestureRecognizer(tap)
            textLabel.userInteractionEnabled = true
            parentView.addSubview(textLabel)

            textLabel.translatesAutoresizingMaskIntoConstraints = false

            let trailingConstraint = NSLayoutConstraint(item: textLabel, attribute:
                .Trailing, relatedBy: .Equal, toItem: menuButton, attribute: .Leading, multiplier: 1.0, constant: -20)
            parentView.addConstraint(trailingConstraint)


            let centerYConstraint = NSLayoutConstraint(item: textLabel, attribute:
                .CenterY, relatedBy: .Equal, toItem: menuButton, attribute: .CenterY, multiplier: 1.0, constant: 0)
            parentView.addConstraint(centerYConstraint)
        }
    }

    func showItem(){
        bottomConstraint?.constant = CGFloat(self.index) * -60
        self.alpha = 1.0
        self.menuButton?.alpha = 1.0
        self.textLabel?.alpha = 1.0
    }

    func hideItem(){
        self.alpha = 0.0
        self.menuButton?.alpha = 0.0
        self.textLabel?.alpha = 0.0
        bottomConstraint?.constant = (menuButton?.bounds.height)!
    }

    func removeSubviews(){
        self.textLabel?.removeFromSuperview()
        self.menuButton?.removeFromSuperview()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    // MARK: - Tapped Action
    func tapped() {
        self.delegate?.menuItemTapped(self)
        self.tappedAction?()
    }

}

ogezue avatar Feb 17 '16 07:02 ogezue

+1

vronin avatar Mar 15 '16 15:03 vronin

Totally agree, without the auto-layout support the https://github.com/monoqlo/ExpandingMenu/issues/6 becomes a real issue and makes this nice library not usable in production without hacks.

daniel-abramov avatar Apr 02 '19 10:04 daniel-abramov