[SOLVED] How can I transition a UIImage slowly from top to bottom for applying filter to the image?

Issue

I want to make it appear as if my image is slowly getting filtered from top to bottom. I am adding two image views. My processed image is in the background and non-processed in the front. I am making the height of non-processed image 0. Here is my code.

imageView.frame = CGRect(x: 0, y: 100, width: self.view.bounds.size.width, height: 400)
imageView.image = processedImage


let nonProcessedImageView = UIImageView()
nonProcessedImageView.frame = CGRect(x: 0, y: 100, width: self.view.bounds.size.width, height: 400)
nonProcessedImageView.image = nonProcessedImage
view.addSubview(nonProcessedImageView)

UIView.transition(with: nonProcessedImageView,
                  duration: 5.0,
                  animations: {
   nonProcessedImageView.frame = CGRect(x: 0, y: 500, width: self.view.bounds.size.width, height: 0)
   },
                  completion: {_ in
   })

The non processed image does not even appear on top of the processed.

Solution

The issue seems to be that changing the y coordinate of the frame in the animation block leads to issues when using the UIView.Animate function.

See this answer

To quote the most essential part:

You should change the center property (to move the view) and bounds
property (to change its size) instead. Those properties behave as
expected.

Since you want to just reduce the height, you don’t need to do anything to the y coordinate

let nonProcessedImageView = UIImageView()

var newImageFrame = imageView.frame

nonProcessedImageView.frame = newImageFrame
nonProcessedImageView.clipsToBounds = true
nonProcessedImageView.contentMode = .scaleAspectFit
nonProcessedImageView.image = imageView.image
view.addSubview(nonProcessedImageView)

// I set this to 1 instead of 0 as 0 does not show the image
// for some reason
newImageFrame.size.height = 1

// Update your processed image
imageView.image = processedImage

UIView.animate(withDuration: 5.0) {
    nonProcessedImageView.frame = newImageFrame
}
completion: { (isComplete) in
    if isComplete {
        nonProcessedImageView.removeFromSuperview()
    }
}

This gives some results but as you can see, the animation is not so good because as you reduce the height, the image view’s contentMode kicks in and gives the seen effect.

UIImageView animate frames swift iOS

For best results, add the new image view to a UIView and reduce the height of the UIView instead of the UIImageView

var newImageFrame = imageView.frame

let containerView = UIView(frame: newImageFrame)
containerView.clipsToBounds = true

let nonProcessedImageView = UIImageView()
nonProcessedImageView.frame = containerView.bounds
nonProcessedImageView.clipsToBounds = true
nonProcessedImageView.contentMode = .scaleAspectFit // same as original
nonProcessedImageView.image = imageView.image

containerView.addSubview(nonProcessedImageView)
view.addSubview(containerView)

newImageFrame.size.height = 1

imageView.image = processedImage

UIView.animate(withDuration: 3.0) {
    containerView.frame = newImageFrame
}
completion: { (isComplete) in
    if isComplete {
        containerView.removeFromSuperview()
    }
}

This should give you what you want:

UIImageView UIView.animate animate image view height swift iOS

Answered By – Shawn Frank

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *