Search code examples
iosswiftanimationuibarbuttonitemuinavigationitem

Slide UIBarButtonItem from the left


When going to a secondary page, I'm trying to slide the back button in from the left over a period of 0.33 seconds. Right now the animation doesn't appear to be doing that, even after slowing duration down to 2 seconds for visual clarification. Was wondering if anyone could tell me what I've done wrong in my code and how to correct it?

Going to come out and say that I likely am just misunderstanding how some aspect of animation works.

func addBackButton() {
        let backButton = UIButton(type: .custom)
        backButton.setImage(#imageLiteral(resourceName: "backArrow"), for: .normal)
        backButton.setTitle("", for: .normal)
        backButton.setTitleColor(backButton.tintColor, for: .normal)
        backButton.addTarget(self, action: #selector(backAction), for: .touchUpInside)
        let backBarButtonItem = UIBarButtonItem(customView: backButton)
        backBarButtonItem.customView?.transform = CGAffineTransform(translationX: -backButton.frame.width, y: 0)
        navigationItem.leftBarButtonItems?.insert(backBarButtonItem, at: 0)
        UIView.animate(withDuration: 2, delay: 0.5, animations: {
            backBarButtonItem.customView?.transform = CGAffineTransform(translationX: 2 * backButton.frame.width, y: 0)
        })
    }

Solution

  • You just need to put this custom button inside a containerView and set that containerView as the UIBarButtonItem's custom view. Your setup will look like this,

    let containerFrame = CGRect(origin: .zero, size: CGSize(width: 44.0, height: 44.0))
    let container = UIView(frame: containerFrame)
    
    let buttonFrame = CGRect(origin: CGPoint(x: -100, y: 0), size: CGSize(width: 44, height: 44))  
    let backButton = UIButton(frame: buttonFrame)
    backButton.setImage(#imageLiteral(resourceName: "backArrow"), for: .normal)
    backButton.setTitle("", for: .normal)
    backButton.setTitleColor(backButton.tintColor, for: .normal)
    backButton.addTarget(self, action: #selector(backAction), for: .touchUpInside)
    container.addSubview(backButton)
    
    let backBarButtonItem = UIBarButtonItem(customView: container)
    UIView.animate(withDuration: 2, delay: 0.5, animations: {
        backButton.transform = CGAffineTransform(translationX: 2 * backButton.frame.width, y: 0)
    })
    

    You can check why you need to wrap your custom button inside another UIView here.