I've made a button style to create circular neumorphic buttons in my app as follows:
struct NeumorphicCircleButtonStyle: ButtonStyle {
var startPoint: UnitPoint
var endPoint: UnitPoint
var padding: CGFloat?
var bgColor: Color?
var bgColorOffset: Color?
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(padding ?? 30)
.contentShape(Circle())
.background(
Group{
if configuration.isPressed {
Circle()
.fill(bgColor ?? Color.backgroundColor)
.overlay(
Circle()
.stroke(Color.black.opacity(0.7), lineWidth: 4)
.blur(radius: 4)
.offset(x: 2, y: 2)
.mask(Circle().fill(LinearGradient(colors: [Color.black, Color.clear], startPoint: startPoint, endPoint: endPoint)))
)
.overlay(
Circle()
.stroke(bgColorOffset ?? Color.backgroundColorOffset, lineWidth: 8)
.blur(radius: 4)
.offset(x: -2, y: -2)
.mask(Circle().fill(LinearGradient(colors: [Color.clear, Color.black], startPoint: startPoint, endPoint: endPoint)))
)
} else {
Circle()
.fill(bgColor ?? Color.backgroundColor)
.shadow(color: Color.black.opacity(0.25), radius: 10, x: 10, y: 10)
.shadow(color: bgColorOffset ?? Color.backgroundColorOffset.opacity(0.7), radius: 10, x: -5, y: -5)
}
}
)
}
// TODO: this will change the x y on the first set and need to make for other x y sets for direction, but can't find a good place for the logic, can't call it from in the makebody anywhere
func getXoffetInnerShadow() -> Int {
switch endPoint {
case .bottomTrailing:
return 2
case .bottomLeading:
return -2
case .topTrailing:
return 2
case .topLeading:
return -2
case .leading:
return -2
case .trailing:
return 2
default:
return 0
}
}
func getYoffsetInnerShadow() -> Int {
switch endPoint {
case .bottomTrailing:
return 2
case .bottomLeading:
return 2
case .bottom:
return 2
case .topTrailing:
return -2
case .topLeading:
return -2
case .top:
return -2
default:
return 0
}
}
func getXoffetInnerHighlight() -> Int {
switch endPoint {
case .bottomTrailing:
return -2
case .bottomLeading:
return 2
case .topTrailing:
return -2
case .topLeading:
return -2
case .leading:
return 2
case .trailing:
return -2
default:
return 0
}
}
func getYoffsetInnerHighlight() -> Int {
switch endPoint {
case .bottomTrailing:
return -2
case .bottomLeading:
return -2
case .bottom:
return -2
case .topTrailing:
return 2
case .topLeading:
return 2
case .top:
return 2
default:
return 0
}
}
func getXoffsetShadow() -> Int {
switch endPoint {
case .bottomTrailing:
return 10
case .bottomLeading:
return -10
case .topTrailing:
return 10
case .topLeading:
return -10
case .leading:
return -10
case .trailing:
return 10
default:
return 0
}
}
func getYoffsetShadow() -> Int {
switch endPoint {
case .bottomTrailing:
return 10
case .bottomLeading:
return 10
case .bottom:
return 10
case .topTrailing:
return -10
case .topLeading:
return -10
case .top:
return -10
default:
return 0
}
}
func getXoffsetHighlight() -> Int {
switch endPoint {
case .bottomTrailing:
return -10
case .bottomLeading:
return 10
case .topTrailing:
return -10
case .topLeading:
return 10
case .leading:
return 10
case .trailing:
return -10
default:
return 0
}
}
func getYoffsetHighlight() -> Int {
switch endPoint {
case .bottomTrailing:
return -10
case .bottomLeading:
return -10
case .bottom:
return -10
case .topTrailing:
return 10
case .topLeading:
return 10
case .top:
return 10
default:
return 0
}
}
}
// this is how I init my gradient if you want a working example
extension LinearGradient {
init(_ colors: Color..., startPoint: UnitPoint, endPoint: UnitPoint) {
self.init(gradient: Gradient(colors: colors), startPoint: startPoint, endPoint: endPoint)
}
}
I was attempting to change the offsets of my two shadows and highlights based off the gradient endpoint passed to the style so that the inner and outer glows and shadows are always on the appropriate sides of the button. However, trying to add a switch case to the offset values or function calls to return the appropriate values spits out a Closure containing control flow statement cannot be used with result builder 'CommandsBuilder'
compile time exception.
Is there any way to set the offset values of my shadows and highlights based off the UnitPoint given to the Style for direction, or do I have to make a button style for every possibility (which seems like an unfeasible expectation)?
Any and all help or suggestions is and are greatly appreciated!
CommandsBuilder
in the code you posted. On what line is the compiler flagging the error? – Orpiment