How to remove top space of `Form` in SwiftUI?
SwiftUI Form
is actually a grouped style UITableView
under the hood and that is default tableHeaderView
. So you can remove it like this:
iOS 13
struct ContentView: View {
init() { // this can be done in `onAppear` modifier if you need to restore the appereance later on `onDisappear`
UITableView.appearance().tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
}
var body: some View {
,,,
}
}
iOS 14
Apple is limiting the appearance
hack and setting the tableHeaderView
's frame is one of them so we need to dig more around by adding these steps:
1. Use constraint instead of frame
:
init() {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: 0).isActive = true
UITableView.appearance().tableHeaderView = view
}
2. Force reload the table:
The constraint is added but it needs a reload. SwiftUI does not allow you to reload a list manually. So we need to add a dummy view and a dummy state
to trick it:
@State var loaded = false // need for stay update
,,,
List {
if loaded {
Text("Actual content of the list")
} else {
Text("Dummy content. Not important")
.onAppear {
loaded = true // need for instatnt force update
}
}
}
Note1:
Try never hard-code any numbers (like -35 for inset!). Numbers vary on different devices and platforms and states and etc.
Note2:
.zero
frame is not working. You should pass at least a minimum height if you use frame
for iOS 13 or UIKit
.
Note3:
All methods are hacks and Apple is trying to restrict access to underlying types like UITableView
. So stay up to date and try to help the community.
Note4:
Contribute to the community by upvoting and commenting. So people will be more motivated to dig in unknown places and bring us cool stuff.
Note5:
Since we are using the Appearance proxy, any change will be applied to all TableView
s in the app. You can store the state of the original Appearance
-> apply the new style onAppear
and restore the original onDisaper
if needed.
if you use Introspect add this to your NavigationView
.introspectTableView {
$0.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
}
Setting the table header view is no longer working for me in Xcode 12. Instead, setting a negative top content inset seems to achieve the same thing.
UITableView.appearance().contentInset.top = -35