28
loading...
This website collects cookies to deliver better user experience
List
view 😭. It's not big deal, but it was one of my expectations from conference. Okay let's do it ourselves 💪struct Country: Identifiable {
let id = UUID()
let name: String
}
if else
conditional statement.struct ContentView: View {
@State var countries: [Country] = [] // Data source
var body: some View {
if countries.isEmpty {
Text("No Countries") // Placeholder
.font(.largeTitle)
} else {
List(countries) { country in // List countires
Text(country.name)
.font(.title)
}
}
}
}
if else
idea and move logic show/hide placeholder to custom view, call it EmptyList
:struct EmptyList<Items: RandomAccessCollection, ListRowView: View, PlaceholderView: View>: View where Items.Element: Identifiable {
private let items: Items
private let listRowView: (Items.Element) -> ListRowView
private let placeholderView: () -> PlaceholderView
/// - Parameters:
/// - items: Source data for List. Item must implement Identifiable protocol
/// - listRowView: View displayed for each source Item
/// - placeholderView: Placeholder. View displayed when the items collection isEmpty
init(_ items: Items,
@ViewBuilder listRowView: @escaping (Items.Element) -> ListRowView,
@ViewBuilder placeholderView: @escaping () -> PlaceholderView) {
self.items = items
self.listRowView = listRowView
self.placeholderView = placeholderView
}
var body: some View {
if !items.isEmpty {
List { // List countires
ForEach(items) { item in
self.listRowView(item)
}
}
} else {
placeholderView()
}
}
}
EmptyList
is very easy. First parameter - data source, second parameter - list row view, and finally third parameter - placeholder view.struct ContentView: View {
@State var countries: [Country] = [] // Data source
var body: some View {
EmptyList(countries, // Data items
listRowView: { country in // List row view
Text(country.name)
.font(.title)
}, placeholderView: {
Text("No Countries") // Placeholder
.font(.largeTitle)
})
}
}
EmptyList
view, and if want to add some ViewModifier-s to the list, need for more efforts and modify codestruct EmptyDataModifier<Placeholder: View>: ViewModifier {
let items: [Any]
let placeholder: Placeholder
@ViewBuilder
func body(content: Content) -> some View {
if !items.isEmpty {
content
} else {
placeholder
}
}
}
EmptyDataModifier
:struct ContentView: View {
@State var countries: [Country] = [] // Data source
var body: some View {
List(countries) { country in
Text(country.name)
.font(.title)
}
.modifier(EmptyDataModifier(
items: countries,
placeholder: Text("No Countries").font(.title)) // Placeholder
)
}
}
EmptyDataModifier
only for List
.extension List {
func emptyListPlaceholder(_ items: [Any], _ placeholder: AnyView) -> some View {
modifier(EmptyDataModifier(items: items, placeholder: placeholder))
}
}
struct ContentView: View {
@State var countries: [Country] = [] // Data source
var body: some View {
List(countries) { country in
Text(country.name)
.font(.title)
}
.emptyListPlaceholder(
countries,
AnyView(ListPlaceholderView()) // Placeholder
)
}
}
List
viewViewModifier
.