SwiftUI 列表空状态视图/修改器

Cra*_*0ek 6 list empty-list swift swiftui

我想知道当列表的数据源为空时如何在列表中提供一个空的状态视图。下面是一个示例,我必须将它包装在一个if/else语句中。有没有更好的替代方法,或者有没有办法在 a 上创建一个修饰符,List这将使这成为可能,即List.emptyView(Text("No data available...")).

import SwiftUI

struct EmptyListExample: View {

    var objects: [Int]

    var body: some View {
        VStack {
            if objects.isEmpty {
                Text("Oops, loos like there's no data...")
            } else {
                List(objects, id: \.self) { obj in
                    Text("\(obj)")
                }
            }
        }
    }

}

struct EmptyListExample_Previews: PreviewProvider {

    static var previews: some View {
        EmptyListExample(objects: [])
    }

}
Run Code Online (Sandbox Code Playgroud)

Lor*_*ley 28

我非常喜欢为此使用overlay附加的,List因为它是一个非常简单、灵活的修饰符:

struct EmptyListExample: View {

    var objects: [Int]

    var body: some View {
        VStack {
            List(objects, id: \.self) { obj in
                Text("\(obj)")
            }
            .overlay(Group {
                if objects.isEmpty {
                    Text("Oops, looks like there's no data...")
                }
            })
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它的优点是可以很好地居中,如果您使用带有图像等的较大占位符,它们将填充与列表相同的区域。


paw*_*222 8

解决方案之一是使用@ViewBuilder

struct EmptyListExample: View {
    var objects: [Int]

    var body: some View {
        listView
    }

    @ViewBuilder
    var listView: some View {
        if objects.isEmpty {
            emptyListView
        } else {
            objectsListView
        }
    }

    var emptyListView: some View {
        Text("Oops, loos like there's no data...")
    }

    var objectsListView: some View {
        List(objects, id: \.self) { obj in
            Text("\(obj)")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我很高兴您回答这个问题,但是使用视图生成器有优势吗?OG问题中的“if/else”对我来说更容易阅读 (3认同)

gan*_*ena 7

对于iOS 17,您可以使用ContentUnavailableView

ContentUnavailableView(
   "Favourite list empty",
   systemImage: "star",
   description: "Add new item to favourite list")
)
Run Code Online (Sandbox Code Playgroud)

如果你愿意,你可以添加一个 foregroundStyle 并且所有文本和图像都将具有与相同颜色不同的颜色:

ContentUnavailableView(
   "Favourite list empty",
   systemImage: "star",
   description: "Add new item to favourite list")
)
.foregroundStyle(.blue)
Run Code Online (Sandbox Code Playgroud)

如果你想添加一个动作,你可以执行下面的代码:

ContentUnavailableView {
     Label("Favourite list empty", systemImage: "star")
} description: {
     Text("Add new item to favourite list")
} actions: {
     Button("Tap here") {
        // add the action here
     }
     .buttonStyle(.borderedProminent)
}
Run Code Online (Sandbox Code Playgroud)

用法可以在这里找到:https://www.avanderlee.com/swiftui/contentunavailableview-handling-empty-states/ 谢谢@Amos


Edw*_*rey 6

您可以创建一个自定义修饰符,当您的列表为空时,它会替换占位符视图。像这样使用它:

List(items) { item in
    Text(item.name)
}
.emptyPlaceholder(items) {
    Image(systemName: "nosign")
}
Run Code Online (Sandbox Code Playgroud)

这是修改器:

struct EmptyPlaceholderModifier<Items: Collection>: ViewModifier {
    let items: Items
    let placeholder: AnyView

    @ViewBuilder func body(content: Content) -> some View {
        if !items.isEmpty {
            content
        } else {
            placeholder
        }
    }
}

extension View {
    func emptyPlaceholder<Items: Collection, PlaceholderView: View>(_ items: Items, _ placeholder: @escaping () -> PlaceholderView) -> some View {
        modifier(EmptyPlaceholderModifier(items: items, placeholder: AnyView(placeholder())))
    }
}
Run Code Online (Sandbox Code Playgroud)