Закруглить нижние углы UIView внутри пользовательского UITableViewCell - PullRequest
0 голосов
/ 25 октября 2018

Я пытаюсь скруглить нижние углы пользовательского представления внутри ячейки табличного представления.Код, который я использую, не работает, и я не понимаю, почему ...

Итак, у меня есть UItableViewCell, а внутри contentView есть пользовательское представление containerView.Внутри этого у меня есть две метки, а внизу другой вид.Это представление должно иметь закругленные нижние углы.

Мой код:

class HomeTableViewCell: UITableViewCell {

var containerView: UIView!
var bottomDetailsView: UIView!
var titleLabel: UILabel!
var timeLabel: UILabel!

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: "tableCell")

    containerView = UIView()
    bottomDetailsView = UIView()
    timeLabel = UILabel()
    titleLabel = UILabel()


    self.contentView.addSubview(containerView)
    containerView.addSubview(bottomDetailsView)
    containerView.addSubview(titleLabel)
    containerView.addSubview(timeLabel)

    containerView.snp.makeConstraints({ (maker) in
        maker.top.equalTo(self.contentView.snp.top)
        maker.bottom.equalTo(self.contentView.snp.bottom)
        maker.left.equalTo(self.contentView.snp.left).inset(10)
        maker.right.equalTo(self.contentView.snp.right).inset(10)
    })

    bottomDetailsView.snp.makeConstraints { (maker) in
        maker.top.equalTo(containerView.snp.centerY).offset(30)
        maker.left.equalTo(containerView.snp.left)
        maker.right.equalTo(containerView.snp.right)
        maker.bottom.equalTo(containerView.snp.bottom)
    }

    timeLabel.snp.makeConstraints { (maker) in
        maker.centerX.equalTo(containerView.snp.centerX)
        maker.centerY.equalTo(containerView.snp.centerY).offset(10)
    }

    titleLabel.snp.makeConstraints { (maker) in
        maker.left.equalTo(containerView.snp.left).inset(10)
        maker.top.equalTo(containerView.snp.top).inset(10)
        maker.right.equalTo(containerView.snp.right).inset(10)
    }
}

override func layoutSubviews() {
    super.layoutSubviews()

    bottomDetailsView.backgroundColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
    containerView.backgroundColor = #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)
    containerView.layer.cornerRadius = 15.0
    timeLabel.font = timeLabel.font.withSize(24)
    timeLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    titleLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

    let path = UIBezierPath(roundedRect: bottomDetailsView.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 15, height: 15))
    let shapeLayer = CAShapeLayer()
    shapeLayer.frame = bottomDetailsView.frame
    shapeLayer.path = path.cgPath
    bottomDetailsView.layer.backgroundColor = UIColor.red.cgColor
    bottomDetailsView.layer.mask = shapeLayer
}


required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

Я использую SnapKit для автоматической разметки.Проблемный код:

let path = UIBezierPath(roundedRect: bottomDetailsView.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 15, height: 15))
let shapeLayer = CAShapeLayer()
shapeLayer.frame = bottomDetailsView.frame
shapeLayer.path = path.cgPath
bottomDetailsView.layer.backgroundColor = UIColor.red.cgColor
bottomDetailsView.layer.mask = shapeLayer

Я пробовал разные комбинации с этим кодом, но не могу заставить что-либо работать.Это не отображает абсолютно ничего.Если вместо bottomDetailsView.layer.mask = shapeLayer я пишу bottomDetailsView.layer.addSublayer(shapeLayer), вид показывает, но без скругленных углов.

Я не помню, что я сделал, но в определенный момент я достиг, что я увидел черный округлый слой сверхувида, но только если ячейка была вне экрана, а затем снова загружена с dequeueReuseableCell.Каждое решение, которое я нашел в Интернете, указывает на тот же код, который у меня есть, может быть, это должно быть сделано где-то еще?

РЕДАКТИРОВАТЬ 1:

После ответов, которые я получил,Я обновил код, и теперь он выглядит так:

