rounded corners while extending subview beyond superview's bounds - ios

I'm designing a specific animation. The image scales beyond bounds, shrinks to appropriate size and than falls down. You can see what I got so far is this video: https://vid.me/i1bx.
The effect I would like to achieve is that the first imageView (the grey one) has rounded corners. Setting the cornerRadius and clipsToBounds of first imageView to true does that, but disables the scaling effect of second imageView(firstScaleImageView) beyond first imageView's bounds.
Is it possible to have rounded corners and also be capable of expanding the imageView beyond superviews's bounds?
This is my code:
#IBAction func goButtonpressed(sender: UIButton) {
firstScaleImageView = UIImageView(frame: bounceFrame)
firstScaleImageView.image = UIImage(named: "1")
firstScaleImageView.transform = CGAffineTransformScale(firstScaleImageView.transform, 0, 0)
firstImageView.addSubview(firstScaleImageView)
UIView.animateWithDuration(0.4, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 10, options: UIViewAnimationOptions.CurveLinear, animations: {
self.firstScaleImageView.transform = CGAffineTransformIdentity
}, completion: {_ in
self.firstImageView.clipsToBounds = true
})
}
#IBAction func backButtonPressed(sender: UIButton) {
UIView.animateWithDuration(0.3, animations: {
self.firstScaleImageView.transform = CGAffineTransformTranslate(self.firstScaleImageView.transform, 0, self.firstImageView.frame.height)
}, completion: {_ in
self.firstImageView.clipsToBounds = false
self.firstScaleImageView.removeFromSuperview()
})
}

Try to set clipsToBounds to false (I don't think you need it for the corner radius).

Related

Shrink heightConstraint animation issue

I'm trying to make pull up menu view
I made this pull up view using xib and attached to ViewController
and added pan gesture on pull up view
lastly, I updated height constraint using pan gesture for animation.
func pullUpControlView(_ pullUpControlView: PullUpControlView, didPanned height: CGFloat, animated: Bool) {
self.pullUpControlViewHeightConstraint?.constant = height
if animated {
UIView.animate(withDuration: 10, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}
this is my code it's animation works fine when view got maximum height,
but when minimising view, view is minimised immediately and start move to down slowly (weird animation)
how can I make this animation correctly (shrink height from top to bottom)
func pullUpControlView(_ pullUpControlView: PullUpControlView, didPanned height: CGFloat, animated: Bool) {
UIView.animate(withDuration: 5, animations: {() -> Void in
self.view.layoutIfNeeded()
}, completion: {(_ finished: Bool) -> Void in
self.pullUpControlViewHeightConstraint?.constant = height
self.view.layoutIfNeeded()
//if animation is finished ("finished" == *YES*), then hidden = "finished" ... (aka hidden = *YES*)
})
}

UIView animation with autolayout and child views

I have a weird problem that seems to be fairly easy to solve. I think I could use some workaround to be able to have the behavior that I want but I want to know if there is a better way to do it.
I have a view called contentView (blue in the image) that it will expand its height using a UIView.animation, this is no problem at all and works as expected.
The problem here is that this view has a child component (a button) that has an autolayout constraint to its bottom equal to 22 like this:
This is the autolayout constraint:
If I do the height resize without the animation it works fine, the view height change and the button are always 22 points of the bottom of the contentView. But when I use an animation to make this change more smoothy and user-friendly the button moves to the end position before the animation even start.
I want to know how I could achieve a smooth animation here but with the button moving along its parent view
The part of the code that handles the animation is pretty straightforward but I'll post it in here:
#IBAction func openDetail(_ sender: ExpandCourseDetail) {
let rotation = sender.getOpen() ? CGAffineTransform.identity : CGAffineTransform(rotationAngle: CGFloat.pi)
UIView.animate(withDuration: 0.5, delay: 0.1, options: [.curveEaseInOut], animations: {
sender.transform = rotation
}, completion: {
success in
sender.setOpen(!sender.getOpen())
})
UIView.animate(withDuration: 1.0, delay: 0.5, options: [.curveEaseInOut], animations: {
self.contentView.frame.size.height = sender.getOpen() ? self.contentView.frame.height - 300 : self.contentView.frame.height + 300
}, completion: nil)
}
As a side note, the button itself has an animation that rotates the button 180 degrees to show the user that the view is expanding.
Thank you so much for your help.
It's super easy with constraints, just create a superView height constraint IBOutlet and change its constant value.
#IBAction func btnPressed(_ sender: UIButton) {
self.toggleButton.isSelected = !sender.isSelected
//Animation starts here
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.7) {
if self.toggleButton.isSelected {
//transform button
self.toggleButton.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
//change your ParentView height to desired one
self.constContentViewHeight.constant = self.view.frame.size.height - 220
self.view.layoutIfNeeded()
} else {
self.toggleButton.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi*2))
// Set height constraint to original value
self.constContentViewHeight.constant = 250
self.view.layoutIfNeeded()
}
}
}
I have created a demo, check it out.
The issue you are facing is due to two animation blocks. So I have changed some lines and put both button transformation and height animation into one animation block.
func openDetail(_ sender: ExpandCourseDetail) {
let isOpen = sender.getOpen() ? CGAffineTransform.identity : CGAffineTransform(rotationAngle: CGFloat.pi)
UIView.animate(withDuration: 1.0, delay: 0.5, options: [.curveEaseInOut], animations: {
sender.transform = rotation
self.contentView.frame.size.height = self.contentView.frame.height + (isOpen ? 300 : -300)
}, completion: { (success) in
sender.setOpen(!isOpen)
})
}

