簡體   English   中英

SwiftUI - 表單中的 NavigationLink 單元格在詳細信息彈出后保持突出顯示

[英]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")
            } 
        }
    }

}

(不同)視覺示例:

例子

在我的情況下,這種行為出現在我的NavigationViewList/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())
    }
}

今天一直在與這個問題作斗爭半天,來到這篇文章,幫助我理解如果TextButton或其他東西放在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")
            }
        }
    }
}

我也遇到過這個問題,它似乎與這里提到的工作表有關。

我的解決方案是調整UITableView捕捉選擇,並取消選擇單元格。 這樣做的代碼在這里 希望這將在未來的 iOS 中得到修復。

這是我一直在使用的解決方法,直到此 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM