[英]SwiftUI NavigationLink highlight staying highlighted after returning to previous view
[英]SwiftUI - NavigationLink cell in a Form stays highlighted after detail pop
在 iOS 14 中,看起来NavigationLink
在返回Form
上下文后不会被取消选择。 这也适用于Form
Picker
和其他任何导致从列表中显示另一个View
的东西(为呈现单元格提供突出显示的上下文)。
我没有注意到 iOS 13 中的这种行为。
一旦另一个视图被关闭,有没有办法“取消选择”突出显示的行?
示例代码:
struct ContentView: View {
var body: some View {
Form {
NavigationLink(destination: Text("Detail")) {
Text("Link")
}
}
}
}
(不同)视觉示例:
在我的情况下,这种行为出现在我的NavigationView
和List/Form
之间使用任何 Viewcontent(例如 Text()、Image()、...)时。
var body: some View {
NavigationView {
VStack {
Text("This text DOES make problems.")
List {
NavigationLink(destination: Text("Doesn't work correct")) {
Text("Doesn't work correct")
}
}
}
}
}
将 Text()放在List之下不会产生任何问题:
var body: some View {
NavigationView {
VStack {
List {
NavigationLink(destination: Text("Does work correct")) {
Text("Does work correct")
}
}
Text("This text doesn't make problems.")
}
}
}
这绝对是一个 XCode 12 错误。 随着越来越多的人报告这个问题,它会越早得到解决。
我也遇到了这个问题,并相信我找到了我的案例的根本原因。
在我的情况下,我有一个如下结构:
struct Page1View: View {
var body: some View {
NavigationView {
List {
NavigationLink("Page 2", destination: Page2View())
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Page 1")
}
}
}
struct Page2View: View {
var body: some View {
List {
NavigationLink("Page 3", destination: Text("Page 3"))
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Page 2")
}
}
此问题会发生在 NavigationLink 到页面 3 上。在控制台输出中,使用该链接时会显示此错误:
2021-02-13 16:41:00.599844+0000 App[59157:254215] [Assert] displayModeButtonItem is internally managed and not exposed for DoubleColumn style. Returning an empty, disconnected UIBarButtonItem to fulfill the non-null contract.
我发现我需要将.navigationViewStyle(StackNavigationViewStyle())
应用于 NavigationView,这解决了问题。
IE
struct Page1View: View {
var body: some View {
NavigationView {
List {
NavigationLink("Page 2", destination: Page2View())
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Page 1")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
今天一直在与这个问题作斗争半天,来到这篇文章,帮助我理解如果Text
、 Button
或其他东西放在NavigationView
和我的案例List
之间会出现这个问题。 我找到了对我有用的解决方案。 只需为该项目添加.zIndex()
。 .zIndex()
必须高于List
Tried with Xcode 12.5
。
var body: some View {
NavigationView {
VStack {
Text("This text DOES make problems.")
.zIndex(1.0)
List {
NavigationLink(destination: Text("Doesn't work correct")) {
Text("Doesn't work correct")
}
}
}
}
}
我做了一些修补,结果证明这是由于UIHostingController
嵌套在UINavigationController
并使用该导航控制器造成的。 更改导航堆栈以使用 SwiftUI NavigationView
解决了此问题。
与@pawello2222 在问题评论中所说的类似,我认为根本原因与 SwiftUI 在使用外部UINavigationController
时不理解正确的导航层次结构有关。
这只是修复了此问题的一个实例,根据我的视图结构,我仍在各种其他上下文中遇到此问题。
我已经向 Apple 提交了一份问题报告FB8705430 ,所以希望这个问题很快得到解决。
之前(损坏):
struct ContentView: View {
var body: some View {
Form {
NavigationLink(destination: Text("test")) {
Text("test")
}
}
}
}
// (UIKit presentation context)
let view = ContentView()
let host = UIHostingController(rootView: view)
let nav = UINavigationController(rootViewController: host)
present(nav, animated: true, completion: nil)
之后(工作):
struct ContentView: View {
var body: some View {
NavigationView {
Form {
NavigationLink(destination: Text("test")) {
Text("test")
}
}
}
}
}
// (UIKit presentation context)
let view = ContentView()
let host = UIHostingController(rootView: view)
present(host, animated: true, completion: nil)
这绝对是List
一个错误,目前,我的解决方法是通过更改 id 来刷新List
,如下所示:
struct YourView: View {
@State private var selectedItem: String?
@State private var listViewId = UUID()
var body: some View {
List(items, id: \.id) {
NavigationLink(destination: Text($0.id),
tag: $0.id,
selection: $selectedItem) {
Text("Row \($0.id)")
}
}
.id(listViewId)
.onAppear {
if selectedItem != nil {
selectedItem = nil
listViewId = UUID()
}
}
}
}
我基于此制作了一个修饰符,您可以使用:
struct RefreshOnAppearModifier<Tag: Hashable>: ViewModifier {
@State private var viewId = UUID()
@Binding var selection: Tag?
func body(content: Content) -> some View {
content
.id(viewId)
.onAppear {
if selection != nil {
viewId = UUID()
selection = nil
}
}
}
}
extension View {
func refreshOnAppear<Tag: Hashable>(selection: Binding<Tag?>? = nil) -> some View {
modifier(RefreshOnAppearModifier(selection: selection ?? .constant(nil)))
}
}
像这样使用它:
List { ... }
.refreshOnAppear(selection: $selectedItem)
我设法通过向列表的不同组件添加 id,使用绑定并重置 .onDisappear 上的绑定来解决它
struct ContentView: View {
@State var selection: String? = nil
var body: some View {
NavigationView {
VStack {
Text("Hello, world!")
.padding()
List {
Section {
NavigationLink( destination: Text("Subscreen1"), tag: "link1", selection: $selection ) {
Text("Subscreen1")
}.onDisappear {
self.selection = nil
}
NavigationLink( destination: Text("Subscreen2"), tag: "link2", selection: $selection ) {
Text("Subscreen2")
}.onDisappear {
self.selection = nil
}
}.id("idSection1")
}
.id("idList")
}
}
}
}
这是我一直在使用的解决方法,直到此 List 问题得到修复。 使用Introspect库,我保存 List 的 UITableView.reloadData 方法并在它再次出现时调用它。
import SwiftUI
import Introspect
struct MyView: View {
@State var reload: (() -> Void)? = nil
var body: some View {
NavigationView {
List {
NavigationLink("Next", destination: Text("Hello"))
}.introspectTableView { tv in
self.reload = tv.reloadData
}.onAppear {
self.reload?()
}
}
}
}
将.navigationViewStyle(StackNavigationViewStyle())
添加到NavigationView
为我修复了它。
在此线程中建议: https : //developer.apple.com/forums/thread/660468
这是我对这个问题的解决方案。
// This in a stack in front of list, disables large navigation title from collapsing by disallowing list from scrolling on top of navigation title
public struct PreventCollapseView: View {
@State public var viewColor: Color?
public init(color: Color? = nil) {
self.viewColor = color
}
public var body: some View {
Rectangle()
.fill(viewColor ?? Color(UIColor(white: 0.0, alpha: 0.0005)))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 1)
}
}
// handy modifier..
extension List {
public func uncollapsing(_ viewUpdater: Bool) -> some View {
VStack(spacing: 0.0) {
Group {
PreventCollapseView()
self
}.id(viewUpdater)
}
}
}
struct TestView: View {
@State var updater: Bool = false
var body: some View {
List {
Text("Item one")
Text("Item two")
Text("Manually refresh")
.onTapGesture { DispatchQueue.main.async { updater.toggle() } }
.onAppear { print("List was refreshed") }
}
.uncollapsing(updater)
.clipped()
.onAppear { DispatchQueue.main.async { updater.toggle() }} // Manually refreshes list always when re-appearing/appearing
}
}
添加 NavigationView,为 largeTitle 配置,并嵌入 TestView,一切就绪。 切换更新程序以刷新。
有同样的问题。 奇怪的是,完全相同的代码在 iOS13 中工作。 我在一个简单的列表中遇到了这个问题:
struct TestList: View {
let someArray = ["one", "two", "three", "four", "five"]
var body: some View {
List(someArray, id: \.self) { item in
NavigationLink(
destination: Text(item)) {
Text(item)
}.buttonStyle(PlainButtonStyle())
}.navigationBarTitle("testlist")
}
}
这嵌入在:
struct ListControllerView: View {
@State private var listPicker = 0
var body: some View {
NavigationView{
Group{
VStack{
Picker(selection: $listPicker, label: Text("Detailoverview")) {
Text("foo").tag(0)
Text("bar").tag(1)
Text("TestList").tag(2)
}
这是在 Tabbar 内。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.