如何使用SwiftUI进行单选列表
我正在创建单个选择列表,以便在我的应用程序中的不同位置使用如何使用SwiftUI进行单选列表,swift,list,swiftui,selection,ios13,Swift,List,Swiftui,Selection,Ios13,我正在创建单个选择列表,以便在我的应用程序中的不同位置使用 问题: 有没有一个简单的解决办法我不知道 如果没有,我如何完成当前的解决方案 我的目标是: 始终仅选择一项或选择一项或无项的列表(取决于配置) 透明背景 在项上选择-执行通过init()方法设置为参数的操作。(该操作需要选定的项目信息。) 以编程方式更改列表数据并将所选内容重置为第一项 我当前的解决方案如下所示: 我不能使用选择器,因为外部操作(目标3)非常耗时。所以我认为它不会顺利运行。 我在SwiftUI中的问题很可能有解决方
问题: 有没有一个简单的解决办法我不知道 如果没有,我如何完成当前的解决方案
我的目标是:
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)
]
struct ContentView: View {
// Use Optional for selection.
// Instead od Set or Array like this...
// @State var selection = Set<Int>()
@State var selection = Int?.none
var body: some View {
List(selection: $selection) {
ForEach(0..<128) { _ in
Text("Sample")
}
}
}
}
导入快捷界面
结构模块列表:视图{
变量模块:[模块]=[]
@绑定变量selectionKeeper:Int
var操作:()->Void
初始化(列表:[模块],选择:绑定,操作:@escaping()->Void){
UITableView.appearance().backgroundColor=.clear
self.modules=list
self.\u selectionKeeper=选择
自我行动
}
var body:一些观点{
列表(){
ForEach(0..Void
初始化(模块:模块,操作:@escaping()->Void){
UITableViewCell.appearance().backgroundColor=.clear
self.module=模块
自我行动
}
var body:一些观点{
按钮(模块名称、操作:{
自我行动
})
.frame(最小宽度:0,最大宽度:。无穷大,对齐方式:。中心)
.modifier(常数.CellSelection(isSelected:module.isSelected))
}
}
类模块:可识别{
var id=UUID()
变量名称:String=“”
var isSelected:Bool=false
变量地址:Int
init(名称:String,地址:Int){
self.name=名称
self.address=地址
}
}
设测试线=[
模块(名称:“Line1”,地址:1),
模块(名称:“Line2”,地址:3),
模块(名称:“Line3”,地址:5),
模块(名称:“Line4”,地址:6),
模块(名称:“Line5”,地址:7),
模块(名称:“第6行”,地址:8),
模块(名称:“Line7”,地址:12),
模块(名称:“Line8”,地址:14),
模块(名称:“Line9”,地址:11),
模块(名称:“第10行”,地址:9),
模块(名称:“Line11”,地址:22)
]
测试一些想法: 尝试在ModuleList中添加@State数组of(isSelected:Bool),并将其绑定到可能更新视图的模块isSelected参数…但在init()中填充此数组失败,因为@State数组参数在.append()之后将保持为空…也许添加函数setList会解决这个问题,我的目标是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"
]
结构模块列表:视图{
变量模块:[模块]=[]
@状态变量选择:[Bool]=[]
初始化(列表:[字符串]){
UITableView.appearance().backgroundColor=.clear
selections=[Bool](重复:false,count:list.count)//保持为空
让test=[Bool](重复:false,count:list.count)//测试:正常工作
选择=测试
对于0..Selection中的i
SwiftUI目前没有一种内置的方法来选择列表中的一行并相应地更改其外观。但实际上,您已经非常接近您的答案。事实上,您的选择实际上已经起作用,但只是没有以任何方式使用
为了进行说明,请在您的ForEach
中的ModuleCell(…)
之后添加以下行:
.background(i == self.selectionKeeper ? Color.red : nil)
换句话说,“如果我的当前行(i
)与存储在selectionKeeper
中的值匹配,则将单元格涂成红色,否则,使用默认颜色。”您将看到,当您点击不同的行时,红色会跟随您的点击,显示基本选择实际上正在改变
取消选择
如果要启用取消选择,可以传入一个绑定
作为选择,并在点击当前选定行时将其设置为nil
:
struct ModuleList: View {
var modules: [Module] = []
// this is new ------------------v
@Binding var selectionKeeper: Int?
var Action: () -> Void
// this is new ----------------------------v
init(list: [Module], selection: Binding<Int?>, action: @escaping () -> Void) {
...
func changeSelection(index: Int){
if selectionKeeper != index {
selectionKeeper = index
} else {
selectionKeeper = nil
}
self.Action()
}
}
而您的ForEach
看起来
ForEach(0..<modules.count) { i in
ModuleCell(module: self.modules[i],
isSelected: i == self.selectionKeeper,
action: { self.changeSelection(index: i) })
}
ForEach(0..实现这一点的最简单方法是在包含所选列表的视图中使用@State,并将其作为@Binding传递给单元格:
struct SelectionView: View {
let fruit = ["apples", "pears", "bananas", "pineapples"]
@State var selectedFruit: String? = nil
var body: some View {
List {
ForEach(fruit, id: \.self) { item in
SelectionCell(fruit: item, selectedFruit: self.$selectedFruit)
}
}
}
}
struct SelectionCell: View {
let fruit: String
@Binding var selectedFruit: String?
var body: some View {
HStack {
Text(fruit)
Spacer()
if fruit == selectedFruit {
Image(systemName: "checkmark")
.foregroundColor(.accentColor)
}
} .onTapGesture {
self.selectedFruit = self.fruit
}
}
}
与可选的类型选择变量一起使用绑定。
列表
将只允许选择一个元素
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)
]
struct ContentView: View {
// Use Optional for selection.
// Instead od Set or Array like this...
// @State var selection = Set<Int>()
@State var selection = Int?.none
var body: some View {
List(selection: $selection) {
ForEach(0..<128) { _ in
Text("Sample")
}
}
}
}
struct ContentView:View{
//使用可选选项进行选择。
//而不是像这样的od集合或数组。。。
//@State var selection=Set()
@状态变量选择=Int?无
var body:一些观点{
列表(选择:$selection){
ForEach(0..这里有一个更通用的方法,您仍然可以根据需要扩展答案
TLDR
细部
struct SingleSelectionList:View{
可变项目:[项目]
@绑定变量selectedItem:Item?
var rowContent:(项目)->Content
var body:一些观点{
列表(项目){中的项目
行内容(项目)
.modifier(CheckmarkModifier(选中:item.id==self.selectedItem?.id))
.contentShape(矩形())
.ontapsigne{
self.selectedItem=项目
}
}
}
}
结构CheckmarkModifier:ViewModifier{
已检查变量:Bool=false
func正文(内容:内容)->某些视图{
团体{