1

I'm setting constraints to image view programmatically like so:

        imgScrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        imgScrollView.showsHorizontalScrollIndicator = false
        imgScrollView.showsVerticalScrollIndicator = false
        imgScrollView.bouncesZoom = false
        imgScrollView.bounces = false

        view.addSubview(imgScrollView)

        imgScrollView.translatesAutoresizingMaskIntoConstraints = false
        imgScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        imgScrollView.bottomAnchor.constraint(equalTo: toolBar.topAnchor, constant: -100).isActive = true
        imgScrollView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 0).isActive = true
        imgScrollView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: 0).isActive = true



        // add image view to scrollview
        imgView = UIImageView(frame: CGRect(x: 0, y: 0,width: 100, height: 100))

        imgScrollView.addSubview(imgView)
        imgView.translatesAutoresizingMaskIntoConstraints = false

        imgView.topAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.topAnchor, constant: 0).isActive = true
        imgView.bottomAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.bottomAnchor, constant: 0).isActive = true
        imgView.leftAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.leftAnchor, constant: 0).isActive = true
        imgView.rightAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.rightAnchor, constant: 0).isActive = true


        imgView.widthAnchor.constraint(equalTo: imgScrollView.widthAnchor, multiplier: 1).isActive = true

Now later on with button tap I'm adding additional constraint

imgView.heightAnchor.constraint(equalTo: imgScrollView.heightAnchor, multiplier: 1).isActive = true

However the constraint is not being added. Why is it happening?

  • @mezzi Why don't you just add the height constraint in the beginning itself, and just change its constant on button tap? – badhanganesh May 01 '20 at 21:45
  • well what you are trying to do ? giving left right constraint and also giving width with them ... they will conflict ... same is the case with bottom and top ...giving hight as well... – Jawad Ali May 01 '20 at 21:49
  • when I add all of the constraints left, right and width, height in the beginning when imgView is created there's no problem. No conflicts. Everything works as expected. It's when I try to add height constraint afterwards on button tap, the constraint is not being added –  May 01 '20 at 21:52
  • @badhanganesh what do you mean? Should I put nil for constant in the beginning? –  May 01 '20 at 21:54
  • 1
    I don't know what you do on the button tap, but instead of adding a new height constraint on button tap, you can add the height constraint in the beginning with height zero or something (or any default value), and then on button tap, you can change that height constant to whatever new value you want. You have to store the (height) constraint that you wish to change. – badhanganesh May 01 '20 at 21:57
  • @badhanganesh Well, I can't set the initial height constraint to 0 or any default value. I need there to be no height constraint at all. My question is why can't I add new constraint after imgView was created? –  May 01 '20 at 22:17
  • Because the view is already laid out and you need to forcefully redraw the view.. – Harsh May 02 '20 at 00:31

1 Answers1

1

Your implementation logic working for me.

  • Left image show implementation without height constraint.
  • Right image show button pressed with height constraint.

In function viewDidLoad

override func viewDidLoad() {
  super.viewDidLoad()
  view.backgroundColor = .white
  scrollView.isScrollEnabled = true
  scrollView.bounces = false
  scrollView.alwaysBounceVertical = true
  imageView.image = UIImage(color: .lightGray)

  navigationItem.rightBarButtonItem = barButtonItem
  view.addSubview(scrollView)
  scrollView.addSubview(imageView)

  scrollView.translatesAutoresizingMaskIntoConstraints = false
  imageView.translatesAutoresizingMaskIntoConstraints = false
  NSLayoutConstraint.activate([
    scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
    scrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
    scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
    scrollView.rightAnchor.constraint(equalTo: view.rightAnchor)
  ])
  NSLayoutConstraint.activate([
    imageView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
    imageView.leftAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leftAnchor),
    imageView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
    imageView.rightAnchor.constraint(equalTo: scrollView.contentLayoutGuide.rightAnchor),
    imageView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
  ])
}

In function buttonPressed

@objc func buttonPressed() {
  navigationItem.rightBarButtonItem = nil
  UIView.animate(withDuration: 1) {
    NSLayoutConstraint.activate([
      self.imageView.heightAnchor.constraint(equalTo: self.scrollView.heightAnchor)
    ])
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()
  }
}

UIImage util Create UIImage with solid color in Swift

fileprivate extension UIImage {
  convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
    let rect = CGRect(origin: .zero, size: size)
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
    color.setFill()
    UIRectFill(rect)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    guard let cgImage = image?.cgImage else { return nil }
    self.init(cgImage: cgImage)
  }
}
ssankosik
  • 88
  • 5
  • Setting constraints with NSLayoutConstraint.activate() did the trick. Not it works as expected. Thank you. –  May 02 '20 at 21:24