SwiftUI:检测点击已选择的列表项
SwiftUI: Detect click on already selected list item
我有一个包含多个项目的 List
视图。所有这些都用于导航目的,并且都是 Text
。我不能为这个应用程序使用NavigationLink
。
也就是说,我正在通过 @State
变量监视列表 selection。
@State private var selection: String?
只要视图更新,我就会打印它的值。当 selecting 列表中的不同 项时,它通常会打印每个项的唯一性 id
。
问题是在尝试 select 再次 相同的项目时 :在这种情况下,视图没有更新,我也没有看到调试消息在我的控制台中。
我希望能够按下列表项以显示视图,然后能够再次按下它,尽管它已经被 selected 因为我有逻辑我想运行(例如:手动视图刷新)。
如何检测已 select 已编辑列表项的重新select离子?
如有任何问题,请告诉我。感谢您的帮助!
更新 1
这是我使用的代码:
帮助列表项结构:
struct NavItem {
let id: String
let text: String
}
列表:
struct NavList: View {
@Binding private var selection: String?
private var listItems: [NavItem]
//note:
//selection is a @State variable declared in a parent struct and passed here.
//This is optional. I could declare it as a @state too.
init(listItems: [NavItem], selection: Binding<String?>) {
self.listItems = listItems
self._selection = selection
debugPrint(self.selection)
}
var body: some View {
List (selection: $selection) {
ForEach(listItems, id:\.id) { item in
Text(item.text)
.tag(item.id)
}
}
}
}
注1:我已经知道这个问题可以通过使用.onTapGesture
修饰符来解决。这个解决方案似乎不是最优的。我试着寻求帮助 here.
注2:在项目中,包含列表的struct
符合View
。当显示该视图时,它添加了 .listStyle(SidebarListStyle())
修饰符。这可能是相关的。
有很多方法可以做你想做的事,
用 .onTapGesture{..}
试试这个
List (selection: $selection) {
ForEach(listItems, id: \.id) { item in
Text(item.text)
.tag(item.id)
.padding(10)
.listRowInsets(.init(top: 0,leading: 0, bottom: 0, trailing: 0))
.frame(minWidth: 111, idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
.onTapGesture {
print("----> " + item.text)
}
}
}
或者您可以使用 Button
而不是 onTapGesture
;
List (selection: $selection) {
ForEach(listItems, id: \.id) { item in
Button(action: { print("----> " + item.text) }) {
Text(item.text)
}
.padding(10)
.listRowInsets(.init(top: 0,leading: 0, bottom: 0, trailing: 0))
.tag(item.id)
.frame(minWidth: 111, idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
}
}
编辑:完整测试代码:
这是我在测试中使用的代码:
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
struct NavItem {
let id: String
let text: String
}
struct ContentView: View {
@State private var listItems: [NavItem] = [NavItem(id: "1", text: "1"),
NavItem(id: "2", text: "2"),
NavItem(id: "3", text: "3"),
NavItem(id: "4", text: "4")]
@State private var selection: String?
var body: some View {
List (selection: $selection) {
ForEach(listItems, id:\.id) { item in
Button(action: { print("----> " + item.text) }) {
Text(item.text)
}
.padding(10)
.listRowInsets(.init(top: 0,leading: -5, bottom: 0, trailing: -5))
.frame(minWidth: 111, idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
.tag(item.id)
.background(Color.red) // <--- last modifier
}
}
}
}
我有一个包含多个项目的 List
视图。所有这些都用于导航目的,并且都是 Text
。我不能为这个应用程序使用NavigationLink
。
也就是说,我正在通过 @State
变量监视列表 selection。
@State private var selection: String?
只要视图更新,我就会打印它的值。当 selecting 列表中的不同 项时,它通常会打印每个项的唯一性 id
。
问题是在尝试 select 再次 相同的项目时 :在这种情况下,视图没有更新,我也没有看到调试消息在我的控制台中。
我希望能够按下列表项以显示视图,然后能够再次按下它,尽管它已经被 selected 因为我有逻辑我想运行(例如:手动视图刷新)。
如何检测已 select 已编辑列表项的重新select离子?
如有任何问题,请告诉我。感谢您的帮助!
更新 1
这是我使用的代码:
帮助列表项结构:
struct NavItem {
let id: String
let text: String
}
列表:
struct NavList: View {
@Binding private var selection: String?
private var listItems: [NavItem]
//note:
//selection is a @State variable declared in a parent struct and passed here.
//This is optional. I could declare it as a @state too.
init(listItems: [NavItem], selection: Binding<String?>) {
self.listItems = listItems
self._selection = selection
debugPrint(self.selection)
}
var body: some View {
List (selection: $selection) {
ForEach(listItems, id:\.id) { item in
Text(item.text)
.tag(item.id)
}
}
}
}
注1:我已经知道这个问题可以通过使用.onTapGesture
修饰符来解决。这个解决方案似乎不是最优的。我试着寻求帮助 here.
注2:在项目中,包含列表的struct
符合View
。当显示该视图时,它添加了 .listStyle(SidebarListStyle())
修饰符。这可能是相关的。
有很多方法可以做你想做的事,
用 .onTapGesture{..}
List (selection: $selection) {
ForEach(listItems, id: \.id) { item in
Text(item.text)
.tag(item.id)
.padding(10)
.listRowInsets(.init(top: 0,leading: 0, bottom: 0, trailing: 0))
.frame(minWidth: 111, idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
.onTapGesture {
print("----> " + item.text)
}
}
}
或者您可以使用 Button
而不是 onTapGesture
;
List (selection: $selection) {
ForEach(listItems, id: \.id) { item in
Button(action: { print("----> " + item.text) }) {
Text(item.text)
}
.padding(10)
.listRowInsets(.init(top: 0,leading: 0, bottom: 0, trailing: 0))
.tag(item.id)
.frame(minWidth: 111, idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
}
}
编辑:完整测试代码:
这是我在测试中使用的代码:
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
struct NavItem {
let id: String
let text: String
}
struct ContentView: View {
@State private var listItems: [NavItem] = [NavItem(id: "1", text: "1"),
NavItem(id: "2", text: "2"),
NavItem(id: "3", text: "3"),
NavItem(id: "4", text: "4")]
@State private var selection: String?
var body: some View {
List (selection: $selection) {
ForEach(listItems, id:\.id) { item in
Button(action: { print("----> " + item.text) }) {
Text(item.text)
}
.padding(10)
.listRowInsets(.init(top: 0,leading: -5, bottom: 0, trailing: -5))
.frame(minWidth: 111, idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
.tag(item.id)
.background(Color.red) // <--- last modifier
}
}
}
}