So here is the deal. I'm making a button component that will have two styles. One of the style has any backgroundColor defined by the dev and the other style has no backgroundColor but does have a border. I have implemented the style with the background color but I am trying to set up the style without background color and it always applies a default white color that I can't get rid of, making the border of the component not look right.
Button with backgroundColor:
var mainContentView: some View {
HStack{
if let leadingIcon = configuration.leadingIcon {
imageView(resource: leadingIcon, color: style.leadingIconColor, size: size.iconSize())
}
titleView
if let trailingIcon = configuration.trailingIcon {
imageView(resource: trailingIcon, color: style.trailingIconColor, size: size.iconSize())
}
}
.frame(maxWidth: configuration.maxWidth ? .infinity : nil)
.padding(.vertical, 8)
.padding(.horizontal, 8)
.background(Color.gray)
.clipShape(
.rect(
topLeadingRadius: configuration.invertCornerRadius ? 5 : 15,
bottomLeadingRadius: configuration.invertCornerRadius ? 15 : 5,
bottomTrailingRadius: configuration.invertCornerRadius ? 5 : 15,
topTrailingRadius: configuration.invertCornerRadius ? 15 : 5
)
)
}
Button without backgroundColor:
var mainContentView: some View {
HStack{
if let leadingIcon = configuration.leadingIcon {
imageView(resource: leadingIcon, color: style.leadingIconColor, size: size.iconSize())
}
titleView
if let trailingIcon = configuration.trailingIcon {
imageView(resource: trailingIcon, color: style.trailingIconColor, size: size.iconSize())
}
}
.frame(maxWidth: configuration.maxWidth ? .infinity : nil)
.padding(.vertical, 8)
.padding(.horizontal, 8)
// .background(Color.clear) I've try this too
.overlay(
RoundedRectangle(cornerRadius: 0)
.stroke(Color.red, lineWidth: 2)
.clipShape(
.rect(
topLeadingRadius: configuration.invertCornerRadius ? 5 : 15,
bottomLeadingRadius: configuration.invertCornerRadius ? 15 : 5,
bottomTrailingRadius: configuration.invertCornerRadius ? 5 : 15,
topTrailingRadius: configuration.invertCornerRadius ? 15 : 5
)
)
)
}
Your Button without backgroundColor
didn't work in this scenario because it was based on RoundedRectangle
which had cornerRadius = 0
. However, if you change it to 5 or 15
you will lose 2 other edges since your view had 2 different cornerRadius values.
You can try this approach to customize a Shape
:
struct MyRoundedRectangle: Shape {
var topLeftRadius: CGFloat = 0
var topRightRadius: CGFloat = 0
var bottomRightRadius: CGFloat = 0
var bottomLeftRadius: CGFloat = 0
func path(in rect: CGRect) -> Path {
var path = Path()
let topLeft = CGPoint(x: rect.minX, y: rect.minY)
let topRight = CGPoint(x: rect.maxX, y: rect.minY)
let bottomRight = CGPoint(x: rect.maxX, y: rect.maxY)
let bottomLeft = CGPoint(x: rect.minX, y: rect.maxY)
path.move(to: CGPoint(x: topLeft.x + topLeftRadius, y: topLeft.y))
path.addLine(to: CGPoint(x: topRight.x - topRightRadius, y: topRight.y))
path.addArc(center: CGPoint(x: topRight.x - topRightRadius, y: topRight.y + topRightRadius),
radius: topRightRadius,
startAngle: Angle(degrees: -90),
endAngle: Angle(degrees: 0),
clockwise: false)
path.addLine(to: CGPoint(x: bottomRight.x, y: bottomRight.y - bottomRightRadius))
path.addArc(center: CGPoint(x: bottomRight.x - bottomRightRadius, y: bottomRight.y - bottomRightRadius),
radius: bottomRightRadius,
startAngle: Angle(degrees: 0),
endAngle: Angle(degrees: 90),
clockwise: false)
path.addLine(to: CGPoint(x: bottomLeft.x + bottomLeftRadius, y: bottomLeft.y))
path.addArc(center: CGPoint(x: bottomLeft.x + bottomLeftRadius, y: bottomLeft.y - bottomLeftRadius),
radius: bottomLeftRadius,
startAngle: Angle(degrees: 90),
endAngle: Angle(degrees: 180),
clockwise: false)
path.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y + topLeftRadius))
path.addArc(center: CGPoint(x: topLeft.x + topLeftRadius, y: topLeft.y + topLeftRadius),
radius: topLeftRadius,
startAngle: Angle(degrees: 180),
endAngle: Angle(degrees: 270),
clockwise: false)
return path
}
}
And then using .stroke
as you wish:
var body: some View {
Button {
} label: {
Text("Button")
.foregroundStyle(.blue)
}
.frame(minWidth: 100, minHeight: 30)
.overlay {
MyRoundedRectangle(
topLeftRadius: 15,
topRightRadius: 5,
bottomRightRadius: 15,
bottomLeftRadius: 5
)
.stroke(.red, lineWidth: 1)
}
}
Output: