Multiple buttons in SwiftUI List rows
In this article we would like to share what we learned about buttons in SwiftUI List
rows when developing one of our apps. We have a list in the form of a tree view. The parent row has a button to expand and collapse the children and each row also acts as a navigation link.
# Two buttons in one row
It is possible to simply put two Button views in a single row.
List {
HStack(spacing: 20) {
Button(action: {
self.isExpanded.toggle()
}) {
Expand(isExpanded: isExpanded)
}
Button(action: {
self.isSelected.toggle()
}) {
Select(isSelected: isSelected)
}
}
}
But in this scenario tapping anywhere on the row will trigger both buttons at once.
# onTapGesture modifier and a button
We can replace the first Button
with a custom view with onTapGesture modifier.
List {
HStack(spacing: 20) {
Expand(isExpanded: isExpanded)
.onTapGesture {
self.isExpanded.toggle()
}
Button(action: {
self.isSelected.toggle()
}) {
Select(isSelected: isSelected)
}
}
}
In this case, tapping exactly on the Expand
view will only toggle the expansion, but tapping anywhere else will trigger the Select
view.
# Two views with onTapGesture modifier
To avoid transforming the entire row into a tappable button, we can only use custom views with onTapGesture
modifiers and no buttons at all.
List {
HStack(spacing: 20) {
Expand(isExpanded: isExpanded)
.onTapGesture {
self.isExpanded.toggle()
}
Select(isSelected: isSelected)
.onTapGesture {
self.isSelected.toggle()
}
}
}
This way tapping exactly on the views will trigger their actions and tapping anywhere else on the row will do nothing.
# Summary
When using Button
views and onTapGesture
modifiers in list rows in SwiftUI we can achieve various results depending on our needs. We have to keep in mind that if we use at least one Button
the whole row will become tappable and tapping anywhere on the row will trigger all of the buttons. Views with onTapGesture
modifier do not have the same behavior and are only triggered when user taps exactly on their area.
You can find the full code for the examples above in our GitHub folder for this article.