Benutzerdefinierte Listen-Sektionen in SwiftUI


Im Vergleich zu einem UITableView ist die List aus dem SwiftUI-Framework ein unkompliziertes Steuerelement. Ein gewaltiger Schritt auf dem Weg zu einfachem und übersichtlichem Programmcode. Vorbei sind die Zeiten von Methodenaufrufen, mit denen eine Tabelle nacheinander die Anzahl der Zellen, die Anzahl der Sektionen und die Tabellenzellen anforderte. Wird in SwiftUI eine Tabelle benötigt, kann man diese problemlos mit einer List realisieren und mit einer ForEach-Schleife füllen. Wenn es ganz einfach sein soll, funktioniert es ohne Schleife und mit Objekten, die im Programmcode hinterlegt sind. Für jeden Eintrag in der Liste ein Objekt. Zum Beispiel vom Typ Text, wie es das folgende Beispiel zeigt.

struct ContentViewView {

    

    init() {

        // Entfernt die Trennlinien unterhalb der gefüllten Liste

        UITableView.appearance().tableFooterView = UIView()

    }

    

    var bodysome View {

        List {

            // Obstsorten

            Text("Apfel")

            Text("Erdbeere")

            Text("Kirsche")

            Text("Pfirsich")

            Text("Zitrone")

            // Gemüsesorten

            Text("Gurke")

            Text("Paprika")

            Text("Spinat")

            Text("Tomate")

            Text("Zucchini")

        }

    }

}

Stacks Image 27

Die Kommentare im Code unterteilen den Inhalt der Liste in Obst und Gemüse. Diese Unterteilung ist aber nur für den Entwickler sichtbar. Auf der grafischen Oberfläche werden sämtliche Bezeichnungen gemeinsam und untereinander in einer Tabelle angezeigt. In vielen Fällen kann diese Art der Darstellung ausreichen. Enthält eine List jedoch viele Einträge, wird es für den Nutzer schwieriger, Informationen zu finden. Zwar sind in diesem Beispiel alle Namen alphabetisch sortiert, aber nur innerhalb ihrer Kategorie. Dass die Zitrone in der Mitte der Auflistung steht, ist ungünstig und unerwartet. Es wäre für den Anwender leichter, wenn die verschiedenen Obst- und Gemüsesorten nicht nur im Code gruppiert wären, sondern ebenfalls auf der grafischen Oberfläche. In SwiftUI können Gruppierung innerhalb einer List mit einer Section realisiert werden.

struct ContentViewView {

    

    init() {

        // Entfernt die Trennlinien unterhalb der gefüllten Liste

        UITableView.appearance().tableFooterView = UIView()

    }

    

    var bodysome View {

        List {

            Section(header: Text("Obstsorten")) {

                Text("Apfel")

                Text("Erdbeere")

                Text("Kirsche")

                Text("Pfirsich")

                Text("Zitrone")

            }

            Section(header: Text("Gemüsesorten"))

            {

                Text("Gurke")

                Text("Paprika")

                Text("Spinat")

                Text("Tomate")

                Text("Zucchini")

            }

        }

    }

}

Stacks Image 61

Mit einer Text-Struktur im Header der Section wird die Liste zwar wie gewünscht unterteilt, ansehnlich ist das Ergebnis aber nicht. Ohne Anpassungen erzeugt SwiftUI einen schwarzen Text auf einem hellgrauen Hintergrund. In vielen Fällen wird die Section mit diesem Erscheinungsbild nicht zum Design der App passen. Anpassungen sind aber realisierbar, denn jede Art von View kann als Header verwendet werden. Es gibt keine Einschränkung, die ausschließlich einen Text erlaubt. Sogar komplett neue Views sind nicht ausgeschlossen, wie der folgende Codeausschnitt zeigt.

struct SectionHeaderView

{

    var headlineText : String

    let backColorColor

    let foreColorColor

    

    var bodysome View {

            HStack {

                Text(headlineText)

                    .font(.largeTitle)

                    .foregroundColor(foreColor)

                    .padding(EdgeInsets(top: 5, leading: 15, bottom: 5, trailing: 0))

                Spacer()

            }

        .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))

        .background(backColor)

    }

}

SectionHeader ist eine von View abgeleitete Struktur und somit geeignet, die Aufgabe eine Gruppenunterteilung zu übernehmen. Die Struktur hat drei Eigenschaften: Den anzuzeigenden Text, die Hintergrundfarbe und die Farbe für den Text. Leicht könnten Grafiken oder Symbole in dem Header angezeigt werden, doch darauf wurde in diesem Beispiel verzichtet.

Der Einsatz ist anschließend einfach. Statt einer Text-Struktur wird für den Header einer Sektion eine Instanz von SectionHeader übergeben. Die Struktur benötigt für eine erfolgreiche Instanziierung Werte für ihre drei Eigenschaften. Diese werden wiederum an SectionHeader übergeben. Glücklicherweise sind die Anweisungen kurz genug, um sie ineinander verschachteln zu können.

struct ContentViewView {

    

    init() {

        // Entfernt die Trennlinien unterhalb der gefüllten Liste

        UITableView.appearance().tableFooterView = UIView()

    }

    

    var bodysome View {

        List {

            Section(header: SectionHeader(headlineText: "Obstsorten", backColor: Color.white, foreColor: Color(.systemBlue)) )

            {

                Text("Apfel")

                Text("Erdbeere")

                Text("Kirsche")

                Text("Pfirsich")

                Text("Zitrone")

            }

            Section(header: SectionHeader(headlineText: "Gemüsesorten", backColor: Color.white, foreColor: Color(.systemRed)) )

            {

                Text("Gurke")

                Text("Paprika")

                Text("Spinat")

                Text("Tomate")

                Text("Zucchini")

            }

        }

    }

}

Stacks Image 59

Geschrieben am: 15.05.2020
Technologien: Swift, SwiftUI, macOS, iOS