SwiftUI:如何检测List已选中列表项的二次点击事件
解决方案:自定义Selection绑定实现重复选中检测
你可以通过重写selection绑定的set逻辑实现重复选中的响应,该方案完全适配SidebarListStyle的行点击规则,不会出现onTapGesture仅能响应文字区域点击的问题。
实现步骤
- 在父视图中构造自定义绑定
将原来直接传入的$selection替换为自定义绑定实例,在set方法中无论新值与旧值是否相等,都执行你需要的业务逻辑:
// 父视图原有状态声明 @State private var selection: String? // 调用NavList时替换为以下绑定参数 NavList( listItems: yourItemArray, selection: Binding( get: { selection }, set: { newValue in // 只要有点击选中动作触发set,就执行该段逻辑,重复选中同一项也会触发 if let targetId = newValue { debugPrint("触发选中逻辑,项ID:\(targetId)") // 此处添加你的业务逻辑,如手动刷新对应视图等 } // 若需要让重复选中也触发视图重绘,可添加以下代码 if newValue == selection { // 先置空再赋值,强制触发状态变化 selection = nil DispatchQueue.main.async { selection = newValue } } else { selection = newValue } } ) )
- (可选)将逻辑封装在NavList内部
如果不需要父视图感知重复选中动作,也可以直接在NavList内部处理绑定逻辑,修改后的NavList代码如下:
struct NavList: View { @Binding private var externalSelection: String? private var listItems: [NavItem] // 内部自定义绑定 private var selection: Binding<String?> { Binding( get: { externalSelection }, set: { newValue in if let targetId = newValue { // 此处添加你的业务逻辑 debugPrint("选中项ID:\(targetId)") } if newValue == externalSelection { externalSelection = nil DispatchQueue.main.async { externalSelection = newValue } } else { externalSelection = newValue } } ) } init(listItems: [NavItem], selection: Binding<String?>) { self.listItems = listItems self._externalSelection = selection } var body: some View { List (selection: selection) { ForEach(listItems, id:\.id) { item in Text(item.text) .tag(item.id) } } .listStyle(SidebarListStyle()) } }
方案说明
该方案复用了List原生的选中逻辑,点击列表任意区域(包括边距空白处)都会触发绑定的set方法,完美适配SidebarListStyle的交互规则,无需额外添加手势修饰器。
内容的提问来源于stack exchange,提问作者Lae
相关产品推荐
相关产品推荐

