🦋
SwiftUI: LabeledContentの不便な挙動を制御する
macOSでLabeledContent
を使うとViewの左側にラベルをつけることができます。
シンプルな例
struct ContentView: View {
@State var isOn: Bool = false
var body: some View {
LabeledContent {
Toggle(isOn: $isOn) {
Text("Detail")
}
} label: {
Text("Item:")
}
}
}
さらに、Form
で囲めば往年のmacOSアプリの設定画面などで見られるラベルの位置が揃ったUIを実装できます。
Formで囲まない場合
var body: some View {
VStack {
LabeledContent {
Toggle(isOn: $isOn) {
Text("Detail")
}
} label: {
Text("Apple:")
}
LabeledContent {
Toggle(isOn: $isOn) {
Text("Detail")
}
} label: {
Text("Banana:")
}
LabeledContent {
Toggle(isOn: $isOn) {
Text("Detail")
}
} label: {
Text("Cherry:")
}
}
}
ラベルの位置がバラバラ
Formで囲む場合
var body: some View {
Form {
LabeledContent {
Toggle(isOn: $isOn) {
Text("Detail")
}
} label: {
Text("Apple:")
}
LabeledContent {
Toggle(isOn: $isOn) {
Text("Detail")
}
} label: {
Text("Banana:")
}
LabeledContent {
Toggle(isOn: $isOn) {
Text("Detail")
}
} label: {
Text("Cherry:")
}
}
}
ラベルの位置が綺麗に揃っている
そんな便利なLabeledContent
ですが、このcontent
の中に複雑なViewを入れた時の挙動制御にコツが要ります。
例えば、VStack
で複数のView
を入れる時何も対策しないとラベルの位置が上下中央寄せや下寄せになってしまうことがあります。
上下中央寄せになるパターン
LabeledContent {
VStack(alignment: .leading) {
Rectangle()
.frame(width: 100, height: 100)
Toggle(isOn: $isOn) {
Text("Detail")
}
}
} label: {
Text("Item:")
}
ラベルが上下中央寄せ
下寄せになるパターン
Form {
LabeledContent {
VStack(alignment: .leading) {
Rectangle()
.frame(width: 100, height: 100)
Toggle(isOn: $isOn) {
Text("Detail")
}
}
} label: {
Text("Item:")
}
}
ラベルが下寄せ
Form
に包むかどうかで挙動が変わっていますね。
色々試したところ、どうやらラベルを上寄せにしたい場合は、必ずForm
の中に入れてcontent
内の一番上にText
属性のViewがあれば良いようです。なので、一番上にText
属性を置きたくない場合はZStack
を使いつつダミーのText
を.hidden()
でおけば良いです。
Form {
LabeledContent {
ZStack(alignment: .top) {
Text("dummy").hidden()
VStack(alignment: .leading) {
Rectangle()
.frame(width: 100, height: 100)
Toggle(isOn: $isOn) {
Text("Detail")
}
}
}
} label: {
Text("Item:")
}
}
ラベルが上寄せ
なにこれ。
Discussion