我使用SwiftUI-Introspect解决了这个问题,它可以从SwiftUI中“审查基础的UIKit组件”。
以下是一个视图的示例:
struct ContentView: View {
@State private var lastHostingView: UIView!
var body: some View {
NavigationView {
ScrollView {
ForEach(1 ... 50, id: \.self) { index in
Text("Index: \(index)")
}
.frame(maxWidth: .infinity)
}
.navigationTitle("Large title")
.introspectNavigationController { navController in
let bar = navController.navigationBar
let hosting = UIHostingController(rootView: BarContent())
guard let hostingView = hosting.view else { return }
// bar.addSubview(hostingView) // <--- OPTION 1
// bar.subviews.first(where: \.clipsToBounds)?.addSubview(hostingView) // <--- OPTION 2
hostingView.backgroundColor = .clear
lastHostingView?.removeFromSuperview()
lastHostingView = hostingView
hostingView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
hostingView.trailingAnchor.constraint(equalTo: bar.trailingAnchor),
hostingView.bottomAnchor.constraint(equalTo: bar.bottomAnchor, constant: -8)
])
}
}
}
}
酒吧内容和个人资料图片浏览:
struct BarContent: View {
var body: some View {
Button {
print("Profile tapped")
} label: {
ProfilePicture()
}
}
}
struct ProfilePicture: View {
var body: some View {
Circle()
.fill(
LinearGradient(
gradient: Gradient(colors: [.red, .blue]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
.frame(width: 40, height: 40)
.padding(.horizontal)
}
}
.frame(width: 40, height: 40)
和hostingView.bottomAnchor
constant
需要根据您的需求进行调整。
每个选项的结果(在代码中进行了注释):
我使用纯SwiftUI完成了这个。您需要用自己的图片替换Image("Profile")
行(可以从Assets中获取,也可以使用带有UIImage的base64数据)。
HStack {
Text("Apps")
.font(.largeTitle)
.fontWeight(.bold)
Spacer()
Image("Profile")
.resizable()
.scaledToFit()
.frame(width: 40, height: 40)
.clipShape(Circle())
}
.padding(.all, 30)
假设您有一个NavigationView
,其中只包含ScrollView
和.navigationTitle
。您可以使用叠加层将个人资料图片添加到其中。
NavigationView {
ScrollView {
//your content here
}
.overlay(
ProfileView()
.padding(.trailing, 20)
.offset(x: 0, y: -50)
, alignment: .topTrailing)
.navigationTitle(Text("Apps"))
}
ProfileView可能是这样的:
struct ProfileView: View {
var body: some View {
Image("Profile")
.resizable()
.scaledToFit()
.frame(width: 40, height: 40)
.clipShape(Circle())
}
}
Option 2
*(这是我想要使用的行为)*时:当导航到另一个也使用Large Title
的视图时,一切都很顺利,但是当导航到一个带有Inline Title
的视图,然后返回时,个人资料图标出现在原始视图的大标题上,不再在右侧。我该如何解决这个错误?那么,你的解决方案是完美的;) - christophriepe.onAppear
和onDisappear
来暂时隐藏BarContent()
(图标不会出现在目标视图中)。我认为最好的解决方案是简单地选择选项#1,因为它的效果要好得多。毕竟,我们正在尝试访问私有视图,所以选项#2的解决方案有点hacky。 - George