我现在面临一个非常奇怪的问题,即相同的代码会在UIView
和UIImageView
上产生不同的结果。
我有自定义UITableViewCell
。添加阴影并在细胞之间也有一些分离。我使用了包含阴影和圆角的容器视图。一切都按预期工作。
下面的一层我使用UIStackView
,所以如果帖子根本没有图像,我可以轻松删除单元格的图像。此堆栈视图包含一个图像和另一个堆栈视图。外部容器视图顶部的角半径不起作用,因为图像没有圆角。因此,我尝试为图像以及用作叠加层的图像上方的视图实现此功能。
叠加层位于堆栈视图之外。现在,我已经写了一些代码来为这两个视图添加角半径,它在叠加层上工作得很好,但在UIImageView上却没有。即使我从堆栈视图中取出图像。
这是它的样子:
我使用稍大一点的圆角半径来显示它并为图像添加了边框。
我期望发生的事情:图像在正确的边上具有完全相同的宽度和角半径,如叠加层(灰色)。
以下是自定义UIImageView类的代码:
import UIKit
@IBDesignable
class RoundedImageView: UIImageView {
@IBInspectable var cornerRadius: CGFloat = 0.0 { didSet { setUpView() } }
@IBInspectable var isOnlyTop: Bool = false { didSet { setUpView() } }
override func awakeFromNib() {
super.awakeFromNib()
}
override func draw(_ rect: CGRect) {
setUpView()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setUpView()
}
func setUpView() {
self.clipsToBounds = true
self.layer.borderColor = UIColor.green.cgColor
self.layer.borderWidth = 2.0
if isOnlyTop {
setTopCornerRadius()
} else {
self.layer.cornerRadius = cornerRadius
}
}
func setTopCornerRadius() {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners:[.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let maskLayer = CAShapeLayer()
maskLayer.frame = self.bounds
maskLayer.path = path.cgPath
self.layer.mask = maskLayer
self.layer.masksToBounds = true
}
}
我已从圆角视图中复制了代码。但是,为了完成,我将在下面添加:
import UIKit
@IBDesignable
class RoundedView: UIView {
@IBInspectable var cornerRadius: CGFloat = 0.0 { didSet { setUpView() } }
@IBInspectable var isOnlyTop: Bool = false { didSet { setUpView() } }
override func awakeFromNib() {
super.awakeFromNib()
setUpView()
}
override func draw(_ rect: CGRect) {
setUpView()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setUpView()
}
func setUpView() {
self.clipsToBounds = true
self.layer.borderColor = UIColor.red.cgColor
//self.layer.borderWidth = 2.0
if isOnlyTop {
setTopCornerRadius()
} else {
self.layer.cornerRadius = cornerRadius
}
}
private func setTopCornerRadius() {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners:[.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let maskLayer = CAShapeLayer()
maskLayer.frame = self.bounds
maskLayer.path = path.cgPath
self.layer.mask = maskLayer
}
}
这是单元格的整个视图树:
我知道,我在这里违反了DRY原则,但我刚刚为UIView和UIImageView编写了相同的代码,因此我可以验证它为什么不起作用。
提示:请注意,我在此单元格中有两次相同的UIImage( Post Image 和 Image out of stack view ),因为我认为它可能是由约束或堆栈视图引起的。因此,堆栈视图外部的图像与叠加视图具有完全相同的约束。
这么长的故事简短:你知道为什么我的UIImageView尺寸错误,并且也没有应用在叠加视图(UIView)上完美运行的角半径。提前谢谢!
编辑:预期结果应如下所示。除非图像的顶角也应该是圆角的(你会看到图像顶角的差异很小?这是由叠加引起的。它有正确的圆角半径,但图像没有)
编辑2:我被要求添加视图控制器的代码。但是,我不会在这里做任何改变。
import UIKit
protocol PostListDisplayLogic: class {
}
class PostListViewController: UIViewController, PostListDisplayLogic, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var interactor: PostListBusinessLogic?
var router: (NSObjectProtocol & PostListRoutingLogic & PostListDataPassing)?
// MARK: Object lifecycle
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
// MARK: Setup
private func setup() {
let viewController = self
let interactor = PostListInteractor()
let presenter = PostListPresenter()
let router = PostListRouter()
viewController.interactor = interactor
viewController.router = router
interactor.presenter = presenter
presenter.viewController = viewController
router.viewController = viewController
router.dataStore = interactor
}
// MARK: Routing
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let scene = segue.identifier {
let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
if let router = router, router.responds(to: selector) {
router.perform(selector, with: segue)
}
}
}
// MARK: View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
tableView.register(UINib(nibName: "PostCell", bundle: nil), forCellReuseIdentifier: "PostCell")
}
// MARK: TableView DataSource & Delegate
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell {
return cell
}
return UITableViewCell()
}
}
答案 0 :(得分:0)
您应该手动将其绘制到图层中。没有预定义的功能来实现这一目标。
答案 1 :(得分:0)
我能够解决它。我发现图像的帧总是有错误的大小。
但是,我将代码更改为以下内容:
RoundedImageView:
import UIKit
@IBDesignable
class RoundedImageView: UIImageView {
@IBInspectable var cornerRadius: CGFloat = 0.0 { didSet { setUpView() } }
func setUpView() {
self.clipsToBounds = true
setTopCornerRadius(rect: self.bounds)
}
func setTopCornerRadius(rect: CGRect) {
let path = UIBezierPath(roundedRect: rect, byRoundingCorners:[.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let maskLayer = CAShapeLayer()
maskLayer.frame = rect
maskLayer.path = path.cgPath
self.layer.mask = maskLayer
self.layer.masksToBounds = true
}
}
在PostViewController中,我使用'willDisplay cell':
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let postCell = cell as? PostCell, let postImage = postCell.postImage {
postCell.postImage.setTopCornerRadius(rect: CGRect(x: postImage.frame.origin.x, y: postImage.frame.origin.y, width: (cell.frame.width - 16.0), height: postImage.frame.size.height))
}
}
当单元格已经具有正确的大小时,将调用后一种方法。注意我在单元格边缘使用了-16.0。但是,我仍然理解为什么UIView
和UIImageView
之间存在差异。
答案 2 :(得分:-1)
尝试使用超级电话'绘制'功能:
override func draw(_ rect: CGRect) {
super.draw(rect)
setUpView()
}