SJ cartoon avatar

Mobile MBProgressHUD - You Spin My Head Right Round

“Progress dialogs”, “Spinners”, “Activity indicators”, “Progress views”, whatever you want to call them - almost every app has them. On iOS, I use MBProgressHUD because it’s so quick and easy that it hurts a little.

Off-the-shelf, MBProgressHUD (found here) looks pretty slick.

MBProgressHUD loading example

But, inevitably, you’ll be asked by a designer somewhere to customize your progress notifications to look like this…

MBProgressHUD refreshing example

But, re-doing all the UI logic of a library would be very lame. Luckily, MBProgressHUD has some functionality to support custom views - and I’ve written a factory extension to help out.

extension MBProgressHUD {
    private class func createHud(addedTo view: UIView, image: UIImage?, text: String, rotate: Bool = true) -> MBProgressHUD {
        let hud = MBProgressHUD.showAdded(to: view, animated: true)

        hud.customView = UIImageView(image: image)
        hud.mode = .customView
        hud.removeFromSuperViewOnHide = false

        // Equal width/height depending on whichever is larger
        hud.isSquare = true

        hud.label.text = text.uppercased()
        hud.label.textColor = .white

        // Partially see-through bezel
        hud.bezelView.color = .black85
        hud.bezelView.style = .solidColor

        // Dim background
        hud.backgroundView.color = .white20
        hud.backgroundView.style = .solidColor

        if rotate {
            let animation = CABasicAnimation(keyPath: "transform.rotation")
            animation.fromValue = 0.0
            animation.toValue = 2.0 * Double.pi
            animation.duration = 1
            animation.repeatCount = HUGE
            animation.isRemovedOnCompletion = false
            hud.customView?.layer.add(animation, forKey: "rotationAnimation")
        }

        return hud
    }

    class func refreshing(addedTo view: UIView) -> MBProgressHUD {
        return createHud(addedTo: view, image: UIImage(named: "icnRefreshing"), text: "refreshing".localized, rotate: true)
    }
}

In the class where you want your spinner to show up, you can simply use the following:

fileprivate lazy var refreshIndicator: MBProgressHUD = {
    return MBProgressHUD.refreshing(addedTo: self.view)
}()

...

self.refreshIndicator.show(animated: true)
...
self.refreshIndicator.hide(animated: true)

Et voilà! You have a new spinner!

Feature photo credit: JoanDragonfly / Foter.com / CC BY-SA