SwiftUI之List的使用

2,260 阅读2分钟

List的常规使用

List对标UIKit中的UITabView,而UITabView是我们在App开发中常用的控件之一。

1.List 静态数据展示

var body: some View {
    List{
        Text("测试展示1")
        Text("测试展示2")
        Text("测试展示3")
        Text("测试展示4")
        Text("测试展示5")
    }
}

截屏2022-06-21 17.32.40.png

2.动态数据展示和List多选

当然大部分情况下 我们创建的list数据都是动态的,这时候需要我们自己自定义展示的视图和驱动UI展示的模型数据,下面是设置List多选的实现,具体效果如下

123.gif

struct Ocean: Identifiable, Hashable{
    let name: String
    let id = UUID()
}

private var oceans = [
    Ocean(name: "Pacific"),
    Ocean(name: "Atlantic"),
    Ocean(name: "Indian"),
    Ocean(name: "Southern"),
    Ocean(name: "Arctic")
]
/// 记录选中的区域
@State private var multiSelection = Set<UUID>()
var body: some View {
    VStack{
        NavigationView {
            List(oceans,selection: $multiSelection){
                Text($0.name)
            }
            .navigationTitle("Oceans")
            .toolbar{
                EditButton()
            }
        }
        Text("已选择\(multiSelection.count)").foregroundColor(.red)
    }
}

3.List数据删除和移动

List数据删除和上下移动也是常用的功能之一,在SwiftUI上实现更加便捷。先看下效果

123.gif

@State private var fruits = [
        "Apple",
        "Banana",
        "Papaya",
        "Mango",
        "orange",
        "pineapple"
]

/// 移动和删除
func removeAndDeleteRow() -> some View {
    NavigationView {
        List{
            ForEach(fruits,id: \.self){
                Text($0)
            }
            .onDelete { fruits.remove(atOffsets: $0)}
            .onMove { fruits.move(fromOffsets: $0, toOffset: $1)}
        }
        .navigationTitle("Oceans")
        .toolbar{
            EditButton()
        }
    }
}

4.List的分组展示

List设置Group展示样式,SwiftUI提供了三种展示样式 .plain ,.group,.automatic,前两种都和之前的样式一样,最后一种是左右会添加一个边距的效果,可以自己设置看下具体样式。List实现分组设置要添加Section组件.

构造假数据

/// 设置分组展示
func setListSection() -> some View {
    NavigationView{
        List{
            ForEach(1..<6){ va in
                Section(header: Text(fruits[va])) {
                    ForEach(1..<5){ i in
                        Text("测试展示数据\(i)")
                    }
                }
            }
        }
        //设置list展示的样式
        .listStyle(.automatic)
        .navigationTitle("测试分组展示")
    }
}

123.gif

5.List设置树状结构视图

展示可折叠list,设置层级展示的树状结构 关键在于设置数据模型。分层列表需要设置树结构数据和children提供关键路径的参数来创建任意深度的分层列表。

func setFileFoldStyle() -> some View {
    struct FileItem: Hashable, Identifiable, CustomStringConvertible {
            var id: Self { self }
            var name: String
            var children: [FileItem]? = nil
            var description: String {
                switch children {
                case nil:
                    return "📄 \(name)"
                case .some(let children):
                    return children.isEmpty ? "📂 \(name)" : "📁 \(name)"
                }
            }
        }
    let fileHierarchyData: [FileItem] = [
      FileItem(name: "users", children:
        [FileItem(name: "user1234", children:
          [FileItem(name: "Photos", children:
            [FileItem(name: "photo001.jpg"),
             FileItem(name: "photo002.jpg")]),
           FileItem(name: "Movies", children:
             [FileItem(name: "movie001.mp4")]),
              FileItem(name: "Documents", children: [])
          ]),
         FileItem(name: "newuser", children:
           [FileItem(name: "Documents", children: [])
           ])
        ]),
        FileItem(name: "private", children: nil)
    ]
    return NavigationView{
        List(fileHierarchyData,children:\.children){ item in
            Text(item.description)
        }.navigationTitle(Text("可折叠list"))
    }
}

123.gif

2.Form的基本使用

Form和List在UI呈现上基本上都是一个可以滚动的视图,对数据进行分类分组进行展示。常用的有设置或检查页面中。

另外 Form 没有 .listStyle 可以设置多个样式,就是一个只有group样式的List组件。

123.gif

enum NotifyMeAboutType: String {
    case directMessages = "directMessages"
    case mentions = "mentions"
    case anything = "anything"
}

enum ProfileImageSize: String {
    case large = "Large size"
    case medium = "Medium size"
    case small = "Small size"
}

struct TestFormView: View {
    
    @State var sendReadReceipts = false
    @State var playNotificationSounds = true
    @State var notifyMeAbout: NotifyMeAboutType = .directMessages
    @State var profileImageSize: ProfileImageSize = .large
    @State var date: Date = Date()
    
    var body: some View {
        NavigationView{
            Form {
                Section(header: Text("Notifications")) {
                     DatePicker(
                         "Start Date",
                         selection: $date,
                         displayedComponents: [.date]
                     )
                     .datePickerStyle(.automatic)
                    
                    Picker("Notify Me About", selection: $notifyMeAbout) {
                        Text("Direct Messages").tag(NotifyMeAboutType.directMessages)
                        Text("Mentions").tag(NotifyMeAboutType.mentions)
                        Text("Anything").tag(NotifyMeAboutType.anything)
                    }.pickerStyle(.automatic)
                    Toggle("Play notification sounds", isOn: $playNotificationSounds)
                    Toggle("Send read receipts", isOn: $sendReadReceipts)
                }
                Section(header: Text("User Profiles")) {
                    Picker("Profile Image Size", selection: $profileImageSize) {
                        Text("Large").tag(ProfileImageSize.large)
                        Text("Medium").tag(ProfileImageSize.medium)
                        Text("Small").tag(ProfileImageSize.small)
                    }.pickerStyle(.menu)
                    /// picker有多个style 可以逐一试试其效果
                    Button("Clear Image Cache") {}
                }
            }
            .navigationTitle("测试来了")
        }
    }
}

参考资料

swiftUI--List基本使用