iOS/Swift: Use UIView.animate to animate text getting added/removed from UITextView

I am adding and removing attributed text from a UITextView. I wish to use UIView.animate to add an animation to when text is appended to the text view and when that appended text is removed from the text view. So far, I have this, but it does not cause any noticeable animation on the text view:
UIView.animate(withDuration: 1, delay: 0, options: .CurveLinear, animations: {
self.view.layoutIfNeeded()
self.textView.attributedText = newAttributedText
}, completion: { finished in
print("Animation completed")
}
// prints "Animation completed", but no animation occurs
You cannot animate changing of text in that manner. There is a list of animatable properties of CALayer class and UIView class.
Set text cannot be animated by UIView.animate. Only changes like transparency, colors, shape, location, etc can be animated by the UIView.animate.
Here is an example of animating origin and transparency change with code looks like
self.textView.text = "test Animation"
self.textView.alpha = 0
UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
var frame = self.textView.frame
frame.origin.x = frame.origin.x + 50
frame.origin.y = frame.origin.y + 50
self.textView.frame = frame
self.textView.alpha = 1
}, completion: { finished in
print("Animation completed")
})
And animation looks like
Here is my solution (swift 3 ) :
let animator = UIViewPropertyAnimator(duration: 0.2, curve: .easeOut, animations: {
self.textView2.frame = self.textView2.frame.offsetBy(dx: 20 , dy: 25)
} )
animator.startAnimation()

shrink width of button with animation issue

