Swiftui - How to Change The Button's Image on Click

How can I create a button with image in SwiftUI?

Go to the image and change the Render As "Original Image"
Sample Image

SwiftUI - Button action draws on an image

I'm not 100% sure if I understand this correctly, but it's simply a matter of displaying an image when a button is clicked?

You already said that you got an image with the desired behavior, but you don't want it to be there from the beginning. I think you are looking for an alternative in SwiftUI for addSubview, but there is no direct one.

What you might be looking for is @State in SwiftUI. Changing a @State variable will force your view to redraw itself. (There are more then just @State variables that to this)

You can draw your Image based on a condition. On your button click you could change the state variable that your condition is based on to redraw your view and to display your Image. I use the toggle() function in my example, so clicking the Button a second time will result in removing the image.

import SwiftUI

struct ContentView: View {
@State private var showImage = false

var body: some View {
VStack {
if showImage {
Image(systemName: "gear") // Your working image
}
Button(action: {
self.showImage.toggle()
}, label: {
Text("draw image")
})
}
}
}

Here is an example how you could add more and more Images when clicking the button again and again. I changed the Type of the @State variable to an array and then iterate over that array via a ForEach.

import SwiftUI

struct ContentView: View {
@State private var images: [UUID] = []

var body: some View {
VStack {
ForEach(images, id: \.self) { _ in
Image(systemName: "gear") // Your working image
}
Button(action: {
self.images.append(UUID())
}, label: {
Text("draw image")
})
}
}
}

Picture and text when clicking on the button. SwiftUI

You can use an if clause to conditionally display elements based on a @State variable.

I'm using the extra frame modifier on the VStack that you didn't originally have to make sure that nothing changes position when the @State variable changes and the elements inside the stack appear/disappear.

struct ContentView : View {
@State private var showImage = false

var body: some View {
VStack {
VStack {
if showImage {
Image(systemName: "house.fill").resizable().aspectRatio(contentMode: .fill).frame(width: 75, height: 75)
Text("TEST")
}
}.frame(height: 100)
Spacer().frame(height: 100)
Button(action: { showImage.toggle() }) {
Text("TEST").foregroundColor(Color.white).padding()
}.background(Color.black) .cornerRadius(10) }
}
}

How to set image to button in SwiftUI?

You could implement it as:

Button(action: {}) {
HStack(alignment: .center, spacing: 5.0) {
Image("cart")
.padding(.leading, 10.0)
Text("Add to Cart")
.foregroundColor(.black)
.padding(.all, 10.0)
}
}
.background(Color.gray)
.cornerRadius(5.0)

Passing HStack instead of Text would do the trick.

To clarify, adding an image next to the button label is not directly related to the button anymore! When creating a button using init(action:label:) initializer, we are passing () -> Label as the second parameter; If you trace the type of Label, you'll see that it is basically a View, so you are not forced to return a Text type for it (as mentioned in the question's code snippet).

Obviously, you could add the image to the right of the label by adding Text before the Image. Also, if you are aiming to add the text on top of the image (or vice-versa), you could simply replace the HStack with a VStack.


Furthermore, more reusable code

You could make your code to be more reusable by creating a custom body View for the button. Also, you could create a custom ViewModifier:

import SwiftUI

// Custom View
struct CustomButtonBody: View {
private var iconName: String
private var title: String

init(iconName: String = "cart", title: String) {
self.iconName = iconName
self.title = title
}

var body: some View {
HStack(alignment: .center, spacing: 5.0) {
Image(iconName)
.padding(.leading, 10.0)
Text(title)
.foregroundColor(.black)
.padding(.all, 10.0)
}
}
}

// Custom Modifier
struct CustomButtonModifier: ViewModifier {
func body(content: Content) -> some View {
return content
.background(Color.gray)
.cornerRadius(5.0)
}
}

thus:

Button(action: {}) {
CustomButtonBody(title: "Add to Cart")
}
.modifier(CustomButtonModifier())

How we can change text of button when a button is clicked for list items in SwiftUI?

If I understand the question correctly, try this approach by removing all toggleText and using @Ali Momeni advice:

struct ContentView: View {
@State var showAnswer = false

@State private var selectedRestaurant: Restaurant?

@State private var restaurants = [ Restaurant(name: "Cafe Deadend", image: "cafedeadend"),
Restaurant(name: "Homei", image: "homei"),
Restaurant(name: "Teakha", image: "teakha"),
Restaurant(name: "Cafe Loisl", image: "cafeloisl"),
Restaurant(name: "Petite Oyster", image: "petiteoyster"),
Restaurant(name: "For Kee Restaurant", image: "forkeerestaurant")
]

private func RestaurantRow(restaurant: Restaurant) -> some View {
BasicImageRow(restaurant: restaurant)
.contextMenu {
Button(action: {
showAnswer = true
setFavorite(item: restaurant)
}) {
HStack {
Text(restaurant.isFavorite ? "UnFavorite" : "Favorite")
Image(systemName: "star")
}
}
}.id(restaurant.id)
.onTapGesture {
selectedRestaurant = restaurant
}
.actionSheet(item: $selectedRestaurant) { restaurant in
ActionSheet(title: Text("What do you want to do"),
message: nil,
buttons: [
.default(
Text(restaurant.isFavorite ? "Mark as UnFavorite" : "Mark as Favorite"),
action: {
setFavorite(item: restaurant)
}),
.cancel()
])
}
}

var body: some View {
List {
ForEach(restaurants) { restaurant in
if restaurant.isFavorite {
RestaurantRow(restaurant: restaurant)
} else {
RestaurantRow(restaurant: restaurant)
}
}
}
}

private func setFavorite(item restaurant: Restaurant) {
if let index = restaurants.firstIndex(where: { $0.id == restaurant.id }) {
restaurants[index].isFavorite.toggle()
}
}

}


Related Topics



Leave a reply



Submit