【SwiftUI】listRowInsetsで上下の余白を消せない?
Summary
環境変数defaultMinListRowHeight
を0
ポイントに設定することで、上下の余白を消すことができます。
struct ContentView: View {
var body: some View {
List {
ForEach(0..<10) { _ in
Text("Hello, world.")
}
.listRowInsets(.init(top: .zero, leading: .zero, bottom: .zero, trailing: .zero))
}
.environment(\.defaultMinListRowHeight, 0)
}
}
Description
本記事に辿り着かれた方の多くは、下記のようなコードを書かれていると思います。
struct ContentView: View {
var body: some View {
List {
ForEach(0..<10) { _ in
Text("Hello, world.")
}
.listRowInsets(.init(top: .zero, leading: .zero, bottom: .zero, trailing: .zero))
}
}
}
一見、上記のコードで上下左右の余白がなくなりそうですが、実際は上下の余白は消えずに下の画像のようになります。
これは環境変数defaultMinListRowHeight
がデフォルトで44
ポイントに設定されているためです。
つまりは、列の高さは最低でも44
ポイントは必要です。
ビューの高さだけでは44
ポイントに満たないため、上下に余白が付与されます。
environment
モディファイアを用いて、環境変数defaultMinListRowHeight
を0
ポイントに設定することで、上下の余白を消すことができます。
struct ContentView: View {
var body: some View {
List {
ForEach(0..<10) { _ in
Text("Hello, world.")
}
.listRowInsets(.init(top: .zero, leading: .zero, bottom: .zero, trailing: .zero))
}
.environment(\.defaultMinListRowHeight, 0)
}
}
上記のコードでアプリを立ち上げると、下の画像の通り上下の余白がなくなります。
Bonus
列の高さが環境変数defaultMinListRowHeight
で設定された値に満たない場合、
「(環境変数defaultMinListRowHeight - ビューの高さ + トップインセット + ボトムインセット) / 2」が上下の余白に追加されます。
下記のコードでは、環境変数defaultMinListRowHeight
が300ポイント、ビューの高さが100ポイント、トップインセットが100ポイント、ボトムインセットが0ポイントとなっています。
列の高さは最低でも300ポイントは必要ですが、ビューの高さとトップインセットとボトムインセットの合計は200ポイントで100ポイント足りません。不足分の100ポイントは、上下の余白に50ポイントずつ追加されることになります。
今回の例では、上部の余白が元々の100ポイントに50ポイントが追加され150ポイントとなり、ビューの高さは変わらず100ポイントとなり、下部の余白が元々の0ポイントに50ポイントが追加され50ポイントとなります。
検証に使用したコードはこちら
struct ContentView: View {
var body: some View {
List {
Rectangle()
.frame(width: 100, height: 100)
.frame(maxWidth: .infinity)
.listRowInsets(.init(top: 100, leading: .zero, bottom: .zero, trailing: .zero))
}
.environment(\.defaultMinListRowHeight, 300)
.overlay(content: DraggableRectangle.init)
}
}
struct DraggableRectangle: View {
@State private var currentOffset: CGSize = .zero
@State private var dragOffset: CGSize = .zero
var body: some View {
Rectangle()
.fill(.pink.opacity(0.3))
.frame(width: 50, height: 50)
// .frame(width: 150, height: 150)
.offset(x: currentOffset.width + dragOffset.width,
y: currentOffset.height + dragOffset.height)
.gesture(dragGesture)
}
var dragGesture: some Gesture {
DragGesture()
.onChanged { value in
dragOffset = value.translation
}
.onEnded { _ in
currentOffset.width += dragOffset.width
currentOffset.height += dragOffset.height
dragOffset = .zero
}
}
}
Discussion