Search code examples
swiftscrollviewswiftui

ScrollView causes buggy buttons in SwiftUI


I've been trying to create a form in SwiftUI but because of the limitations using "Form()" I instead chose to create a ScrollView with a ForEach loop that contains a button. When I run the project and I try to click on the buttons it clicks the incorrect one, unless I scroll the view. I am new in SwiftUI and I have not been able to figure it out.

I tried making the ScrollView in different sizes and it doesn't seem to be related

struct DropDown: View {

var datos: [String]
var categoria: String

@State var titulo: String = "Seleccione"
@State var expand = false

var body: some View {

    VStack {
        Text(categoria).fontWeight(.heavy).foregroundColor(.white)
        HStack {
            Text(titulo).fontWeight(.light).foregroundColor(.white)
            Image(systemName: expand ? "chevron.up" : "chevron.down").resizable().frame(width: 10, height: 6).foregroundColor(.white)

        }.onTapGesture {
            self.expand.toggle()
        }

        if expand {
            ScrollView(showsIndicators: true) {
                ForEach(0..<self.datos.count){ nombre in
                    Button(action: {
                        print(self.datos[nombre])
                        self.titulo = self.datos[nombre]
                        self.expand.toggle()
                        diccionarioDatos[self.categoria] = self.titulo
                        print(diccionarioDatos)
                    }) {
                        Text(self.datos[nombre]).foregroundColor(.white)
                    }
                }
            }
            .frame(maxHeight: 150)
            .fixedSize()
        }
    }
    .padding()
    .background(LinearGradient(gradient: .init(colors: [.blue, .green]), startPoint: .top, endPoint: .bottom))
    .cornerRadius(20)
    .animation(.spring())
}

}

I clicked on "2018" under "Modelo" and "2015" got selected for some reason

This is how the dropdown menu looks like


Solution

  • As I tested the observed behaviour is due to order of animatable properties. In your case moving rounding corners into background itself solves the problem.

    So instead of

    .background(
        LinearGradient(gradient: .init(colors: [.blue, .green]), startPoint: .top, endPoint: .bottom)
    )
    .cornerRadius(20)
    

    Use

    .background(
        LinearGradient(gradient: .init(colors: [.blue, .green]), startPoint: .top, endPoint: .bottom)
            .cornerRadius(20)
    )