SwiftUI のボーダーボタン と clipped

四角ボタン

四角のボタンにボーダーをつける場合は .border modifier を指定すれば作れる。

Button("四角のボーダーボタン", action: {})
    .frame(height: height)
    .padding()
    .background(Color.orange)
    .border(Color.red, width: borderWidth)

f:id:komaji504:20210528153240p:plain
四角のボーダーボタン

角丸ボタン

角丸のボタンにボーダーをつける場合には Button.init(action:,label) の label に Text を置いて、 .overlay modifier で ボーダーを引いた Shape を指定すれば作れる。

Button(
    action: {},
    label: {
        Text(“角丸のボーダーボタン”)
            .frame(height: height)
            .padding()
            .background(Color.orange)
            .cornerRadius(radius)
            .overlay( 
                RoundedRectangle(cornerRadius: radius)
                    .stroke(Color.red, lineWidth: borderWidth)
            )
    }
)

f:id:komaji504:20210528153709p:plain
角丸のボーダーボタン

四角同様に .border modifier だけで作ろうとしても、角丸にするための .conerRadius modifier では下記のように四角いボーダーがついてしまうので NG。

Button("角丸のボーダーボタン", action: {})
    .frame(height: height)
    .padding()
    .background(Color.orange)
    .cornerRadius(radius)
    .border(Color.red, width: borderWidth)

f:id:komaji504:20210528154008p:plain
NG 角丸のボーダーボタン

角丸ボタンの clipped

Button が clipped されるようなレイアウトを作る場合、Button に padding を付与する必要がある。 .stroke modifier で作られたボーダーは、 Button の edge をセンターとしてそこから左右に広がるように描画されるため、 Button のサイズで clipped されるとボーダーが見切れることになってしまう。

Button(
    action: {},
    label: {
        Text(“角丸のボーダーボタン”)
            .frame(height: height)
            .padding()
            .background(Color.orange)
            .cornerRadius(radius)
            .overlay(
                RoundedRectangle(cornerRadius: radius)
                    .stroke(Color.red, lineWidth: borderWidth)
            )
    }
)
.padding(borderWidth / 2.0) // <- これがないとボーダーが見切れる
.clipped()

f:id:komaji504:20210528154126p:plain
clipped 角丸のボーダーボタン