Requirements#
In my new App LinguaTale, I want to make a custom header for a list view which is a sub view of the NavigationView. In this header, I'd like to set an image at the top of screen, ignore the safe area. Finally it looks like the screenshot shows below.
Implementation#
- Hide the navigationBar's default background with
.toolbarBackground(.hidden, for: .navigationBar)
. - Set the HeaderView with
overlay
modifier. - Set an image background to HeaderView with
.background
modifier. - You can use
.background(.ultraThinMaterial.opacity(0.8))
before the image background modifier to make the image a little bit fuzzy, so that the text over the image looks more clear. - Set
.edgesIgnoringSafeArea(.top)
on the background image so that it can overspread to the top of the screen. - Set a
HeaderView().opacity(0)
in ScrollView and make sure it is the first view in ScrollView. This invisible view is used to occupy a space that is the same with HeaderView in overlay, then the real first element in ScrollView won't be covered up by the HeaderView inoverlay
.
import SwiftUI
struct DemoView: View {
var body: some View {
VStack {
ScrollView {
HeaderView()
.opacity(0) // this invisible view is used for occupy a space
}
}
.toolbarBackground(.hidden, for: .navigationBar)
.overlay(alignment: .top) {
HeaderView()
.background(.ultraThinMaterial.opacity(0.8))
.background {
Image("TheBackgroundImage")
.resizable(resizingMode: .stretch)
.edgesIgnoringSafeArea(.top)
}
}
}
}
struct HeaderView: View {
var body: some View {
Text("This is a demo header view")
}
}