MultipleSelectionList.swift 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. //
  2. // MultipleSelectionList.swift
  3. // LoopKitUI
  4. //
  5. // Created by Nathaniel Hamming on 2020-02-27.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. public struct MultipleSelectionList<Item>: View where Item: Hashable {
  10. var items: [Item]
  11. @Binding var selectedItems: Set<Item>
  12. var itemToDisplayableString: (Item) -> String
  13. public init(items: [Item], selectedItems: Binding<Set<Item>>, itemToDisplayableString: @escaping (Item) -> String) {
  14. self.items = items
  15. _selectedItems = selectedItems
  16. self.itemToDisplayableString = itemToDisplayableString
  17. }
  18. public var body: some View {
  19. List(items, id:\.self) { item in
  20. MultipleSelectionRow<Item>(item: item,
  21. selectedItems: self.$selectedItems,
  22. itemToDisplayableString: self.itemToDisplayableString)
  23. }
  24. .insetGroupedListStyle()
  25. }
  26. }
  27. struct MultipleSelectionRow<Item>: View where Item: Hashable {
  28. var item: Item
  29. @Binding var selectedItems: Set<Item>
  30. var itemToDisplayableString: (Item) -> String
  31. var isSelected: Bool {
  32. selectedItems.contains(item)
  33. }
  34. var body: some View {
  35. HStack {
  36. Button(action: {
  37. if self.isSelected {
  38. self.selectedItems.remove(self.item)
  39. } else {
  40. self.selectedItems.insert(self.item)
  41. }
  42. }) {
  43. Text(self.itemToDisplayableString(item))
  44. .foregroundColor(.primary)
  45. }
  46. Spacer()
  47. if isSelected {
  48. Image(systemName: "checkmark.circle.fill")
  49. .foregroundColor(.accentColor)
  50. }
  51. }
  52. }
  53. }
  54. struct SelectableList_Previews: PreviewProvider {
  55. static var previews: some View {
  56. PreviewWrapper()
  57. }
  58. struct PreviewWrapper: View {
  59. static var fruit = ["Orange", "Apple", "Banana", "Peach", "Grape"]
  60. @State(initialValue: [fruit[1], fruit[3]]) var selectedFruit: Set<String>
  61. var body: some View {
  62. MultipleSelectionList<String>(items: SelectableList_Previews.PreviewWrapper.fruit,
  63. selectedItems: $selectedFruit,
  64. itemToDisplayableString: { String(describing:$0) })
  65. }
  66. }
  67. }