In SwiftUI, why will my buttons trigger if contained in a ZStack but not in an overlay on a VStack?

523 Views Asked by At

Thanks in advance for any advice you can give. I have a custom dropdown menu that I have built in SwiftUI:

struct PhoneTypeDropdown: View {
    let phoneTypes:[PhoneType] = [.Cell, .Work, .Landline]
    @State var isExpanded: Bool

    var body : some View {
        VStack (spacing: 0) {
            HStack {
                Text("select type").font(.footnote)
                Spacer()
                Image(systemName: Constants.Design.Image.IconString.ChevronDown)
                .resizable()
                    .frame(width: Constants.Design.Measurement.DropDownIconWidth,
                           height: Constants.Design.Measurement.DropDownIconHeight)
            }
            .padding(Constants.Design.Measurement.PadMin)
            .background(Constants.Design.Colors.LightGrey)
            .cornerRadius(Constants.Design.Measurement.CornerRadius)
            .onTapGesture {
                self.isExpanded.toggle()
            }
            
            if isExpanded {
                VStack (spacing: 0){
                    ForEach(0 ..< phoneTypes.count) { i in
                        Button(self.phoneTypes[i].description, action: {
                            print("button tapped")
                            self.isExpanded.toggle()
                        })
                            .buttonStyle(DropDownButtonStyle())
                        
                        if i != self.phoneTypes.count - 1 {
                            Divider()
                                .padding(.vertical, 0)
                                .padding(.horizontal, Constants.Design.Measurement.Pad)
                                .foregroundColor(Constants.Design.Colors.DarkGrey)
                        }
                    }
                }.background(Constants.Design.Colors.LightGrey)
                .cornerRadius(Constants.Design.Measurement.CornerRadiusMin)
                .padding(.top, Constants.Design.Measurement.PadMin)
            }
        }.frame(width: Constants.Design.Measurement.PhoneTypeFieldWidth)
            .cornerRadius(Constants.Design.Measurement.CornerRadius)
    }

}

When I went to utilize this in my view, I had planned on using it as an overlay like this:

                VStack(spacing: 0) {
                    ProfileField(text: phone1,
                                 label: Constants.Content.PrimaryPhone,
                                 position: .Justified)
                        .overlay(
                            PhoneTypeDropdown(isExpanded: expandDropdown1)
                                .padding(.top, 32) //FIXME: Fix this hard-coded value.
                                .padding(.trailing, Constants.Design.Measurement.PadMax),
                            alignment: .topTrailing
                    )
                }

However, although the above code will trigger on clicking and expand the dropdown box, tapping any of the Button objects inside the dropdown box does nothing. I then tried to implement the dropdown box using a ZStack like this:

                ZStack(alignment: .topTrailing) {
                    ProfileField(text: phone1,
                                 label: Constants.Content.PrimaryPhone,
                                 position: .Justified)
                    PhoneTypeDropdown(isExpanded: expandDropdown1)
                        .padding(.top, 32) //FIXME: Fix this hard-coded value.
                        .padding(.trailing, Constants.Design.Measurement.PadMax)
                }

The dropdown box worked beautifully, expanding and collapsing as expected. However, now, when it expands, it pushes down the rest of the form instead of laying on top of the form as desired.

My question then is this: what would cause my button action to fire correctly when using the dropdown object in a ZStack as opposed to incorporating it in an overlay on an view in a VStack?

0

There are 0 best solutions below