class HomeTableViewCell: UITableViewCell {

var containerView: UIView!
var bottomDetailsView: BottomDetailsView!
var titleLabel: UILabel!
var timeLabel: UILabel!

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: "tableCell")

    containerView = UIView()
    bottomDetailsView = BottomDetailsView(frame: .zero)
    timeLabel = UILabel()
    titleLabel = UILabel()

    self.contentView.addSubview(containerView)

    containerView.addSubview(titleLabel)
    containerView.addSubview(timeLabel)
    containerView.addSubview(bottomDetailsView)

    containerView.snp.makeConstraints({ (maker) in
        maker.top.bottom.left.right.equalToSuperview()
    })

    titleLabel.snp.makeConstraints { (maker) in
        maker.height.equalTo(15)
        maker.top.left.right.equalTo(containerView)
        maker.bottom.equalTo(timeLabel.snp.top)
    }

    timeLabel.snp.makeConstraints { (maker) in
        maker.height.equalTo(34)
        maker.top.equalTo(titleLabel.snp.bottom)
        maker.centerX.equalTo(containerView.snp.centerX)
        maker.bottom.equalTo(bottomDetailsView.snp.top)
    }
    bottomDetailsView.snp.makeConstraints { (maker) in
        maker.top.equalTo(timeLabel.snp.bottom)
        maker.left.equalTo(containerView.snp.left)
        maker.right.equalTo(containerView.snp.right)
        maker.bottom.equalTo(containerView.snp.bottom)
    }
}

override func layoutSubviews() {
    super.layoutSubviews()

    bottomDetailsView.backgroundColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)

    containerView.backgroundColor = #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)
    containerView.layer.cornerRadius = 15.0

    timeLabel.font = timeLabel.font.withSize(24)
    timeLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    titleLabel.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    titleLabel.numberOfLines = 0
}


required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

Также я сделал подкласс UIView, как предложил Дункан С:

class BottomDetailsView: UIView {
var shapeLayer: CAShapeLayer!

//If the view's bounds change, update the shapeLayer's frame and also rebuild the path
override var bounds: CGRect {
    didSet {
        shapeLayer.frame = self.bounds
        createShapeLayerPath()
    }
}

func createShapeLayerPath() {
    let path = UIBezierPath(roundedRect: bounds,
                            byRoundingCorners: [.bottomLeft, .bottomRight],
                            cornerRadii: CGSize(width: 15.0, height: 15.0))
    shapeLayer.path = path.cgPath
}

override init(frame: CGRect) {
    super.init(frame: frame)

    shapeLayer = CAShapeLayer()
    shapeLayer.frame = bounds
    layer.mask = shapeLayer
}

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

Теперь все работает, кроме того, чтоесли я увеличу масштаб, если я выгляжу пристально, я могу видеть немного нижнего вида по углам.Они не идеально выровнены.Суть в порядке, только углы.

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Ваш код для добавления CAShapeLayer в качестве слоя маски вашего представления довольно близок.Эта строка:

shapeLayer.frame = bottomDetailsView.frame

Следует читать

shapeLayer.frame = bottomDetailsView.bounds

Кадры вида / слоя выражаются в системе координат их суперпредставления.Границы представления определяют его систему координат.

Я не пробовал ваш сложный случай табличного представления, но я создал подкласс UIView, который создает маску со скругленным дном:

class RoundedBottomCornersView: UIView {
    var shapeLayer: CAShapeLayer!

    //If the view's bounds change, update the shapeLayer's frame and also rebuild the path
    override var bounds: CGRect {
        didSet {
            shapeLayer.frame = self.bounds
            createShapeLayerPath()
        }
    }

    func createShapeLayerPath() {
        let path = UIBezierPath(roundedRect: bounds,
                                byRoundingCorners: [.bottomLeft, .bottomRight],
                                cornerRadii: CGSize(width: 15, height: 15))
        shapeLayer.path = path.cgPath
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        layer.borderWidth = 1.0

        shapeLayer = CAShapeLayer()
        shapeLayer.frame = bounds
        layer.backgroundColor = UIColor.red.cgColor
        layer.mask = shapeLayer
    }
}
0 голосов
/ 25 октября 2018

Ваши ограничения недостаточны для компоновки подпредставлений ячейки, поскольку вы задаете containerView

top, left .right, bottom

и метки timeLabel

centerX, Y

titleLabel

влево, вправо, вверху

, если вы смотрели на эти ограничения тамнет вертикального создания ограничений from сверху вниз, ячейка ожидает высоту от своего подпредставления containeView, но вы делаете обратное, поэтому вам нужно привязать метку titleLabel сверху к контейнеру (вы это сделали), и этонижняя часть к метке timeLabel top, а нижняя к нижней части контейнера, а нижняя часть контейнера уже подключена к contentView, так что автоматическое расположение может вычислить правильную высоту ячейки, и этим любоеокругление покажет

КСТАТИ: Я не знаю ваш желаемый дизайн, но вы должны следовать перехвату ограничений сверху вниз, чтобы не только показать округление, но и, что более важно, показатьвид, что вы хотите применить округление к

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...