I want to replicate this animation in my project
So what I did try is:
To transform scale X .. but the problem is it also shrinks the title of a button.
self.transform = CGAffineTransform.identity
UIView.animate(withDuration: duration, delay: delayTime,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.7,
options: [.curveEaseIn],
animations: {
self.transform = CGAffineTransform(scaleX: 0.5, y: 1.0)
}, completion: nil)
This is what it gives (title of button also shrinks)
Use of CASpringAnimation
let shrinkAnim = CASpringAnimation(keyPath: "bounds.size.width")
shrinkAnim.damping = 0.7
shrinkAnim.initialVelocity = 0.7
shrinkAnim.fromValue = frame.width
shrinkAnim.toValue = width
shrinkAnim.dura[![enter image description here][3]][3]tion = duration
shrinkAnim.timingFunction = getTimingFunction(curve: curve)
shrinkAnim.fillMode = kCAFillModeForwards
shrinkAnim.isRemovedOnCompletion = false
layer.add(shrinkAnim, forKey: shrinkAnim.keyPath)
So it can change the width but also position of the title
So my question is whats going wrong or what I need to add to replicate first image?
My constraints for button is pinned to left, right and bottom edges and fix height. and more thing is I am making a class for this so I cant change constants because I have to use this in many screens .. so I want one stop solution.
Don't use CGAffineTransform, rather take and NSLayoutConstraint attribute outlet for Button's width and change its constant inside animation block/closure.
UIView.animate(withDuration: duration, delay: delayTime,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.7,
options: [.curveEaseIn],
animations: {
self.buttonWidthConstraint.constant = desired_width_here
}, completion: nil)
Put your button inside a UIView
your view tree would then look like this
Superview > UIView > Button
By doing this you now have a fixed width size your button can follow which is the uiview
It would look like this
And then animate using
//let's say the current left and right constraint are 8
leftConstraint.constant = 50
rightConstraint.constant = 50
UIView.animate ... {
self.view.layoutIfNeeded()
}
By using this you'd only need to set the UIView's frame to your desired frame and have the button follow suit and your animations would just be set proportionate to how you'd code it
//let's say the current left and right constraint are 8
// get view frame
...
// calculate distance
var calculatedDistance = ......
// set distance
let distanceToAnimate = calculatedDistance
leftConstraint.constant = distanceToAnimate
rightConstraint.constant = distanceToAnimate
UIView.animate ... {
self.view.layoutIfNeeded()
}
Have you tried content content hugging and compression resistance. Can you please try doing below at highest priorty.
Apply the transform on the frame of the button. When you scale an UIView in animation it does not take consideration of subviews/layout it will just uniformly scale whatever is being drawn.
self.transform = CGAffineTransform.identity
UIView.animate(withDuration: duration, delay: delayTime,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.7,
options: [.curveEaseIn],
animations: {
self.frame = CGRectMake(<#CGFloat x#>, <#CGFloat y#>, <#CGFloat width#>, <#CGFloat height#>)
}, completion: nil)

Swift : Animate width and height of UIButton

Inside of these two functions, I want to animate the button shrinking(gone), then animate it growing(seen). I was able to animate it growing, but not at first have the button shrink. Any help on how to animate a button shrinking?
func progressBarButtonFadeOut(){
UIView.animateWithDuration(0.2, animations: {
//timeCapDesign is a UIButton
self.timeCapDesign.transform = CGAffineTransformMakeScale(0, 0)
})
}
//Progress Bar Fade In Buttons
func progressBarButtonFadeIn(){
UIView.animateWithDuration(0.2, animations: {
self.timeCapDesign.transform = CGAffineTransformIdentity
})
}
got it. So what i had to do was this:
func progressBarButtonFadeOut(){
UIView.animateWithDuration(0.2, animations: {
//timeCapDesign is a UIButton
self.timeCapDesign.alpha = 0
self.timeCapDesign.transform = CGAffineTransformMakeScale(0.1, 0.1)
})
}
//Progress Bar Fade In Buttons
func progressBarButtonFadeIn(){
UIView.animateWithDuration(0.2, animations: {
self.timeCapDesign.alpha = 1
self.timeCapDesign.transform = CGAffineTransformIdentity
})
}
So ultimately to shrink it i set it to a value of the CGAffineTransformMakeScale really low such as (0.1,0.1) and then animated the alpha to 0 to give the effect that its shrinking to nothing.
The scale of "1" is the current size, and if you want to animate it growing, the number should be bigger than 1.
func progressBarButtonFadeOut(){
UIView.animateWithDuration(0.2, animations: {
//timeCapDesign is a UIButton
self.timeCapDesign.transform = CGAffineTransformMakeScale(1.5, 1.5)
})
}

Resources