您的“目标”图像与您为“Neumorphism informations”发布的链接中的示例并不真正匹配,因此不确定这是否会为您提供所需的确切结果。
但是,一些注意事项...
-
draw()绝对不是您要在其中创建和添加/插入子层。
- 您可以使用
CAGradientLayer 来获得“内在”外观(基于您的目标图像)
- 您可以添加
UIImageView 作为子视图来保存图像。
所以,这里有一个例子 UIView 子类:
class NeuView: UIView {
public var image: UIImage? {
didSet {
imgView.image = image
}
}
private let imgView = UIImageView()
private let darkShadow = CALayer()
private let lightShadow = CALayer()
private let gradientLayer = CAGradientLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() -> Void {
// add sublayers
self.layer.addSublayer(darkShadow)
self.layer.addSublayer(lightShadow)
self.layer.addSublayer(gradientLayer)
darkShadow.shadowColor = UIColor.black.withAlphaComponent(0.2).cgColor
darkShadow.shadowOffset = CGSize(width: 5, height: 5)
darkShadow.shadowOpacity = 1
darkShadow.shadowRadius = 10
lightShadow.shadowColor = UIColor.white.withAlphaComponent(0.9).cgColor
lightShadow.shadowOffset = CGSize(width: -5, height: -5)
lightShadow.shadowOpacity = 1
lightShadow.shadowRadius = 10
// 45-degree gradient layer
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 1)
self.layer.borderColor = UIColor.white.withAlphaComponent(0.5).cgColor
layer.borderWidth = 3
// very light gray background color
let bkgColor = UIColor(white: 0.95, alpha: 1.0)
darkShadow.backgroundColor = bkgColor.cgColor
lightShadow.backgroundColor = bkgColor.cgColor
// set gradient colors from
// slightly darker than background to
// slightly lighter than background
let c1 = UIColor(white: 0.92, alpha: 1.0)
let c2 = UIColor(white: 0.97, alpha: 1.0)
gradientLayer.colors = [c1.cgColor, c2.cgColor]
// image view properties
imgView.contentMode = .scaleAspectFit
imgView.translatesAutoresizingMaskIntoConstraints = false
//imgView.layer.masksToBounds = true
addSubview(imgView)
NSLayoutConstraint.activate([
// let's make the image view 60% of self
imgView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.6),
imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor),
imgView.centerXAnchor.constraint(equalTo: centerXAnchor),
imgView.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
override func layoutSubviews() {
super.layoutSubviews()
// set all layers' frames to bounds
darkShadow.frame = bounds
lightShadow.frame = bounds
gradientLayer.frame = bounds
// set all layers' cornerRadius to one-half height
let cr = bounds.height * 0.5
darkShadow.cornerRadius = cr
lightShadow.cornerRadius = cr
gradientLayer.cornerRadius = cr
layer.cornerRadius = cr
}
}
还有一个示例视图控制器:
class NeuTestVC: UIViewController {
let neuView = NeuView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
guard let img = UIImage(named: "neu01") else {
print("Could not load image!")
return
}
neuView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(neuView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
neuView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
neuView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
neuView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
neuView.heightAnchor.constraint(equalTo: neuView.widthAnchor),
])
// set the image
neuView.image = img
}
}
使用此图片(透明背景):
这是结果:
通过调整颜色、阴影属性等,这可能会给你想要的结果。
编辑
这是NewView 类的修改版本。
我们不使用渐变层,而是添加一个带有“孔”切口的CAShapeLayer,并使用该层投射“内阴影”:
class NeuView: UIView {
public var image: UIImage? {
didSet {
imgView.image = image
}
}
private let imgView = UIImageView()
// "outer" shadows
private let darkShadow = CALayer()
private let lightShadow = CALayer()
// "inner" shadow
private let innerShadowLayer = CAShapeLayer()
private let innerShadowMaskLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() -> Void {
// add sublayers
self.layer.addSublayer(darkShadow)
self.layer.addSublayer(lightShadow)
self.layer.addSublayer(innerShadowLayer)
darkShadow.shadowColor = UIColor.black.withAlphaComponent(0.2).cgColor
darkShadow.shadowOffset = CGSize(width: 5, height: 5)
darkShadow.shadowOpacity = 1
darkShadow.shadowRadius = 10
lightShadow.shadowColor = UIColor.white.withAlphaComponent(0.9).cgColor
lightShadow.shadowOffset = CGSize(width: -5, height: -5)
lightShadow.shadowOpacity = 1
lightShadow.shadowRadius = 10
self.layer.borderColor = UIColor.white.withAlphaComponent(0.5).cgColor
//layer.borderWidth = 3
// very light gray background color
let bkgColor = UIColor(red: 0.94, green: 0.95, blue: 0.99, alpha: 1.0) // UIColor(white: 0.95, alpha: 1.0)
darkShadow.backgroundColor = bkgColor.cgColor
lightShadow.backgroundColor = bkgColor.cgColor // UIColor(white: 0.98, alpha: 1.0).cgColor
// image view properties
imgView.contentMode = .scaleAspectFit
imgView.translatesAutoresizingMaskIntoConstraints = false
//imgView.layer.masksToBounds = true
addSubview(imgView)
NSLayoutConstraint.activate([
// let's make the image view 60% of self
imgView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.6),
imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor),
imgView.centerXAnchor.constraint(equalTo: centerXAnchor),
imgView.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
override func layoutSubviews() {
super.layoutSubviews()
// set dark and light shadow layers' frames to bounds
darkShadow.frame = bounds
lightShadow.frame = bounds
// set self.layer and dark and light shadow layers' cornerRadius to one-half height
let cr = bounds.height * 0.5
darkShadow.cornerRadius = cr
lightShadow.cornerRadius = cr
self.layer.cornerRadius = cr
// for the "inner" shadow,
// rectangle path needs to be larger than
// bounds + shadow offset + shadow raidus
// so the shadow doesn't "bleed" from all sides
let path = UIBezierPath(rect: bounds.insetBy(dx: -40, dy: -40))
// create a path for the "hole" in the layer
let circularHolePath = UIBezierPath(ovalIn: bounds)
// this "cuts a hole" in the path
path.append(circularHolePath)
path.usesEvenOddFillRule = true
innerShadowLayer.path = path.cgPath
innerShadowLayer.fillRule = .evenOdd
// fillColor doesn't matter - just needs to be opaque
innerShadowLayer.fillColor = UIColor.white.cgColor
// mask the layer, so we only "see through the hole"
innerShadowMaskLayer.path = circularHolePath.cgPath
innerShadowLayer.mask = innerShadowMaskLayer
// adjust properties as desired
innerShadowLayer.shadowOffset = CGSize(width: 15, height: 15)
innerShadowLayer.shadowColor = UIColor(white: 0.0, alpha: 1.0).cgColor
innerShadowLayer.shadowRadius = 5
// setting .shadowOpacity to a very small value (such as 0.025)
// results in very light shadow
// set .shadowOpacity to 1.0 to clearly see
// what the shadow is doing
innerShadowLayer.shadowOpacity = 0.025
}
}
示例视图控制器:
class NeuTestVC: UIViewController {
let neuView = NeuView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 0.94, green: 0.95, blue: 0.99, alpha: 1.0)
guard let img = UIImage(named: "neu01") else {
print("Could not load image!")
return
}
neuView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(neuView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
neuView.topAnchor.constraint(equalTo: g.topAnchor, constant: 60.0),
neuView.widthAnchor.constraint(equalToConstant: 125.0),
neuView.heightAnchor.constraint(equalTo: neuView.widthAnchor),
neuView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
])
// set the image
neuView.image = img
}
}
结果 - 顶部实例的“内阴影”不透明度设置为 0.9(使其清晰可见)...底部实例设置为 0.025: