Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView.transitionWithView breaks the loader's layout

I am trying to animate the root-view-controller-change in my app. After I swap the view controllers, I load the data necessary for the 2nd controller right away. While the data is loading, I show a loader(MBProgressHUD). This is my function for swapping the view controllers:

class ViewUtils {

    class func animateRootViewController(duration: NSTimeInterval, changeToViewController: UIViewController) {
        let window = UIApplication.sharedApplication().delegate?.window?
        if window == nil {
            return
        }
        UIView.transitionWithView(window!,
            duration: duration,
            options: UIViewAnimationOptions.TransitionFlipFromLeft | UIViewAnimationOptions.AllowAnimatedContent,
            animations: {
                window!.rootViewController = changeToViewController
            },
            completion: nil
        )
    }
}

All good with this but one thing - it totally breaks the loader. I am attaching an imagine of what's happening: 2nd view controller This is the 2nd view controller while rotating. Once the rotation is complete, the loader appears just fine, both the spinner and the text tween to the correct position in the rounded rectangle.

I really don't understand why this happens, would somebody explain it to me, please? Is there a way to prevent it?

The code of the 2nd view controller where I show the loader:

override func viewDidLoad() {
    super.viewDidLoad()

    hud = HUD(containingView: view)
    hud.show()

    createBackground()
}

And my hud class:

class HUD {

    private var hudBG: UIView!
    private var view: UIView!
    private(set) var isShown = false

    init(containingView: UIView) {
        view = containingView
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func show() {
        if !isShown {
            if(hudBG == nil) {
                hudBG = UIView(frame: CGRectMake(0, 0, view.bounds.width, view.bounds.height))
                hudBG.backgroundColor = UIColor(white: 0, alpha: 0.4)
            }
            view.addSubview(hudBG)
            let hud = MBProgressHUD.showHUDAddedTo(view, animated: true)
            hud.mode = MBProgressHUDModeIndeterminate
            hud.labelText = "Cargando"

            hudBG.alpha = 0

            UIView.animateWithDuration(0.3, animations: { () -> Void in
                self.hudBG.alpha = 1
            })
            isShown = true
        }
    }

    func hide() {
        if isShown {
            UIView.animateWithDuration(0.3, animations: {
                () -> Void in
                self.hudBG.alpha = 0
            }, completion: {
                (b) -> Void in
                self.hudBG.removeFromSuperview()
            })
            MBProgressHUD.hideHUDForView(view, animated: true)
            isShown = false
        }
    }
}

Thanks a lot for any ideas!

like image 645
Fygo Avatar asked Oct 31 '22 06:10

Fygo


1 Answers

You are adding the hud to a view that is not properly initialized yet. If you are loading the view controller from a xib or storyboard, the view and it's subviews have the size as they were loaded from interface.

You have to add the hud after the views have been resized to their final size.

If you move

hud = HUD(containingView: view)
hud.show()

to viewDidLayoutSubviews, it should work fine.

like image 67
pteofil Avatar answered Nov 15 '22 07:11

pteofil