0
votes

Im new to IOS development and I have two buttons in the UIView and when user select the option portrait or landscape, change the UIView re-size and change the background color as well and i need to add animation for that process. As as ex: User select portrait and then user can see red color UIVIew. after click the landscape option, animation should be started and it looks like, red color image come front and change the size (changing height and width) for landscape mode and go to previous position and change color to green. i have added small UIView animation on code and it is helpful to you identify the where should we start the animation and finish it. if someone know how to it properly, please, let me know and appreciate your help. please, refer below code

import UIKit

class ViewController: UIViewController {
    
    let portraitWidth : CGFloat = 400
    let portraitHeight : CGFloat = 500
    
    let landscapeWidth : CGFloat = 700
    let landscapeHeight : CGFloat = 400
    
    var mainView: UIView!
    var mainStackView: UIStackView!
    
    let segment: UISegmentedControl = {
        let segementControl = UISegmentedControl()
        return segementControl
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.translatesAutoresizingMaskIntoConstraints = false
        
        mainStackView = UIStackView()
        mainStackView.axis = .vertical
        mainStackView.translatesAutoresizingMaskIntoConstraints = false
        mainStackView.alignment = .center
        mainStackView.distribution = .equalCentering
        self.view.addSubview(mainStackView)
        
        self.segment.insertSegment(withTitle: "Portrait", at: 0, animated: false)
        self.segment.insertSegment(withTitle: "Landscape", at: 1, animated: false)
        self.segment.selectedSegmentIndex = 0
        self.segment.addTarget(self, action: #selector(changeOrientation(_:)), for: .valueChanged)
        self.segment.translatesAutoresizingMaskIntoConstraints = false
        self.segment.selectedSegmentIndex = 0
        mainStackView.addArrangedSubview(self.segment)
        
        let safeAreaLayoutGuide = self.view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            self.mainStackView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 20),
            self.mainStackView.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor, constant: 0),
        ])
        
        NSLayoutConstraint.activate([
            self.segment.heightAnchor.constraint(equalToConstant: 35),
            self.segment.widthAnchor.constraint(equalToConstant: 300)
        ])
        
        mainView = UIView(frame: .zero)
        mainView.translatesAutoresizingMaskIntoConstraints = false
        mainStackView.addArrangedSubview(mainView)
        mainView.backgroundColor = UIColor.red
        NSLayoutConstraint.activate([
            mainView.heightAnchor.constraint(equalToConstant: portraitHeight),
            mainView.widthAnchor.constraint(equalToConstant: portraitWidth),
            mainView.topAnchor.constraint(equalTo: segment.bottomAnchor, constant: 30)
        ])
        
    }
    
    @IBAction func changeOrientation(_ sender: UISegmentedControl) {
        self.mainView.constraints.forEach{ (constraint) in
            self.mainView.removeConstraint(constraint)
        }
        UIView.animate(withDuration: 1.0) {
            if (sender.selectedSegmentIndex == 0) {
                self.mainView.backgroundColor = UIColor.red
                NSLayoutConstraint.activate([
                    self.mainView.heightAnchor.constraint(equalToConstant: self.portraitHeight),
                    self.mainView.widthAnchor.constraint(equalToConstant: self.portraitWidth),
                    self.mainView.topAnchor.constraint(equalTo: self.segment.bottomAnchor, constant: 30)
                ])
            } else {
                self.mainView.backgroundColor = UIColor.green
                NSLayoutConstraint.activate([
                    self.mainView.heightAnchor.constraint(equalToConstant: self.landscapeHeight),
                    self.mainView.widthAnchor.constraint(equalToConstant: self.landscapeWidth),
                    self.mainView.topAnchor.constraint(equalTo: self.segment.bottomAnchor, constant: 30)
                ])
            }
        }
    }
    
    
}

existing output

updated logic

@IBAction func changeOrientation(_ sender: UISegmentedControl) {
    UIView.animate(withDuration: 4.0) {
        if (sender.selectedSegmentIndex == 0) {
            self.mainView.backgroundColor = UIColor.red
            self.widthConstraint.constant = self.portraitWidth
            self.heightConstraint.constant = self.portraitWidth
        } else {
            self.mainView.backgroundColor = UIColor.green
            self.widthConstraint.constant = self.landscapeWidth
            self.heightConstraint.constant = self.landscapeHeight
        }
        self.mainView.layoutIfNeeded()
    } }
1
just FYI there is no purpose in all the "self."s inside viewDidLoad and elsewhere.Fattie
@Fattie Yes, for testing i have added all of them under viewDidLoad method, i guess , this is the easy way to ask question in here, all things are in one method :)Dileepa Chandrasekara
hi Dileepa! I have put in an answer. Just to be clear what I mean is you can delete the "self." there. self.view.addSubview is wrong. it should be view.addSubview. Good luck!Fattie

1 Answers

0
votes

It's possible, the basic problem is:

• It's not possible to animate an actual change between one constraint and another.

To change size or shape you simply animate the length of a constraint.


While you are learning I would truly urge you to simply animate the constraints.

So, don't try to "change" constraints, simply animate the length of one or the other.

yourConstraint.constant = 99  // it's that easy

I also truly urge you to just lay it out on storyboard.

You must master that first!

Also there is no reason at all for the stack view, get rid of it for now.

Just have an outlet

 @IBOutlet var yourConstraint: NSLayoutConstraint!

and animate

    UIView.animateWithDuration(4.0) {
        self.yourConstraint.constant = 666
        self.view.layoutIfNeeded()
    }

Be sure to search in Stack Overflow for "iOS animate constraints" as there is a great deal to learn.

  • Do this on storyboard, it will take 20 seconds tops for such a simple thing. Once you have mastered storyboard, only then move on to code if there is some reason to do so

  • Forget the stack view

  • Simply animate the constant of the constraint(s) to change the size, shape or anything you like.

  • Be sure to google for the many great articles "animating constraints in iOS" both here on SO and other sites!