'SwiftUI + Dynamic action closure for Button
I am exploring SwiftUI and I was able to create a subclass of Button
.
The subclass contains image
& title
properties, which makes it a reusable component.
But I am not able to define dynamic action behavior for Button
class.
Please refer code below.
Subclass of Round Button:
struct RoundButton: View {
var image: String
var title: String
var body: some View {
VStack {
Button(action: {
print("Button pressed")
}){
Image(image)
.renderingMode(Image.TemplateRenderingMode?.init(Image.TemplateRenderingMode.template))
}
.frame(width: 40, height: 40)
.background(Color.blue)
.cornerRadius(20)
.accentColor(.white)
Text(title)
.font(.footnote)
}
}
}
Example usage:
HStack(alignment: .center) {
Spacer(minLength: 50)
RoundButton(image: "chat", title: "message")
Spacer()
RoundButton(image: "call", title: "call")
Spacer()
RoundButton(image: "video", title: "video")
Spacer()
RoundButton(image: "mail", title: "mail")
Spacer(minLength: 50)
}
You will see that action
block print a message here.
I would like to know how we can pass a function for a button's action event?
Solution 1:[1]
Button update ...
struct RoundButton: View {
var image: String
var title: String
var action: () -> Void
var body: some View {
VStack {
Button(action: action){
Image(image)
.renderingMode(Image.TemplateRenderingMode?.init(Image.TemplateRenderingMode.template))
}
...
Usage update ...
RoundButton(image: "chat", title: "message") {
print("Button pressed")
}
Solution 2:[2]
Here is another way that you could just create your custom button without given an action to it! and if you need to give an action you could do it as well, like example in ContentView:
PS: I noticed that you just given the tap or clickable posibility just to Image which makes the tap or click harder! instead you can put all in a VStack and it makes more easier to tap or click for user and also much better animation of being tapped. And also you do not need use cornerRadius for making a Circle, you could use clipShape.
struct RoundButton: View {
var image: String
var title: String
var action: (() -> Void)?
init(image: String, title: String, action: (() -> Void)? = nil) {
self.image = image
self.title = title
self.action = action
}
var body: some View {
VStack {
Button(action: {
action?()
}){
VStack {
Image(image)
.renderingMode(Image.TemplateRenderingMode?.init(Image.TemplateRenderingMode.template))
.frame(width: 40, height: 40)
.background(Color.blue)
.foregroundColor(.white)
.clipShape(Circle())
Text(title)
.font(.footnote)
.foregroundColor(.black)
}
}
}
}
}
Use case:
struct ContentView: View {
var body: some View {
RoundButton(image: "person", title: "person")
RoundButton(image: "person", title: "person", action: { print("Button pressed") })
RoundButton(image: "person", title: "person") {
print("Button pressed")
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |