UIStackView

时间:2017-11-17 16:50:24

标签: ios swift

我现在面临一个非常奇怪的问题,即相同的代码会在UIViewUIImageView上产生不同的结果。

我有自定义UITableViewCell。添加阴影并在细胞之间也有一些分离。我使用了包含阴影和圆角的容器视图。一切都按预期工作。

下面的一层我使用UIStackView,所以如果帖子根本没有图像,我可以轻松删除单元格的图像。此堆栈视图包含一个图像和另一个堆栈视图。外部容器视图顶部的角半径不起作用,因为图像没有圆角。因此,我尝试为图像以及用作叠加层的图像上方的视图实现此功能。

叠加层位于堆栈视图之外。现在,我已经写了一些代码来为这两个视图添加角半径,它在叠加层上工作得很好,但在UIImageView上却没有。即使我从堆栈视图中取出图像。

这是它的样子:

enter image description here

我使用稍大一点的圆角半径来显示它并为图像添加了边框。

我期望发生的事情:图像在正确的边上具有完全相同的宽度和角半径,如叠加层(灰色)。

以下是自定义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
    }
} 

这是单元格的整个视图树:

enter image description here

我知道,我在这里违反了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()
    }
}

enter image description here

3 个答案:

答案 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。但是,我仍然理解为什么UIViewUIImageView之间存在差异。

答案 2 :(得分:-1)

尝试使用超级电话'绘制'功能:

 override func draw(_ rect: CGRect) {
      super.draw(rect)
      setUpView()
 }