🦋
SwiftUI: Buttonを中身がすっぽり収まる正方形に矯正する
Button
の中にImage
でSF Symbolsのアイコンを入れてボタンを作ることあると思います。
この場合、SF SymbolのサイズによってButton
のサイズが変化してしまうことよくあると思います。
SF SymbolsのサイズによってButtonのサイズが変化する
HStack {
Button {
} label: {
Image(systemName: "chevron.right")
.font(.title2)
}
.border(Color.red)
Button {
} label: {
Image(systemName: "plus")
.font(.title2)
}
.border(Color.red)
Button {
} label: {
Image(systemName: "rectangle.and.pencil.and.ellipsis")
.font(.title2)
}
.border(Color.red)
}
そんな時はLayout
とButtonStyle
を自作してButton
にModifierをつければ正方形に矯正できます!
struct SquareButtonContainer: Layout {
private func maxLength(subviews: Subviews) -> CGFloat {
return subviews.map { subview -> CGFloat in
let size = subview.sizeThatFits(.unspecified)
return max(size.width, size.height)
}
.max() ?? .zero
}
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let length = maxLength(subviews: subviews)
return CGSize(width: length, height: length)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
guard subviews.count == 1 else { return }
subviews.forEach { subview in
subview.place(at: CGPoint(x: bounds.midX, y: bounds.midY),
anchor: .center,
proposal: proposal)
}
}
}
struct SquareButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
SquareButtonContainer {
configuration.label
.fixedSize()
.foregroundColor(.accentColor)
.opacity(configuration.isPressed ? 0.3 : 1.0)
}
}
}
extension ButtonStyle where Self == SquareButtonStyle {
static var square: SquareButtonStyle {
return SquareButtonStyle()
}
}
からの
HStack {
Button {
} label: {
Image(systemName: "chevron.right")
.font(.title2)
}
+ .buttonStyle(.square)
.border(Color.red)
Button {
} label: {
Image(systemName: "plus")
.font(.title2)
}
+ .buttonStyle(.square)
.border(Color.red)
Button {
} label: {
Image(systemName: "rectangle.and.pencil.and.ellipsis")
.font(.title2)
}
+ .buttonStyle(.square)
.border(Color.red)
}
で、
それぞれちょうどSF Symbolsが収まる正方形になっている
当然、中身がText
の時も大丈夫!
Button {
} label: {
Text("Hello World")
.font(.title2)
}
.buttonStyle(.square)
.border(Color.red)
文字列がちょうど収まる正方形になっている
Discussion