Swift Autolayout - якорь высоты не применяется - PullRequest
0 голосов
/ 11 апреля 2020

Я работаю над «контроллером представления профиля», который находится внутри TableViewCell, а размер ячейки таблицы установлен как UITableView.automaticDimension: enter image description here

Проблема в том, что Я хотел бы установить вид фона изображения (синий) с переменной высотой, основанной на ширине ячейки и соотношении 16: 9. По какой-то причине я не могу изменить высоту вида, даже если я установил константу.

Вот код:

let topView : UIView = {
   let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.layer.cornerRadius = 20
    view.backgroundColor = .yoofitDarkBlue
    view.layer.masksToBounds = true
    view.layer.shadowColor = UIColor.lightGray.cgColor
    view.layer.borderWidth = 0.5
    view.layer.borderColor = UIColor.yoofitDarkBlue.cgColor
    view.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
    view.layer.shadowRadius = 12.0
    view.layer.shadowOpacity = 0.7
    return view
}()

let userImage : UIImageView = {
   let i = UIImageView()
    i.translatesAutoresizingMaskIntoConstraints = false
    i.image = UIImage(named: "user2")
    i.layer.masksToBounds = true
    i.layer.cornerRadius = 75
    i.layer.borderWidth = 1
    i.layer.borderColor = UIColor.white.cgColor
    return i
}()

var userNameLabel:UILabel = {
    let l = UILabel()
    l.translatesAutoresizingMaskIntoConstraints = false
    l.font = UIFont(name: "AvenirNext-DemiBold", size: 20)
    l.textAlignment = .center
    l.textColor = .yoofitBlack
    return l
}()

func setupViews() {
    self.backgroundColor = .clear
    self.selectionStyle = .none
    addSubview(topView)
    let width = self.frame.width
    print(width) // print 320
    topView.topAnchor.constraint(equalTo: topAnchor, constant: 10).isActive = true
    topView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
    topView.rightAnchor.constraint(equalTo: rightAnchor, constant:  -8).isActive = true
    topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true // this doesn't work even if I set another number like 600
    topView.layoutIfNeeded()
    addSubview(userImage)
    userImage.centerYAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true
    userImage.centerXAnchor.constraint(equalTo: topView.centerXAnchor).isActive = true
    userImage.widthAnchor.constraint(equalToConstant: 150).isActive = true
    userImage.heightAnchor.constraint(equalToConstant: 150).isActive = true
    addSubview(userNameLabel)
    userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 10).isActive = true
    userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
    userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
    userNameLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
    userNameLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -20).isActive = true
}

1 Ответ

0 голосов
/ 12 апреля 2020

ОБРАТИТЕ ВНИМАНИЕ, 2 ответа на этот вопрос. Последний, безусловно, правильный, но первый, возможно, может помочь другим.

Так вот, как я это исправил, но я надеюсь получить лучшие ответы. Этот ответ помог мне go выбрать правильный путь (iOS: Как выровнять центр вида по основанию другого вида с помощью AutoLayout)

  1. I Я добавил содержащий вид, который в два раза больше необходимого размера моего вида сверху (синий).
  2. Я центрировал изображение на вмещающем виде.

    self.conteiningView.backgroundColor = .red // I made this red so you can visually see how the views are related to each other
    let width = self.frame.width
    
    self.addSubview(conteiningView)
    conteiningView.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
    conteiningView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
    conteiningView.rightAnchor.constraint(equalTo: rightAnchor, constant:  -8).isActive = true
    conteiningView.heightAnchor.constraint(equalToConstant: (width/16*9)*2).isActive = true // twice of the blue view 
    conteiningView.layoutIfNeeded()
    
    self.conteiningView.addSubview(topView)
    topView.topAnchor.constraint(equalTo: conteiningView.topAnchor).isActive = true
    topView.leftAnchor.constraint(equalTo: conteiningView.leftAnchor).isActive = true
    topView.rightAnchor.constraint(equalTo: conteiningView.rightAnchor).isActive = true
    topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true // 16:9 ration 
    
    
    conteiningView.addSubview(userImage)
    userImage.centerYAnchor.constraint(equalTo: conteiningView.centerYAnchor).isActive = true
    userImage.centerXAnchor.constraint(equalTo: conteiningView.centerXAnchor).isActive = true
    userImage.widthAnchor.constraint(equalToConstant: width/2).isActive = true
    userImage.heightAnchor.constraint(equalToConstant: width/2).isActive = true
    userImage.layer.cornerRadius = width/4 // to mantain nice proportions 
    
    conteiningView.addSubview(userNameLabel)
    userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 10).isActive = true
    userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
    userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
    userNameLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
    

С красным фоном:

enter image description here С четким фоном:

enter image description here

ОБНОВЛЕНИЕ: Ответ выше работает, но я действительно нашел проблему:

  1. Даже если я установил:

    self.tableView.rowHeight = UITableView.automaticDimension
    self.tableView.estimatedRowHeight = 300
    
  2. Для некоторых (глупый я) я также реализовал:

    tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
    

Это, конечно, не реализовано для автоматов c размерность для работы.

удаление, позволяющее использовать следующий код для достижения того же результата, но без установки предварительно определенной высоты:

   self.addSubview(conteiningView)
   conteiningView.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
   conteiningView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
   conteiningView.rightAnchor.constraint(equalTo: rightAnchor, constant:  -8).isActive = true
   conteiningView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
   conteiningView.layoutIfNeeded()

   self.conteiningView.addSubview(topView)
   topView.topAnchor.constraint(equalTo:     conteiningView.topAnchor).isActive = true
   topView.leftAnchor.constraint(equalTo: conteiningView.leftAnchor).isActive = true
   topView.rightAnchor.constraint(equalTo: conteiningView.rightAnchor).isActive = true
   topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true

   conteiningView.addSubview(userImage)
   userImage.centerYAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true // the vertical center is now set nicely at bottom edge of my top view. 
   userImage.centerXAnchor.constraint(equalTo: topView.centerXAnchor).isActive = true
   userImage.widthAnchor.constraint(equalToConstant: width/2).isActive = true
   userImage.heightAnchor.constraint(equalToConstant: width/2).isActive = true
    userImage.layer.cornerRadius = width/4

   conteiningView.addSubview(userNameLabel)
   userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 2).isActive = true
   userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
   userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
   userNameLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true
...