diff --git a/README.md b/README.md index 0564fd9..5457170 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,35 @@ AdvancedList(yourData, content: { item in .lineLimit(nil) }, loadingStateView: { Text("Loading ...") -}, pagination: .noPagination) +}) +``` + +### 🆕 Custom List view + +Starting from version `6.0.0` you can use a custom list view instead of the `SwiftUI` `List` used under the hood. As an example you can now easily use the **LazyVStack** introduced in **iOS 14** if needed. + +Upgrade from version `5.0.0` **without breaking anything**. Simply add the **listView parameter** after the upgrade: + +```swift +AdvancedList(yourData, listView: { rows in + if #available(iOS 14, macOS 11, *) { + ScrollView { + LazyVStack(alignment: .leading, content: rows) + .padding() + } + } else { + List(content: rows) + } +}, content: { item in + Text("Item") +}, listState: $listState, emptyStateView: { + Text("No data") +}, errorStateView: { error in + Text(error.localizedDescription) + .lineLimit(nil) +}, loadingStateView: { + Text("Loading ...") +}) ``` ### 📄 Pagination @@ -91,7 +119,7 @@ AdvancedList(yourData, content: { item in .lineLimit(nil) }, loadingStateView: { Text("Loading ...") -}, pagination: .noPagination) +}) .onMove { (indexSet, index) in // move me } @@ -130,7 +158,7 @@ AdvancedList(yourData, content: { item in } }, loadingStateView: { Text("Loading ...") -}, pagination: .noPagination) +}) ``` For more examples take a look at [AdvancedList-SwiftUI](https://github.com/crelies/AdvancedList-SwiftUI). diff --git a/Sources/AdvancedList/private/Models/AnyAdvancedListPagination.swift b/Sources/AdvancedList/private/Models/AnyAdvancedListPagination.swift index 34fe3fb..adbb5e0 100644 --- a/Sources/AdvancedList/private/Models/AnyAdvancedListPagination.swift +++ b/Sources/AdvancedList/private/Models/AnyAdvancedListPagination.swift @@ -1,6 +1,6 @@ // // AnyAdvancedListPagination.swift -// +// AdvancedList // // Created by Christian Elies on 31.07.20. // diff --git a/Sources/AdvancedList/private/Models/ListState+error.swift b/Sources/AdvancedList/private/Models/ListState+error.swift index 0308d24..f38a551 100644 --- a/Sources/AdvancedList/private/Models/ListState+error.swift +++ b/Sources/AdvancedList/private/Models/ListState+error.swift @@ -1,6 +1,6 @@ // // ListState+error.swift -// +// AdvancedList // // Created by Christian Elies on 02.08.20. // diff --git a/Sources/AdvancedList/public/Models/AdvancedListPagination.swift b/Sources/AdvancedList/public/Models/AdvancedListPagination.swift index b07eb2f..5de7ce5 100644 --- a/Sources/AdvancedList/public/Models/AdvancedListPagination.swift +++ b/Sources/AdvancedList/public/Models/AdvancedListPagination.swift @@ -1,6 +1,6 @@ // // AdvancedListPagination.swift -// +// AdvancedList // // Created by Christian Elies on 15.08.19. // diff --git a/Sources/AdvancedList/public/Models/AdvancedListPaginationState.swift b/Sources/AdvancedList/public/Models/AdvancedListPaginationState.swift index de74af9..fdf77a1 100644 --- a/Sources/AdvancedList/public/Models/AdvancedListPaginationState.swift +++ b/Sources/AdvancedList/public/Models/AdvancedListPaginationState.swift @@ -1,6 +1,6 @@ // // AdvancedListPaginationState.swift -// +// AdvancedList // // Created by Christian Elies on 17.08.19. // diff --git a/Sources/AdvancedList/public/Models/AdvancedListPaginationType.swift b/Sources/AdvancedList/public/Models/AdvancedListPaginationType.swift index e84397c..1224e96 100644 --- a/Sources/AdvancedList/public/Models/AdvancedListPaginationType.swift +++ b/Sources/AdvancedList/public/Models/AdvancedListPaginationType.swift @@ -1,6 +1,6 @@ // // AdvancedListPaginationType.swift -// +// AdvancedList // // Created by Christian Elies on 16.08.19. // diff --git a/Sources/AdvancedList/private/Models/AnyDynamicViewContent.swift b/Sources/AdvancedList/public/Models/AnyDynamicViewContent.swift similarity index 52% rename from Sources/AdvancedList/private/Models/AnyDynamicViewContent.swift rename to Sources/AdvancedList/public/Models/AnyDynamicViewContent.swift index 6f3285f..8d727d0 100644 --- a/Sources/AdvancedList/private/Models/AnyDynamicViewContent.swift +++ b/Sources/AdvancedList/public/Models/AnyDynamicViewContent.swift @@ -1,17 +1,19 @@ // // AnyDynamicViewContent.swift -// +// AdvancedList // // Created by Christian Elies on 20.11.19. // import SwiftUI -struct AnyDynamicViewContent: DynamicViewContent { +/// Type erased dynamic view content that generates views from an underlying collection of data. +public struct AnyDynamicViewContent: DynamicViewContent { private let view: AnyView - private(set) var data: AnyCollection - var body: some View { view } + public private(set) var data: AnyCollection + + public var body: some View { view } init(_ view: View) { self.view = AnyView(view) diff --git a/Sources/AdvancedList/public/Views/AdvancedList.swift b/Sources/AdvancedList/public/Views/AdvancedList.swift index 0e174e5..155e505 100644 --- a/Sources/AdvancedList/public/Views/AdvancedList.swift +++ b/Sources/AdvancedList/public/Views/AdvancedList.swift @@ -12,7 +12,8 @@ import SwiftUI /// An `advanced` container that presents rows of data arranged in a single column. /// Built-in `empty`, `error` and `loading` state. /// Supports `lastItem` or `thresholdItem` pagination. -public struct AdvancedList : View where Data.Element: Identifiable { +public struct AdvancedList : View where Data.Element: Identifiable { + public typealias Rows = () -> AnyDynamicViewContent public typealias OnMoveAction = Optional<(IndexSet, Int) -> Void> public typealias OnDeleteAction = Optional<(IndexSet) -> Void> @@ -20,6 +21,7 @@ public struct AdvancedList ListView)? private var content: (Data.Element) -> Content private var listState: Binding private let emptyStateView: () -> EmptyStateView @@ -33,6 +35,30 @@ public struct AdvancedList ListView, @ViewBuilder content: @escaping (Data.Element) -> Content, listState: Binding, @ViewBuilder emptyStateView: @escaping () -> EmptyStateView, @ViewBuilder errorStateView: @escaping (Error) -> ErrorStateView, @ViewBuilder loadingStateView: @escaping () -> LoadingStateView) { + self.data = data + self.listView = listView + self.content = content + self.listState = listState + self.emptyStateView = emptyStateView + self.errorStateView = errorStateView + self.loadingStateView = loadingStateView + configurations = [] + } +} + +extension AdvancedList where ListView == List { + /// Initializes the list with the given values. + /// Uses the native `SwiftUI` `List` as list view. + /// + /// - Parameters: + /// - data: The data for populating the list. /// - content: A view builder that creates the view for a single row of the list. /// - listState: A binding to a property that determines the state of the list. /// - emptyStateView: A view builder that creates the view for the empty state of the list. @@ -46,6 +72,7 @@ public struct AdvancedList Self { var result = self result.configurations.append(configuration) return result } - private func getListView() -> some View { - List { - configurations - .reduce(AnyDynamicViewContent(ForEach(data) { item in - getItemView(item) - })) { (currentView, configuration) in configuration(currentView) } - } + func getListView(rows: Rows) -> List { + List(content: rows) + } + + func rows() -> AnyDynamicViewContent { + configurations + .reduce( + AnyDynamicViewContent( + ForEach(data) { item in + getItemView(item) + } + ) + ) { (currentView, configuration) in configuration(currentView) } } - private func getItemView(_ item: Data.Element) -> some View { + func getItemView(_ item: Data.Element) -> some View { content(item) .onAppear { listItemAppears(item) @@ -131,7 +166,7 @@ extension AdvancedList { } } - private func listItemAppears(_ item: Data.Element) { + func listItemAppears(_ item: Data.Element) { guard let pagination = pagination else { return }