Heestand XYZ
Heestand XYZ

Reputation: 2221

SwiftUI - Two buttons in a List

I've got two buttons in a list, tho when tapping, the full area of the list item is highlighted. Is there a way to separate the two buttons?

In this case I've got an Action button and an Info button:

enter image description here

I found this question, tho no direct solution.

Here's the code:

var body: some View {
    HStack {
        Text(control.name)
        Spacer()
        Button(action: {
            print("action")
        }) {
            Text("Action")
            }
            .frame(width: 250 - 10)
            .padding(5)
            .background(Color(white: 0.9))
            .cornerRadius(10)
            .frame(width: 250)
        Group {
            Button(action: {
                print("action")
            }) {
                Image(systemName: "info.circle")
                    .foregroundColor(.accentColor)
            }
        }
    }
}

Upvotes: 49

Views: 19522

Answers (5)

Jake
Jake

Reputation: 13753

I struggled with this issue for a while. Apple has made Button kind of special in SwiftUI. It can change depending on the context it's used. That is why we see this weird functionality when a Button is inside a List.

Fortunately, there are other ways using .onTapGesture. Try out the code below.

var body: some View {
    HStack {
        Text(control.name)
        Spacer()
        Text("Action")
            .frame(width: 250 - 10)
            .padding(5)
            .background(Color(white: 0.9))
            .cornerRadius(10)
            .frame(width: 250)
            .onTapGesture {
                print("action1")
            }
    
        Image(systemName: "info.circle")
            .foregroundColor(.accentColor)
            .onTapGesture {
                print("action2")
            }
    }
}

Upvotes: 13

kewika
kewika

Reputation: 47

On Xcode 12.5 I've had the same issue in SwiftUI, the full area of the list item being highlighted when tapped.

.buttonStyle(BorderlessButtonStyle()) does the job, and now the two custom button can be tapped separately on the list item.

Upvotes: 4

Anton
Anton

Reputation: 1785

Set the button style to something different from the default, e.g., BorderlessButtonStyle()

struct Test: View {
  var body: some View {
    NavigationView {
      List {
        ForEach([
          "Line 1",
          "Line 2",
        ], id: \.self) {
          item in
          HStack {
            Text("\(item)")
            Spacer()
            Button(action: { print("\(item) 1")}) {
              Text("Button 1")
            }
            Button(action: { print("\(item) 2")}) {
              Text("Button 2")
            }
          }
        }
        .onDelete { _ in }
        .buttonStyle(BorderlessButtonStyle())
      }
      .navigationBarItems(trailing: EditButton())
    }
    .accentColor(.red)
  }
}

Upvotes: 97

Apostolos Apostolidis
Apostolos Apostolidis

Reputation: 189

For anyone having a similar problem with the latest SwiftUI (Xcode 11.2) and multiple Buttons in a HStack, I got my problem solved only after converting all buttons in the HStack to Images and adding the .onTapGesture handler.

The problem in my case was that tapping on one button triggered all other buttons in the HStack. Only after I converted all buttons to images did they stop interfering with each other.

Of course, if your buttons don't have an image, you can use Text instead.

Upvotes: 2

Vivek
Vivek

Reputation: 1

You can add padding or try adding Spacer

Add Padding

HStack {
        Text("Button")
        Spacer()
        Button(action: {
            print("action")
        }) {
            Text("Action")
            }
            .frame(width: 250 - 10)
            .padding(5)
            .background(Color(white: 0.9))
            .cornerRadius(10)
            .frame(width: 250)
        Group {
            Button(action: {
                print("action")
            }) {
                Image(systemName: "info.circle")
                    .foregroundColor(.accentColor)
            }
            .padding(15)
        }
    }

Add Spacer

HStack {
        Text("Button")
        Spacer()
        Button(action: {
            print("action")
        }) {
            Text("Action")
            }
            .frame(width: 250 - 10)
            .padding(5)
            .background(Color(white: 0.9))
            .cornerRadius(10)
            .frame(width: 250)
        Spacer()
        Group {
            Button(action: {
                print("action")
            }) {
                Image(systemName: "info.circle")
                    .foregroundColor(.accentColor)
            }
        }
    }

Upvotes: -7

Related Questions