IBDesignable ButtonView 右边框在方向更改时重叠(横向)

IBDesignable ButtonView right border overlapping on orientation change (Landscape)

我在使用 IBDesignable ButtonView 和方向管理我的 UITableView 时遇到问题。基本上,问题发生在我切换到横向时,UITableViewCell 内的 customView 的右边框重叠。只有当我将方向更改为横向时才会发生这种情况。它应该能够在单元格内正确显示右边框。

有人对这个问题有什么想法吗?我附上了一张关于我的布局组织方式和行为的图片:

In Portrait, working as expected

In Landscape, right border overlapping

要添加更多详细信息,每个 ButtonView 都在 Storyboard 中定义为 User Defined Runtime Attributes 的布尔值,前两个按钮也是如此。

这是IBDesignable ButtonView实现

import UIKit

@IBDesignable
class ButtonView: UIView {

    // MARK: - Properties
    @IBInspectable var image: UIImage? {
        didSet {
            imageView.image = image
        }
    }

    @IBInspectable var title: String? {
        didSet {
            titleLabel.text = title
        }
    }

    @IBInspectable var hasRightBorder: Bool = false

    @IBInspectable var disabledColor: UIColor = Colors.lightGray
    @IBInspectable var enabledColor: UIColor = Colors.primary
    @IBInspectable var iconSize: CGFloat = 16.0 {
        didSet {
            imageView.addConstraints(width: iconSize, height: iconSize)
        }
    }
    var imageView = UIImageView()
    var titleLabel = UILabel()
    var button = UIButton(type: .custom)

    var isEnabled = true {
        didSet {
            if isEnabled {
                imageView.tintColor = enabledColor
                titleLabel.textColor = enabledColor
            } else {
                imageView.tintColor = disabledColor
                titleLabel.textColor = disabledColor
            }

            button.isEnabled = isEnabled
        }
    }

    var buttonClosure: (() ->Void)?

    // MARK: - Initializers
    override init(frame: CGRect) {
        super.init(frame: frame)

        setupView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        setupView()
    }

    // MARK: - View lifecycle
    override func layoutSubviews() {
        super.layoutSubviews()

        if hasRightBorder {
            layer.addBorder(edge: .right, color: Colors.lightGray, thickness: 1.0)
        } else {
            layer.addBorder(edge: .right, color: UIColor.clear, thickness: 0.0)
        }
    }

    // MARK: - Actions
    @objc fileprivate func buttonTapped() {
        buttonClosure?()
    }

    // MARK: - Private API
    fileprivate func setupView() {
        imageView.tintColor = enabledColor
        imageView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(imageView)
        imageView.topAnchor.constraint(equalTo: topAnchor, constant: 5.0).isActive = true
        imageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true

        titleLabel.textColor = Colors.primary
        titleLabel.font = FontBook.regular.of(size: .extraSmall)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        addSubview(titleLabel)
        titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -5.0).isActive = true
        titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true

        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        addSubview(button)
        button.fillSuperview(with: -10.0)
    }

}

addBorder 实现

extension CALayer {

    func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
        let border = CALayer();

        switch edge {
        case UIRectEdge.top:
            border.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: thickness)
            break
        case UIRectEdge.bottom:
            border.frame = CGRect(x:0, y:self.frame.height - thickness, width:self.frame.width, height:thickness)
            break
        case UIRectEdge.left:
            border.frame = CGRect(x:0, y:0, width: thickness, height: self.frame.height)
            break
        case UIRectEdge.right:
            border.frame = CGRect(x:self.frame.width - thickness, y: 0, width: thickness, height:self.frame.height)
            break
        default:
            break
        }

        border.backgroundColor = color.cgColor;

        addSublayer(border)
    }

}

Here is how it looks in Storyboard

我使用不同的方法解决了这个问题。通过查看 this answer,我了解到包括旋转设备在内的许多事情都需要调用 layoutSubview。这就是边界重复的原因。我正在发布我的解决方案,以防有人遇到同样的问题。

首先,我没有定义布尔值 hasRightBorder,而是在 Storyboard

中创建了宽度为 1 的 border

然后,我在ButtonViewclass里面定义了一个UIView,设置了宽度和边框加高后添加到视图中。像魅力一样工作:)

@IBDesignable
class ButtonView: UIView {

    // MARK: - Properties
    @IBInspectable var image: UIImage? {
        didSet {
            imageView.image = image
        }
    }

    //Add the rightBorder support
    @IBInspectable var border: CGFloat = 1.0 {
        didSet {
            view.addConstraints(width: border, height: frame.size.height)
        }
    }

    // MARK: - Initializers
    override init(frame: CGRect) {
        super.init(frame: frame)

        setupView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        setupView()
    }

    //view to add right border
    var view = UIView()

    // MARK: - Private API
    fileprivate func setupView() {

        //Set the color & add it to view
        view.backgroundColor = Colors.lightGray
        view.translatesAutoresizingMaskIntoConstraints = false
        addSubview(view)

        view.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true

    }

}