Я создаю один список выбора для использования в разных местах моего приложения.
Вопросы:
Есть ли простое решение, которое я не знаю?
Если нет, как я могу закончить свое текущее решение?
Моя цель:
- Список, в котором всегда выбран только один элемент или выбран один или ни один элемент(в зависимости от конфигурации)
- Прозрачный фон
- При выборе элемента - выполнить действие, заданное в качестве параметра с помощью метода init (). (Для этого действия требуется информация о выбранном элементе.)
- Изменить данные списка программно и сбросить выбор до первого элемента
Мое текущее решение выглядит следующим образом: Вид списка с выбранным вторым элементом
Я не могу использовать Пикер, потому что внешнее действие (цель № 3) отнимает много времени. Поэтому я думаю, что это не будет работать гладко. Скорее всего, есть решение моей проблемы в SwiftUI, но я либо пропустил его, потому что я новичок в swift, либо, как я понимаю, еще не все отлично работает в SwiftUI, например: прозрачный фон для List (вот почему мне нужно было очиститьbackground в init ()).
Поэтому я сам начал осуществлять выделение и остановился на этом: мое текущее решение не обновляет представление при нажатии на элемент (кнопку). (Только выходя и возвращаясь к просмотру обновлений страницы). И все же можно выбрать несколько элементов.
import SwiftUI
struct ModuleList: View {
var modules: [Module] = []
@Binding var selectionKeeper: Int
var Action: () -> Void
init(list: [Module], selection: Binding<Int>, action: @escaping () -> Void) {
UITableView.appearance().backgroundColor = .clear
self.modules = list
self._selectionKeeper = selection
self.Action = action
}
var body: some View {
List(){
ForEach(0..<modules.count) { i in
ModuleCell(module: self.modules[i], action: { self.changeSelection(index: i) })
}
}.background(Constants.colorTransparent)
}
func changeSelection(index: Int){
modules[selectionKeeper].isSelected = false
modules[index].isSelected = true
selectionKeeper = index
self.Action()
}
}
struct ModuleCell: View {
var module: Module
var Action: () -> Void
init(module: Module, action: @escaping () -> Void) {
UITableViewCell.appearance().backgroundColor = .clear
self.module = module
self.Action = action
}
var body: some View {
Button(module.name, action: {
self.Action()
})
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
.modifier(Constants.CellSelection(isSelected: module.isSelected))
}
}
class Module: Identifiable {
var id = UUID()
var name: String = ""
var isSelected: Bool = false
var address: Int
init(name: String, address: Int){
self.name = name
self.address = address
}
}
let testLines = [
Module(name: "Line1", address: 1),
Module(name: "Line2", address: 3),
Module(name: "Line3", address: 5),
Module(name: "Line4", address: 6),
Module(name: "Line5", address: 7),
Module(name: "Line6", address: 8),
Module(name: "Line7", address: 12),
Module(name: "Line8", address: 14),
Module(name: "Line9", address: 11),
Module(name: "Line10", address: 9),
Module(name: "Line11", address: 22)
]
Проверка некоторых идей:
Попытка добавить массив @State (isSelected: Bool) в ModuleList и связать его с параметром Module isSelectedэто МОЖЕТ обновить представление ... Но не удалось затем заполнить этот массив в init (), потому что параметр массива @State останется пустым после .append () ... Возможно, добавление функции setList решило бы эту проблему, и моя цель Nr. 4. Но я не был уверен, что это действительно обновит мой взгляд.
struct ModuleList: View {
var modules: [Module] = []
@State var selections: [Bool] = []
init(list: [String]) {
UITableView.appearance().backgroundColor = .clear
selections = [Bool] (repeating: false, count: list.count) // stays empty
let test = [Bool] (repeating: false, count: list.count) // testing: works as it should
selections = test
for i in 0..<test.count { // for i in 0..<selections.count {
selections.append(false)
modules.append(Module(name: list[i], isSelected: $selections[i])) // Error selections is empty
}
}
var body: some View {
List{
ForEach(0..<modules.count) { i in
ModuleCell(module: self.modules[i], action: { self.changeSelection(index: i) })
}
}.background(Constants.colorTransparent)
}
func changeSelection(index: Int){
modules[index].isSelected = true
}
}
struct ModuleCell: View {
var module: Module
var Method: () -> Void
init(module: Module, action: @escaping () -> Void) {
UITableViewCell.appearance().backgroundColor = .clear
self.module = module
self.Method = action
}
var body: some View {
Button(module.name, action: {
self.Method()
})
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
.modifier(Constants.CellSelection(isSelected: module.isSelected))
}
}
struct Module: Identifiable {
var id = UUID()
var name: String = ""
@Binding var isSelected: Bool
init(name: String, isSelected: Binding<Bool>){
self.name = name
self._isSelected = isSelected
}
}
let testLines = ["Line1","Line2","Line3","Line4"
]