Reputation: 107
I have seen quite a few tutorials online referring to the use of neumorphism design. However it appears to be only limited to SwiftUI.
Therefore it leads me to two questions:
Is this design style possible using regular storyboards (without SwiftUI) on an existing UIView?
Failing question 1, is it possible to inject a SwiftUI element, if the majority of the project is configured using storyboards.
Upvotes: 1
Views: 845
Reputation: 17
class NeumorphicButton: UIButton {
private let darkShadow = CALayer()
private let lightShadow = CALayer()
private let radius: CGFloat = 20
private let shadowRadiuss: CGFloat = 5
lazy var innerShadowLayer: CAShapeLayer = {
let shadowLayer = CAShapeLayer()
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowOffset = CGSize(width: 0.0, height: 0.0)
shadowLayer.shadowOpacity = 0.1
shadowLayer.shadowRadius = 14
shadowLayer.fillRule = .evenOdd
return shadowLayer
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupButton()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupButton()
}
override func layoutSubviews() {
super.layoutSubviews()
updateShadows()
}
private func setupButton() {
clipsToBounds = false // Important for shadows
layer.cornerRadius = radius
backgroundColor = UIColor.systemGray6 // Match with the superview's background
setupShadows()
}
private func setupShadows() {
// Dark shadow (bottom-right)
darkShadow.removeFromSuperlayer()
lightShadow.removeFromSuperlayer()
darkShadow.shadowColor = UIColor(white: 0.8, alpha: 1.0).cgColor
darkShadow.shadowOffset = CGSize(width: shadowRadiuss, height: shadowRadiuss)
darkShadow.shadowOpacity = 1
darkShadow.shadowRadius = shadowRadiuss
// Light shadow (top-left)
lightShadow.shadowColor = UIColor.white.cgColor
lightShadow.shadowOffset = CGSize(width: -shadowRadiuss, height: -shadowRadiuss)
lightShadow.shadowOpacity = 1
lightShadow.shadowRadius = shadowRadiuss
layer.insertSublayer(darkShadow, at: 0)
layer.insertSublayer(lightShadow, at: 0)
}
private func updateShadows() {
darkShadow.frame = bounds
lightShadow.frame = bounds
darkShadow.cornerRadius = radius
lightShadow.cornerRadius = radius
darkShadow.backgroundColor = backgroundColor?.cgColor
lightShadow.backgroundColor = backgroundColor?.cgColor
}
func setUpIsPressed() {
self.layer.masksToBounds = true
self.layer.addSublayer(self.innerShadowLayer)
let shadowPath = CGMutablePath()
let inset = -self.innerShadowLayer.shadowRadius * 2.0
shadowPath.addRect(self.bounds.insetBy(dx: inset, dy: inset))
shadowPath.addRect(self.bounds)
self.innerShadowLayer.path = shadowPath
}
func setUpPressedReleased() {
clipsToBounds = false
backgroundColor = UIColor.systemGray6
innerShadowLayer.removeFromSuperlayer()
setupShadows()
}
override var isHighlighted: Bool {
didSet {
if isHighlighted {
setUpIsPressed()
} else {
setUpPressedReleased()
}
}
}
}
when button pressed it will add inner shadow to make it look like pressed.
Upvotes: 0