如何在 SwiftUI 中的大型导航栏标题旁边显示个人资料图标?

chr*_*epe 11 profile image ios swift swiftui

我正在开发一个支持多个配置文件的应用程序。Profile Icon我真的很喜欢苹果在所有应用程序中显示下一个的方式Large Navigation Bar Title。请参阅下面的屏幕截图:

截图示例

我的问题如下:

  • 有可能实现这一目标SwiftUI吗?如果是这样,怎么办?
  • 如果在 pure 中不可能SwiftUI,我怎样才能实现它,包括UIKit代码?

感谢您的帮助。

Geo*_*e_E 21

我通过使用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)
                ])
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

酒吧内容和个人资料图片浏览量:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

&需要根据您的需要进行调整.frame(width: 40, height: 40)hostingView.bottomAnchor constant

以及每个选项的结果(在代码中注释):

选项1 选项2
滚动时查看棒 视图在滚动下方消失
结果 - 选项 1 结果 - 选项 2


Pyr*_*nen 4

没有导航视图

我用纯 SwiftUI 完成了这个。您必须Image("Profile")用您自己的图像替换该行(可能来自资产或带有 UIImage 的 base64 数据)。

HStack {
    Text("Apps")
        .font(.largeTitle)
        .fontWeight(.bold)
    
    Spacer()
    
    Image("Profile")
        .resizable()
        .scaledToFit()
        .frame(width: 40, height: 40)
        .clipShape(Circle())
}
.padding(.all, 30)
Run Code Online (Sandbox Code Playgroud)

本产品结果如下: 结果显示大粗体字“应用程序”,然后是我的示例个人资料图片

带导航视图

假设您有NavigationView和 ,其中只有ScrollView.navigationTitle。您可以使用叠加来添加该个人资料图像。

NavigationView {
    ScrollView {
        //your content here
    }
    .overlay(
        ProfileView()
            .padding(.trailing, 20)
            .offset(x: 0, y: -50)
    , alignment: .topTrailing)

    .navigationTitle(Text("Apps"))
}
Run Code Online (Sandbox Code Playgroud)

ProfileView 可能是这样的:

struct ProfileView: View {
    var body: some View {
        Image("Profile")
            .resizable()
            .scaledToFit()
            .frame(width: 40, height: 40)
            .clipShape(Circle())
    }
}
Run Code Online (Sandbox Code Playgroud)

结果会是这样的……

上面代码的结果

...这与 App Store 非常接近:

显示 App Store 行为的 gif

  • 更重要的是:个人资料图标必须是一个按钮。但是,当添加填充和偏移量时,按钮不再可单击。我怎么解决这个问题? (3认同)