Seltsames Verhalten der Zeilenbreiten einer List in einem VStack


Obwohl es schon seit einigen Jahren existiert, ist SwiftUI immer noch ein junges Framework und mache Dinge funktionieren nicht, wie erwartet. Entweder, weil das Framework sie falsch umsetzt, oder weil Entwickler Fehler machen. Man kann sich nie sicher sein, was der Fall ist. Seltsame Probleme entstehen dabei nicht selten bei Programmcode, der auf den ersten Blick einfach erscheint.

Der folgende Code zeigt eine SwiftUI View mit einem List-Steuerelement, das eine Liste von Städtenamen anzeigt. Wenig aufregend. Die List ist einem NavigationView untergeordnet. Die grafische Oberfläche erinnert an das UITableView-Steuerelement aus dem UIKit-Framework und die App verhält sich auch so.

struct SimpleListView {

    

    @State var searchQuery = ""

    let cities = ["Berlin","Paris""London","Tokio","Amsterdam","Madrid","Hong Kong","New York""Bern""Delhi""Shanghai"]

    

    var body: some View {

       NavigationView{

                List{

                    ForEach(self.cities.sorted() , id: \.self)   { city in

                        Text(city)

                    }

                }.navigationBarTitle("SwiftUI List Demo", displayMode: .inline)

       }

    }

}

Stacks Image 162

Die Probleme fangen an, wenn man oberhalb des List-Steuerelements noch andere Dinge anzeigen möchte. Beispielsweise ein Textfeld, mit dem der Inhalt der Liste durchsucht werden kann. Weil der View immer nur genau ein Element enthalten kann, müssen Textfeld und List in einem Container-Element eingekapselt werden. Gut geeignet ist in diesem Fall ein VStack.

struct SimpleListView {

    

    @State var searchQuery = ""

    let cities = ["Berlin","Paris""London","Tokio","Amsterdam","Madrid","Hong Kong","New York""Bern""Delhi""Shanghai"]

    

    var body: some View {

        

        NavigationView{

            VStack {

                

                TextField("Hier Text eingeben", text: $searchQuery)

                    .textFieldStyle(RoundedBorderTextFieldStyle())

                    .padding(EdgeInsets(top: 10, leading: 10, bottom: 2, trailing: 10))

                

                List{

                    ForEach(self.cities.sorted() , id: \.self)   { city in

                        Text(city)

                    }

                }

            }.navigationBarTitle("SwiftUI List Demo", displayMode: .inline)

        }

    }

}

Nach dieser Erweiterung nehmen die Zeilen des List-Steuerelementes plötzlich nicht mehr die komplette Breite der View ein und schuld daran ist nicht das Padding des TextField. Das Problem tritt auch auf, wenn sich kein weiteres Element mit in dem VStack befindet.

Stacks Image 158

Die Ursache für dieses Verhalten ist nicht bekannt, die Lösung hingegen schon und sie ist einfach. Dem List-Steuerelement muss der Style PlainListStyle zugewiesen werden. Anschließend beanspruchen die Zeilen erneut die komplette Breite der Ansicht.

struct SimpleListView {

    

    @State var searchQuery = ""

    let cities = ["Berlin","Paris""London","Tokio","Amsterdam","Madrid","Hong Kong","New York""Bern""Delhi""Shanghai"]

    

    var body: some View {

        

        NavigationView{

            VStack {

                

                TextField("Hier Text eingeben", text: $searchQuery)

                    .textFieldStyle(RoundedBorderTextFieldStyle())

                    .padding(EdgeInsets(top: 10, leading: 10, bottom: 2, trailing: 10))

                

                List{

                    ForEach(self.cities.sorted() , id: \.self)   { city in

                        Text(city)

                    }

                }.listStyle(PlainListStyle())

            }.navigationBarTitle("SwiftUI List Demo", displayMode: .inline)

        }

    }

}

Stacks Image 164

Geschrieben am: 05.01.2021
Technologien: SwiftUI, iOS