ios - 具有切换子视图和选择手势的列表项
问题描述
我有一个列表和包含Toggle
视图的项目。我想分别处理选择和切换状态。未选择列表项时应禁用切换。问题是:
- 第一次点击 - 选择列表项。(
selected = true
) - 点击切换 - 设置
selection = false
在 UIKit 上,Button/Switch/etc... 抓住“点击”,不要进入 TableView 选择状态。
struct ListView: View {
@State var selected = Set<Int>()
let items = (1...10).map { ItemDataModel(id: $0) }
var body: some View {
List(items) { item in
ListItemView(dataModel: item)
.onTapGesture { if !(selected.remove(item.id) != .none) { selected.insert(item.id) }}
}
}
}
struct ListItemView: View {
@ObservedObject var dataModel: ItemDataModel
var body: some View {
HStack {
Text(dataModel.title)
Spacer()
Toggle(
isOn:Binding<Bool>(get: {dataModel.isOn}, set: {dataModel.isOn = $0}),
label: { Text("toggle") })
}
}
}
class ItemDataModel: Hashable, Identifiable, ObservableObject {
let id: Int
let title: String
@Published var isOn: Bool = false
init(id: Int) {
self.id = id
title = "item \(id)"
}
func hash(into hasher: inout Hasher) {
hasher.combine(title)
}
static func == (lhs: ItemDataModel, rhs: ItemDataModel) -> Bool {
return lhs.id == rhs.id
}
}
[请尽量忽略语法错误(如果存在)并专注于手势问题]
解决方案
首先,你的[ItemDataModel]
数组应该移到身体之外,所以它不会每次都重新创建:
struct ListView: View {
@State var selected = Set<Int>()
let items = (1...10).map(ItemDataModel.init) // move outside the `body`
var body: some View {
VStack {
Text(String(describing: selected))
List(items) { item in
ListItemView(dataModel: item)
.onTapGesture { if !(selected.remove(item.id) != .none) { selected.insert(item.id) }}
}
}
}
}
然后,确保Toggle
in yourListItemView
不会占用所有空间(这是默认行为)并附onTapGesture
加以覆盖父母的手势:
struct ListItemView: View {
@ObservedObject var dataModel: ItemDataModel
var body: some View {
HStack {
Text(dataModel.title)
// Text("toggle") // if necessary add Toggle's label as `Text`
Spacer()
Toggle("", isOn: $dataModel.isOn) // use another initialiser
.fixedSize() // limit Toggle's width
.background(Color.red) // debug-only, to see the real frame
.onTapGesture {} // override tap gestures
}
.contentShape(Rectangle()) // make empty space *clickable*
}
}
推荐阅读
- javascript - Froala 编辑器 v3 渲染按钮全部在一行上,没有下拉菜单
- c# - 如何仅通过将其作为基类类型来创建与另一个实例相同类型的类的新对象实例?
- c# - 我想要扩展属性值作为列名
- sql - 反转postgres中的列
- javascript - 动态添加按钮显示错误的值jquery
- javascript - 创建文件对象而不保存
- rust - 为什么我不能调用 Global.alloc_zeroed()
- matplotlib - matplotlib 图形输出一团糟
- javascript - (React Native) 组件异常 - 文本字符串必须在
零件 - azure-data-explorer - Azure 数据资源管理器如何工作。在内部,它使用哪个数据库