skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    This works for top to bottom transition.

    imageView.frame = CGRect(x: 0, y: 100, width: self.view.bounds.width, height: 400)
    imageView.image = nonProcessedImage
    view.addSubview(imageView)
        
    let frontView = UIView(frame: CGRect(x: 0, y: 100, width: self.view.frame.width, height: 0))
    frontView.clipsToBounds = true
    view.addSubview(frontView)
    
    let nonProcessedImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: 400))
    nonProcessedImageView.image = processedImage
    nonProcessedImageView.clipsToBounds = true
    frontView.addSubview(nonProcessedImageView)
        
    UIView.transition(with: frontView, duration: 5, options: [.allowAnimatedContent], animations: {
        frontView.frame = CGRect(x: 0, y: 100, width: self.view.frame.width, height: 400)
    }, completion: nil)
    

  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search