@@ -36,10 +36,25 @@ internal struct UINavigationBarRecorder: NodeRecorder {
3636
3737 private func inferOccupiedFrame( of navigationBar: UINavigationBar , in context: ViewTreeRecordingContext ) -> CGRect {
3838 var occupiedFrame = navigationBar. frame
39+ var largeTitleFrame : CGRect ?
40+
3941 for subview in navigationBar. subviews {
4042 let subviewFrame = subview. convert ( subview. bounds, to: context. coordinateSpace)
43+
44+ if subview. isNavigationBarLargeTitleView {
45+ largeTitleFrame = subviewFrame
46+ }
47+
4148 occupiedFrame = occupiedFrame. union ( subviewFrame)
4249 }
50+
51+ if #available( iOS 26 , * ) , navigationBar. isSwiftUINavigationBar, let largeTitleFrame {
52+ // For SwiftUI navigation bars, exclude the large title view from `occupiedFrame`
53+ // to prevent occluding the large title that's rendered as a sibling view
54+ let height = max ( 0 , min ( largeTitleFrame. height, occupiedFrame. height) )
55+ occupiedFrame = occupiedFrame. inset ( by: . init( top: 0 , left: 0 , bottom: height, right: 0 ) )
56+ }
57+
4358 return occupiedFrame
4459 }
4560
@@ -88,4 +103,26 @@ internal struct UINavigationBarWireframesBuilder: NodeWireframesBuilder {
88103 ]
89104 }
90105}
106+
107+ extension UIView {
108+ private enum Constants {
109+ static let UIKitNavigationBarClass : AnyClass ? = NSClassFromString ( " SwiftUI.UIKitNavigationBar " )
110+ static let NavigationBarLargeTitleView : AnyClass ? = NSClassFromString ( " UIKit.NavigationBarLargeTitleView " )
111+ }
112+
113+ fileprivate var isSwiftUINavigationBar : Bool {
114+ guard let cls = Constants . UIKitNavigationBarClass else {
115+ return false
116+ }
117+ return type ( of: self ) . isSubclass ( of: cls)
118+ }
119+
120+ fileprivate var isNavigationBarLargeTitleView : Bool {
121+ guard let cls = Constants . NavigationBarLargeTitleView else {
122+ return false
123+ }
124+ return type ( of: self ) . isSubclass ( of: cls)
125+ }
126+ }
127+
91128#endif
0 commit comments