在列表 (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)
                }
            }
        }
    }
}