ios - 对从 nib 加载的子视图应用阴影
问题描述
我正在从 nib 加载一个自定义视图类viewWillAppear
。加载笔尖后,我将其添加为子视图,然后应用一些约束,然后更新约束。那时我尝试在这个视图中添加一个阴影,但没有显示阴影......
仅在某些情况下, ViewController 具有包含contentView
. 所有视图的内容都在 thiscontentView
中。
这是我的代码:
视图控制器
class MyViewController: UIViewController {
@IBOutlet weak var contentView: UIView!
var matches: [Match] = []
var matchViews: [MatchDetailsView] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setMatches()
}
func setMatches() {
// Match One
let matchOneDetailsView = MatchDetailsView.instanceFromNib(match: matches.count > 0 ? matches[0] : nil, delegate: self, tag: 1)
contentView.addSubview(matchOneDetailsView)
matchOneDetailsView.translatesAutoresizingMaskIntoConstraints = false
let matchOneLeadingConstraint = NSLayoutConstraint(item: matchOneDetailsView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 16)
let matchOneTrailingConstraint = NSLayoutConstraint(item: matchOneDetailsView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: -16)
let matchOneTopConstraint = NSLayoutConstraint(item: matchOneDetailsView, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1, constant: 32)
// Match Two
let matchTwoDetailsView = MatchDetailsView.instanceFromNib(match: matches.count > 1 ? matches[1] : nil, delegate: self, tag: 2)
contentView.addSubview(matchTwoDetailsView)
matchTwoDetailsView.translatesAutoresizingMaskIntoConstraints = false
let matchTwoLeadingConstraint = NSLayoutConstraint(item: matchTwoDetailsView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 16)
let matchTwoTrailingConstraint = NSLayoutConstraint(item: matchTwoDetailsView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: -16)
let matchTwoTopConstraint = NSLayoutConstraint(item: matchTwoDetailsView, attribute: .top, relatedBy: .equal, toItem: matchOneDetailsView, attribute: .bottom, multiplier: 1, constant: 32)
// Match Three
let matchThreeDetailsView = MatchDetailsView.instanceFromNib(match: matches.count > 2 ? matches[2] : nil, delegate: self, tag: 3)
contentView.addSubview(matchThreeDetailsView)
matchThreeDetailsView.translatesAutoresizingMaskIntoConstraints = false
let matchThreeLeadingConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 16)
let matchThreeTrailingConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: -16)
let matchThreeTopConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .top, relatedBy: .equal, toItem: matchTwoDetailsView, attribute: .bottom, multiplier: 1, constant: 32)
let matchThreeBottomConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: -32)
NSLayoutConstraint.activate([matchOneLeadingConstraint, matchOneTrailingConstraint, matchOneTopConstraint, matchTwoLeadingConstraint, matchTwoTrailingConstraint, matchTwoTopConstraint, matchThreeLeadingConstraint, matchThreeTrailingConstraint, matchThreeTopConstraint, matchThreeBottomConstraint])
updateViewConstraints()
matchViews.append(matchOneDetailsView)
matchViews.append(matchTwoDetailsView)
matchViews.append(matchThreeDetailsView)
styleMatchViews()
}
func styleMatchViews() {
for view in matchViews {
view.addShadow(opacity: 0.25, yOffset: 0, xOffset: 0, radius: 5.0)
view.roundCorners(withRadius: 5.0)
}
}
}
比赛详情查看
class MatchDetailsView: UIView {
class func instanceFromNib(match: Match?, delegate: MatchDetailsViewDelegate, tag: Int) -> MatchDetailsView {
let view = UINib(nibName: "MatchDetailsView", bundle: nil).instantiate(withOwner: MatchDetailsView(), options: nil)[0] as! MatchDetailsView
view.translatesAutoresizingMaskIntoConstraints = false
view.updateMatchContent()
return view
}
}
UIViewExtension
extension UIView {
/**
Add Shadow
Puts a Drop Shadow in the UIView
*/
func addShadow(opacity: Float, yOffset: Int, xOffset: Int, radius: CGFloat) {
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOpacity = opacity
self.layer.shadowOffset = CGSize(width: xOffset, height: yOffset)
self.layer.shadowRadius = radius
self.layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
}
}
如果MatchDetailsView
nib 文件的 'clipsToBounds' 设置为 false,为什么页面加载时我的影子没有出现?layout
即使它们似乎布局正确,我是否错过了一个功能?
解决方案
您正在将 设置为.shadowPath
视图的边界......但在自动布局布局视图之后,该点的边界可能不是(可能不会是)边界。
对于“阴影视图”,最好将阴影设置在layoutSubviews()
视图本身内部。
您还应该添加和设置您的子视图,其中viewDidLoad()
viewWillAppear()
可能会多次调用(取决于您的导航),您最终会添加多个子视图副本。
所以...
像这样改变你的MatchDetailsView
班级:
class MatchDetailsView: UIView {
var opacity: CGFloat = 0.0
var xOffset: CGFloat = 0.0
var yOffset: CGFloat = 0.0
// for the shadowRadius
var sRadius: CGFloat = 0.0
// for the cornerRadius
var cRadius: CGFloat = 0.0
override func layoutSubviews() {
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOpacity = Float(opacity)
self.layer.shadowOffset = CGSize(width: xOffset, height: yOffset)
self.layer.shadowRadius = sRadius
self.layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
self.layer.cornerRadius = cRadius
}
class func instanceFromNib(match: Match?, delegate: MatchDetailsViewDelegate, tag: Int) -> MatchDetailsView {
let view = UINib(nibName: "MatchDetailsView", bundle: nil).instantiate(withOwner: MatchDetailsView(), options: nil)[0] as! MatchDetailsView
view.translatesAutoresizingMaskIntoConstraints = false
view.updateMatchContent()
return view
}
}
然后,在您的视图控制器中:
override func viewDidLoad() {
super.viewDidLoad()
setMatches()
}
func setMatches() {
// Match One
let matchOneDetailsView = MatchDetailsView.instanceFromNib(match: matches.count > 0 ? matches[0] : nil, delegate: self, tag: 1)
contentView.addSubview(matchOneDetailsView)
matchOneDetailsView.translatesAutoresizingMaskIntoConstraints = false
let matchOneLeadingConstraint = NSLayoutConstraint(item: matchOneDetailsView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 16)
let matchOneTrailingConstraint = NSLayoutConstraint(item: matchOneDetailsView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: -16)
let matchOneTopConstraint = NSLayoutConstraint(item: matchOneDetailsView, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1, constant: 32)
// Match Two
let matchTwoDetailsView = MatchDetailsView.instanceFromNib(match: matches.count > 1 ? matches[1] : nil, delegate: self, tag: 2)
contentView.addSubview(matchTwoDetailsView)
matchTwoDetailsView.translatesAutoresizingMaskIntoConstraints = false
let matchTwoLeadingConstraint = NSLayoutConstraint(item: matchTwoDetailsView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 16)
let matchTwoTrailingConstraint = NSLayoutConstraint(item: matchTwoDetailsView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: -16)
let matchTwoTopConstraint = NSLayoutConstraint(item: matchTwoDetailsView, attribute: .top, relatedBy: .equal, toItem: matchOneDetailsView, attribute: .bottom, multiplier: 1, constant: 32)
// Match Three
let matchThreeDetailsView = MatchDetailsView.instanceFromNib(match: matches.count > 2 ? matches[2] : nil, delegate: self, tag: 3)
contentView.addSubview(matchThreeDetailsView)
matchThreeDetailsView.translatesAutoresizingMaskIntoConstraints = false
let matchThreeLeadingConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 16)
let matchThreeTrailingConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: -16)
let matchThreeTopConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .top, relatedBy: .equal, toItem: matchTwoDetailsView, attribute: .bottom, multiplier: 1, constant: 32)
let matchThreeBottomConstraint = NSLayoutConstraint(item: matchThreeDetailsView, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: -32)
NSLayoutConstraint.activate([matchOneLeadingConstraint, matchOneTrailingConstraint, matchOneTopConstraint, matchTwoLeadingConstraint, matchTwoTrailingConstraint, matchTwoTopConstraint, matchThreeLeadingConstraint, matchThreeTrailingConstraint, matchThreeTopConstraint, matchThreeBottomConstraint])
matchViews.append(matchOneDetailsView)
matchViews.append(matchTwoDetailsView)
matchViews.append(matchThreeDetailsView)
styleMatchViews()
}
func styleMatchViews() {
for view in matchViews {
view.opacity = 0.25
view.yOffset = 0.0
view.xOffset = 0.0
view.sRadius = 5.0
view.cRadius = 5.0
}
}
推荐阅读
- spring - 在同一个应用程序中配置 Morphia 和 MongoTemplate
- go - 如何绕过 dgrijalva/jwt-go 中的 cve-2020-26160 漏洞?
- html - 什么引导库需要使用 modal-body?
- wordpress - Woocommerce - 排除没有上传“图库图片”的产品
- rust - 我可以阻止创建或使用类型的引用吗?
- css - 如何使用css制作滑块水平移动的动画并做出反应?
- flutter - TextStyle 不能识别accentColor 并返回错误的颜色
- java - PDFBox 2.0.9 - pdf 到带有 alpha 的图像
- python - 删除属于另一个单词的单词
- dns - 为什么我们可以创建两个具有相同 DNS 名称的区域?