在列表 (SwiftUI) 中返回后,所选列表行的背景保持灰色(选中)。 iOS14 + Xcode12
Selected list row's background remains grey (selected) after navigating back in List (SwiftUI). iOS14 + Xcode12
从详细视图导航回来后,所选行保持灰色。在模拟器和真实设备上都发生,仅在 iOS 14 上发生。有谁知道如何删除它以便它的行为与 iOS 13 上的行为相同(不保持选中状态)?
这是项目中唯一的代码。 (没有其他导航或任何东西)。
let items = ["item1", "item2"]
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello")
List(items, id: \.self) { item in
NavigationLink(destination: Text(item)) {
Text(item)
}
}
.listStyle(PlainListStyle())
}
}
// .navigationViewStyle(StackNavigationViewStyle()) // didn't solve the problem
}
}
This is how it looks
我实际上找到了一个使用 lazystack 的解决方法,然后将 row/cell 与一些填充和分隔符一起放入 Hstack 中。但是性能比列表差很多。
编辑
如果您将列表 放在另一个视图的 之外(在您的示例中不要将其嵌入 VStack 中),它将正常工作。所以你必须把你的列表放在一个单独的 View-Struct 中,并将这个列表嵌入到你的 ContentView 中。像这样:
struct ExtractedListView: View {
var listItems:[something]
List(listItems, id: \.self) { item in
NavigationLink(destination: Text(item)) {
Text(item)
}
}
struct ContentView : View {
NavigationView {
VStack {
Text("Hello")
ExtractedListView(listItems: items)
}
}
}
我一用StackNavigationViewStyle()
就遇到了同样的问题。
使用 DefaultNavigationViewStyle()
.
为我解决了这个问题
这是我让它工作的方式。我发现了一些非常罕见的情况,其中高光消失有点滞后,但到目前为止它有很大帮助。
这个例子使用了 MVVM 模式,希望你能理解。
您可以使用此第三方库访问 SwiftUI List 背后的底层 UITableView :
https://github.com/siteline/SwiftUI-Introspect
然后您可以存储 tableView 实例,并在 table 出现和消失时刷新选择(不知何故,在两者中都这样做效果更好,因为这些块可能会执行有点滞后,具体取决于用户导航的积极程度)
List {
// ...
}
.introspectTableView { tableView in
self.viewModel.bindToTableView(tableView)
}
.onAppear(perform: {
self.viewModel.clearTableViewSelection()
})
.onDisappear(perform: {
self.viewModel.clearTableViewSelection()
})
在 viewModel 中,这里是函数
func bindToTableView(_ tableView: UITableView) {
self.tableView = tableView
}
func clearTableViewSelection() {
// This is a iOS14 hack that prevents clicked cell background view to remain highlighted when we come back to the screen
if #available(iOS 14, *){
DispatchQueue.main.async {
if let selectedIndexPath = self.tableView?.indexPathForSelectedRow {
self.tableView?.deselectRow(at: selectedIndexPath, animated: false)
if let selectedCell = self.tableView?.cellForRow(at: selectedIndexPath) {
selectedCell.setSelected(false, animated: false)
}
}
}
}
}
你可以像这样包装你的视图,这在你使用列表等时特别有用。这个解决方案也摆脱了插入符号。
ZStack {
NavigationLink(destination: DestinationView()) {
EmptyView()
}
Rectangle().background(Color(UIColor.systemBackground)).foregroundColor(Color(UIColor.systemBackground))
ViewToClick()
}
以下是对我有用的方法:
@State var selection: Int? = nil
var body: some View {
List {
ForEach(self.model.data, id: \.self) { item in
ZStack {
Button("") {
self.selection = item.id
}
NavigationLink(destination: ItemView(item: item), tag: item.id, selection: self.$selection) {
Spacer()
}.hidden()
ItemRow(item: item)
}
}
}
}
这就是诀窍。只需创建一个 ZStack 并在上面放置一个空按钮。
var body: some View {
List {
ForEach(data, id: \.self) { item in
ZStack {
Button("") {}
NavigationLink(destination: ItemView(item: item)) {
ItemRow(item: item)
}
}
}
}
}
从详细视图导航回来后,所选行保持灰色。在模拟器和真实设备上都发生,仅在 iOS 14 上发生。有谁知道如何删除它以便它的行为与 iOS 13 上的行为相同(不保持选中状态)? 这是项目中唯一的代码。 (没有其他导航或任何东西)。
let items = ["item1", "item2"]
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello")
List(items, id: \.self) { item in
NavigationLink(destination: Text(item)) {
Text(item)
}
}
.listStyle(PlainListStyle())
}
}
// .navigationViewStyle(StackNavigationViewStyle()) // didn't solve the problem
}
}
This is how it looks
我实际上找到了一个使用 lazystack 的解决方法,然后将 row/cell 与一些填充和分隔符一起放入 Hstack 中。但是性能比列表差很多。
编辑 如果您将列表 放在另一个视图的 之外(在您的示例中不要将其嵌入 VStack 中),它将正常工作。所以你必须把你的列表放在一个单独的 View-Struct 中,并将这个列表嵌入到你的 ContentView 中。像这样:
struct ExtractedListView: View {
var listItems:[something]
List(listItems, id: \.self) { item in
NavigationLink(destination: Text(item)) {
Text(item)
}
}
struct ContentView : View {
NavigationView {
VStack {
Text("Hello")
ExtractedListView(listItems: items)
}
}
}
我一用StackNavigationViewStyle()
就遇到了同样的问题。
使用 DefaultNavigationViewStyle()
.
这是我让它工作的方式。我发现了一些非常罕见的情况,其中高光消失有点滞后,但到目前为止它有很大帮助。 这个例子使用了 MVVM 模式,希望你能理解。
您可以使用此第三方库访问 SwiftUI List 背后的底层 UITableView :
https://github.com/siteline/SwiftUI-Introspect
然后您可以存储 tableView 实例,并在 table 出现和消失时刷新选择(不知何故,在两者中都这样做效果更好,因为这些块可能会执行有点滞后,具体取决于用户导航的积极程度)
List {
// ...
}
.introspectTableView { tableView in
self.viewModel.bindToTableView(tableView)
}
.onAppear(perform: {
self.viewModel.clearTableViewSelection()
})
.onDisappear(perform: {
self.viewModel.clearTableViewSelection()
})
在 viewModel 中,这里是函数
func bindToTableView(_ tableView: UITableView) {
self.tableView = tableView
}
func clearTableViewSelection() {
// This is a iOS14 hack that prevents clicked cell background view to remain highlighted when we come back to the screen
if #available(iOS 14, *){
DispatchQueue.main.async {
if let selectedIndexPath = self.tableView?.indexPathForSelectedRow {
self.tableView?.deselectRow(at: selectedIndexPath, animated: false)
if let selectedCell = self.tableView?.cellForRow(at: selectedIndexPath) {
selectedCell.setSelected(false, animated: false)
}
}
}
}
}
你可以像这样包装你的视图,这在你使用列表等时特别有用。这个解决方案也摆脱了插入符号。
ZStack {
NavigationLink(destination: DestinationView()) {
EmptyView()
}
Rectangle().background(Color(UIColor.systemBackground)).foregroundColor(Color(UIColor.systemBackground))
ViewToClick()
}
以下是对我有用的方法:
@State var selection: Int? = nil
var body: some View {
List {
ForEach(self.model.data, id: \.self) { item in
ZStack {
Button("") {
self.selection = item.id
}
NavigationLink(destination: ItemView(item: item), tag: item.id, selection: self.$selection) {
Spacer()
}.hidden()
ItemRow(item: item)
}
}
}
}
这就是诀窍。只需创建一个 ZStack 并在上面放置一个空按钮。
var body: some View {
List {
ForEach(data, id: \.self) { item in
ZStack {
Button("") {}
NavigationLink(destination: ItemView(item: item)) {
ItemRow(item: item)
}
}
}
}
}