Adding an Instructional Overlay for first time users to your app in iOS
Sometimes called Coachmarks, a Wizard, or an Onboarding Flow, this common UX pattern is used to guide first time users to an app on its features in your UI.
Here’s a quick and simple way to implement this pattern:
private func buildButton(with title: String) -> UIButton {
let button = UIButton(type: .system)
button.backgroundColor = .systemOrange
button.setTitle(title, for: .normal)
return button
}
override func viewDidLoad() {
super.viewDidLoad()
let buttonText = "Put me in coach!"
let button = buildButton(with: buttonText)
button.translatesAutoresizingMaskIntoConstraints = false
let overlay = UIView(frame: .zero)
overlay.translatesAutoresizingMaskIntoConstraints = false
overlay.backgroundColor = UIColor.black.withAlphaComponent(0.5)
let coachButton = buildButton(with: buttonText)
coachButton.translatesAutoresizingMaskIntoConstraints = false
coachButton.isUserInteractionEnabled = false
let coachLabel = UILabel(frame: .zero)
coachLabel.translatesAutoresizingMaskIntoConstraints = false
coachLabel.textColor = .white
coachLabel.text = "Get player in the game"
view.addSubview(button)
view.addSubview(overlay)
view.addSubview(coachButton)
view.addSubview(coachLabel)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
coachButton.centerXAnchor.constraint(equalTo: button.centerXAnchor),
coachButton.centerYAnchor.constraint(equalTo: button.centerYAnchor),
coachLabel.centerXAnchor.constraint(equalTo: coachButton.centerXAnchor),
coachLabel.centerYAnchor.constraint(equalTo: coachButton.bottomAnchor, constant: 20),
overlay.topAnchor.constraint(equalTo: self.view.topAnchor),
overlay.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
overlay.leftAnchor.constraint(equalTo: self.view.leftAnchor),
overlay.rightAnchor.constraint(equalTo: self.view.rightAnchor),
])
}
The idea here is that you have a duplicate button on top of a semi-transparent overlay. We use Auto Layout to constrain coachButton
to the real button
, and we also disable isUserInteractionEnabled
since we don’t actually want the user to be able to select it in this flow.
Also, note how we’re using buildButton(with:)
to instantiate the buttons so we make sure we’re actually constructing the buttons the same way for both button
and coachButton
.