【SwiftUI】Listのひとつの要素の中に複数のボタンを置く方法
何が問題か?
タイトルを読んだ限り簡単に実現できそうですよね?
実は、そうでもないのです。
素直に実装した例です。
- コード
import SwiftUI
struct ContentView: View {
let items = ["Item 1", "Item 2", "Item 3"] // 仮のデータ
var body: some View {
List {
ForEach(items, id: \.self) { item in
VStack {
Text(item)
.padding()
HStack {
Button(action: {
print("\(item) Button 1 tapped")
}) {
Text("Button 1")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
Button(action: {
print("\(item) Button 2 tapped")
}) {
Text("Button 2")
.padding()
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(8)
}
// 必要なだけボタンを追加
}
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(8)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
- 実行結果

ボタンが識別されていない(T . T)
`Item1`の`Button1`を押しているのに、となりのButton2までおされていることになっています、、、
# 対処法
- 原因
タップ領域が原因です。
Listをそのまま実装すると、ひとつの要素にタップ領域はその要素の中全部です。今回の場合はbutton1とbutton2の両方が同じタップ領域となっています。
- 結論
`buttonStyleのborderless`修飾子を使用しましょう!
- 修正後のコード
~~~Swift
import SwiftUI
struct ButtonOnList: View {
let items = ["Item 1", "Item 2", "Item 3"] // 仮のデータ
var body: some View {
List {
ForEach(items, id: \.self) { item in
VStack {
Text(item)
.padding()
HStack {
Button(action: {
print("\(item) Button 1 tapped")
}) {
Text("Button 1")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
.buttonStyle(.borderless) // これを追加
Button(action: {
print("\(item) Button 2 tapped")
}) {
Text("Button 2")
.padding()
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(8)
}
.buttonStyle(.borderless) // これを追加
// 必要なだけボタンを追加
}
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(8)
}
}
}
}
struct ButtonOnList_Previews: PreviewProvider {
static var previews: some View {
ButtonOnList()
}
}
- 実行結果

無事に同じ要素の中でもボタンが識別されるようになりました!
最後に
Swiftで稼げるようになりたい方は、メンターの申し込み検討をぜひ!
特徴はSlackでメンティーさん同士の交流もできるようになっています♪

