0

I am trying to make a Log Out button inside a List with sections. However, when I add the button to the section, only the "Log Out" text is clickable and not the entire section. I don't want to resize it to anything larger than the current section its in.

I have searched online for a similar question, but all of those involve making two things clickable in one section, not the row itself.

Section with Links and Log Out Button

            Section{
                //Log out button
                Button("Log Out"){
                    signOutAlert = true
                }
                .foregroundColor(.red)
                .buttonStyle(.borderless)
                .alert(isPresented: $signOutAlert){
                    Alert(
                        title: Text("Log Out"),
                        message: Text("Are you sure you want to log out?"),
                        primaryButton: .destructive(Text("Log Out")){
                            do {
                                try Auth.auth().signOut()
                                auth_status.current_status = .unauthenticated
                            } catch let signOutError as NSError {
                                print("Error logging out")
                            }
                        },
                        secondaryButton: .cancel()
                        
                        
                        
                    )
                }
            }

Unlike creating a Navigation or Link, the entire thing isn't clickable. Is there another way I can keep my log out functionality?

EDIT: As @flanker pointed out. My issue was having .buttonStyle(.borderless) Removing it resulted in my intended output

  • removing the `.borderless` button style will have the effect you want, and in a List cell won't impact visual effect. – flanker May 03 '23 at 00:50
  • @flanker thank you! I totally thought that was required to get them that shape – thatsquitemid May 03 '23 at 03:23
  • While this works, I'm not happy with it as a longterm solution. I've added a better solution as an answer. – flanker May 03 '23 at 17:00
  • If an issue is solved in a comment, don't edit your question to include the answer. Instead, post a new response to the question, acknowledging the person that gave you the answer. This helps everyone follow the standard Q&A format. –  May 03 '23 at 17:31

1 Answers1

2

As noted in the question, using a Button with .buttonStyle(.borderless) inside a list cell, only results in the actual frame of text being tappable to activate the action, whereas the requirement is for the whole width of the cell to be tappable.

Removing the border style results in the required behaviour : in the below the whole of the button's list cell can be tapped to activate the print statement.

List {
   Section  {
      Button ("Log out") {print("Tapped")}
         .foregroundColor(.red)
   }
}

While this works, it seems strange and got me thinking. I can't see why a different style modifier would have such a functional change; it seems as if it might be a bug in the framework? In any case relying on it working consistently in production code when not understanding the pattern of the behaviour is risky: if it is unintended it could change in future versions of SwiftUI.

Therefore a more reliable way to achieve the same effect is to use a Text label with a frame modifier to force it to full width.

List {
   Section{
      Button{
         print("Button 2 tapped")
      } label: 
      { Text("log Out")
            .frame( maxWidth: .infinity, alignment: .leading)
            .foregroundColor(.red)
         
      }
      .buttonStyle(.borderless)
   }
}

This way will make the button fill the whole of the list cell, irrespective of the applied (or absence of) .buttonStyle.

flanker
  • 3,840
  • 1
  • 12
  • 20
  • Thank you for this. I was adding the .frame to the button. That makes the button extend full width, but still only the text is tappable, which is kind of weird to me. – Ants Jun 24 '23 at 03:12