Creating Action Sheets in SwiftUI

An ActionSheet is useful when you want to present the user with multiple options to choose from, without presenting an alert. For example, you would want to offer the possibility to the user to either pick from their library or take a photo to change their profile picture. Let's see how to create an action sheet like this.

Show an action sheet with multiple options for the user to choose from.

Create your button 

Create your button on which the user will tap to change their photo.

VStack {
		Text("Change photo")
				.font(.headline)
				.frame(maxWidth: .infinity)
				.frame(height: 50)
				.background(LinearGradient(gradient: Gradient(colors: [Color(#colorLiteral(red: 0.262745098, green: 0.0862745098, blue: 0.8588235294, alpha: 1)), Color(#colorLiteral(red: 0.5647058824, green: 0.462745098, blue: 0.9058823529, alpha: 1))]), startPoint: .top, endPoint: .bottom))
				.cornerRadius(16)
				.foregroundColor(.white)
}

..

Add onTapGesture 

When the user taps on the button, we want to show the ActionSheet. Let's create a state at the top of the file.

@State private var showActionSheet = false

..

Then, let's add the onTapGesture modifier to change the showActionSheet variable to true.

.onTapGesture {
	showActionSheet = true
}

..

Add the actionSheet 

Finally, let's add the action sheet. The variable we will check to present the action sheet is showActionSheet.

.actionSheet(isPresented: $showActionSheet, content: {

})

..

Next, we'll create the ActionSheet. With the ActionSheet, you can add a title, a message, and an array of buttons. The title and the buttons are mandatory, but the message is optional.

.actionSheet(isPresented: $showActionSheet, content: {
		ActionSheet(title: Text("Choose a new photo"), 
				message: Text("Pick a photo that you like"), 
				buttons: [
					.default(Text("Pick from library")) {
              print("Tapped on pick from library")
          },
          .default(Text("Take a photo")) {
              print("Tapped on take a photo")
          },
          .cancel()
        ])
})

..

Output:

The final code will look like this:

@State private var showActionSheet = false

var body: some View {
	VStack {
		Text("Change photo")
				.font(.headline)
				.frame(maxWidth: .infinity)
				.frame(height: 50)
				.background(LinearGradient(gradient: Gradient(colors: [Color(#colorLiteral(red: 0.262745098, green: 0.0862745098, blue: 0.8588235294, alpha: 1)), Color(#colorLiteral(red: 0.5647058824, green: 0.462745098, blue: 0.9058823529, alpha: 1))]), startPoint: .top, endPoint: .bottom))
				.cornerRadius(16)
				.foregroundColor(.white)
	}
	.padding(.horizontal, 20)
	.onTapGesture {
		showActionSheet = true
	}
	.actionSheet(isPresented: $showActionSheet, content: {
		ActionSheet(title: Text("Choose a new photo"), 
				message: Text("Pick a photo that you like"), 
				buttons: [
					.default(Text("Pick from library")) {
              print("Tapped on pick from library")
          },
          .default(Text("Take a photo")) {
              print("Tapped on take a photo")
          },
          .cancel()
        ])
	})
}

The first line defines a boolean @State variable called showActionSheet with an initial value of false.


The VStack contains a Text view with the title "Change photo" that has a gradient background and rounded corners. This text view also has a tap gesture attached to it, which will set the showActionSheet variable to true.


The actionSheet modifier is used to present the action sheet. It takes a binding to a boolean value that controls whether the action sheet is shown ($showActionSheet in this case), and the content of the action sheet is defined by an ActionSheet view.

The ActionSheet view has a title and a message, and it defines an array of buttons. In this example, there are two buttons with the .default style, each with a different text label. Tapping on either of these buttons will print a message to the console. The third button has the .cancel style, and it simply dismisses the action sheet.

..

Comments