A view that animates upward without filling the screen - ios

So this is what I am trying to do:
Here is the initial screen:
When the bottom pointing arrow is clicked there is a smaller view that transitions from bottom to top like this:
And as you can see the view in the back is dimmed. And when I click on the back view, the smaller sized view goes away by animating downwards.
There were several things that I tried:
1. I tried to segue modally which seemed to animate properly, namely, from bottom to top, but it covers the entire back view.
2. I tried to make the modal view only half the parent size by trying to replicate this post: Present modal view controller in half size parent controller. However, it did not work.
3. So I decided to put a UIView on top of my back view like so:
And I connected the grey colored view with the #IBOutlet weak var messageView: UIView!. And I tried using this code: UIView.transitionWithView(messageView, duration: 1.0, options: UIViewAnimationOptions.CurveEaseIn, animations: nil, completion: nil). However, nothing seems to be happening. Any suggestions on how to accomplish this?

For the Animation of button:
Add autolayout constraint to the BottomLayout Guide.And create an IBOutlet as
#IBOutlet weak var bottomConstraint: NSLayoutConstraint!
var shouldAnimateView:Bool = true
On the Action of the button you need to animate the View using constraint
#IBAction func showOrHideViewBtn(sender: AnyObject) {
if shouldAnimateView {
self.bottomConstraint.constant = self.view.frame.size.height/2+5
UIView.animateWithDuration(Double(0.2), animations: {
self.bottomConstraint.constant = self.view.frame.size.height/2 - self.toanimateView.frame.size.height
self.view.layoutIfNeeded()
})
}else{
self.bottomConstraint.constant = self.view.frame.size.height/2 - self.toanimateView.frame.size.height
UIView.animateWithDuration(Double(0.2), animations: {
self.bottomConstraint.constant = self.view.frame.size.height/2+5
self.view.layoutIfNeeded()
})
}
shouldAnimateView = !shouldAnimateView
}

Related

UIStackView show/hide animation is not working properly

I'm using UIStackView and it contains 3 UIView instances, which has fixed height
I'm trying to hide these subviews by clicking button
first and second view show/hide well with proper animation
but last view doesn't animate
class ViewController: UIViewController {
private var flag: Bool = true
#IBOutlet weak var targetView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonDidTapped(_ sender: Any) {
flag = !flag
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
self.targetView.isHidden = !self.flag
}
}
}
The issue is the way stack views change their frames when hiding an arranged subview.
Easiest way to see what's happening:
set your Green view to Alpha: 0.5
toggle .isHidden on the Blue view
You'll see that the 50% translucent Green view "slides up over" the Blue view... the Blue view does not "shrink in height" during the animation.
To solve your specific issue, set Clips To Bounds to true on your stack view. Now, when you toggle .isHidden on your Green view, the animation will look correct.
That will not change the "slide over" appearance if you have translucent views, but that's a different issue.
As a side note, you can simplify your code and get rid of the flag like this:
UIView.animate(withDuration: 0.5) {
// not needed
//self.view.layoutIfNeeded()
self.targetView.isHidden.toggle()
}
Try change your code from:
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
self.targetView.isHidden = !self.flag
}
to:
self.targetView.isHidden = !self.flag
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
Looks like you animate before change.

UIView.transition animation causing view to become nil

Goal of code is that on each tap of a view containing 2 UIImageview, to have the bottom image go on top of the to image, and so on each time I tap.
I have a view container with 2 UIImageview on top of each other:
#IBOutlet weak var imagesContainer: UIView!
#IBOutlet weak var imageZero: UIImageView!
#IBOutlet weak var imageOne: UIImageView!
I add a tap gesture in ViewDidLoad:
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapImagesContainer(_:)))
self.imagesContainer.addGestureRecognizer(tapGestureRecognizer
Also a top level variable, to control which image to bring on top, and which to push down:
var imageOnTopIsImageZero = true
so that when I tap on the container, the under image comes on top.
While developing I implemented a transition without animation:
#objc func didTapImagesContainer(_ sender: UITapGestureRecognizer) {
let imageToBringOnTop: UIImageView? = imageOnTopIsImageZero ? self.imageOne : self.imageZero
let ImagetoBringDown: UIImageView? = imageOnTopIsImageZero ? self.imageZero : self.imageOne
imageToBringOnTop?.layer.zPosition = 1.0
ImagetoBringDown?.layer.zPosition = 0.0
self.imageOnTopIsImageZero.toggle()
}
This works fine. Now I tried to implement the same transition with animation:
#objc func didTapImagesContainer(_ sender: UITapGestureRecognizer) {
let imageToBringOnTop: UIImageView? = imageOnTopIsImageZero ? self.imageOne : self.imageZero
let ImagetoBringDown: UIImageView? = imageOnTopIsImageZero ? self.imageZero : self.imageOne
UIView.transition(from: ImagetoBringDown!, to: imageToBringOnTop!, duration: 1.0, options: .transitionCrossDissolve, completion: nil)
self.imageOnTopIsImageZero.toggle()
}
The first time I tap on the image, the transition happens correctly, underimage is cross disolved into the on top image.
But on the second tap, imageToBringOnTop is nil!
I really don't understand why the animation has an effect on the view content. What is the cause, and how to resolve this issue?
The docs say:
fromView
The starting view for the transition. By default, this view is removed from its superview as part of the transition.
Detail:
The idea of a transition animation is that you're changing the view hierarchy by replacing one view with another in an animated way. If you are not doing such a 'transition', you can use other (non-transition) animation API like animateWithDuration:delay:options:animations:completion:
Or there is support for keeping two views in the hierarchy, one shown, one hidden, using the transition animation API, if you include UIViewAnimationOptionShowHideTransitionViews in the option set:
UIView.transition(from: ImagetoBringDown!, to: imageToBringOnTop!,
duration: 1.0,
options: [.transitionCrossDissolve, .showHideTransitionViews],
completion: nil)
So "showHideTransitionViews" means 'show/hide the from/to instead of add/remove'
Rather than setting the z positions, transition actually removes the from view from the view hierarchy, and adds the to view to the view hierarchy (documentation):
Parameters
fromView
The starting view for the transition. By default, this view is
removed from its superview as part of the transition.
toView The ending view for the transition. By default, this view is
added to the superview of fromView as part of the transition.
Also note that since your VC is holding a weak reference to the images, their superviews are the only objects holding a strong reference to them. Once one of them is removed from its superview, your VC's weak reference becomes nil.
To fix this, simply use strong references, remove the word weak:
#IBOutlet var imageZero: UIImageView!
#IBOutlet var imageOne: UIImageView!

Weird animation behavior using Swift 4 and UIView

I really can't figure out what's wrong with my code. Let me explain in detail what was my aim:
I have two UIView in the same UIViewController. They're called "redSquare" and "greenSquare".
When the UIViewController is presented I want to animate the redSquare in order to move on the Y-axis till it reaches the top-border of the greenSquare.
This is how I set the xCode project:
The behavior that I got is completely the opposite and I really can't understand why and what's happening:
Any tips or explanations for this?
Okay. Part of the problem is that you're aligning the center Y... which means that you're trying to break constraints with your animation.
Another part of the problem is that you are doing your animation in viewDidLoad, which totally runs before viewWillAppear and viewDidAppear get called.
For my own animations, I usually animate a constraint.
That is, get rid of the center-Y constraint for your red box and add a new constraint putting the red box some Y distance from the bottom of the superview. Connect this new constraint to an outlet and then you can animate like this:
#IBOutlet weak var redYConstraint : NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// This line sets the red box to be in the center Y of the green box
self.redYConstraint.constant = self.greenSquare.frame.midY
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 3.0, delay: 2.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.redYConstraint.constant = self.greenSquare.frame.maxY
self.view.layoutIfNeeded()
}, completion: nil)
}

Can't animate a position change of two container UIViews that have child view controllers

I have two views in self.view that are container views (via storyboard: each has an embed segue in viewDidLoad which loads up their respective child view controller). They're called self.leftPane and self.rightPane. I'm using auto-layout.
I want to animate a position change of self.leftPane, as it moves from x=0 to x=(negative something). I'm basically trying to make a hamburger menu on the left, in a simple fashion...
#IBOutlet weak var leftPane: UIView! // has child view controller embedded
#IBOutlet weak var rightPane: UIView! // has child view controller embedded
// in/after viewDidAppear
self.leftPaneLeftConstraint.constant = 0 - self.leftPane.frame.size.width + 20.0
UIView.transition(with: self.leftPane, duration: 1.0, options: [], animations: {
self.leftPane.layoutIfNeeded()
}, completion: { (finished) in
self.leftPaneIsFull = false
})
The problem is that there's no animation -- it just jumps. I've tried UIView.transition with different views, and different UIView.animate flavors, all with the same effect (no actual animation).
What am I missing? Thanks!
You should use UIView.animate instead of UIView.transition.I wrote down the code sample.Are you try this code?
#IBOutlet weak var leftPane: UIView! // has child view controller
embedded
#IBOutlet weak var rightPane: UIView! // has child view controller embedded
// in/after viewDidAppear
UIView.animate(withDuration: 1.0, animations: {
self.leftPaneLeftConstraint.constant = 0 - self.leftPane.frame.size.width + 20.0
self.view.layoutIfNeeded()
}, completion: { (success) -> Void in
//You can write something you want
})
}
})
Enjoy it :)

UIView reloaded after clicking a textfield?

I'm trying to make a very simple login page. Everything is fine, until I started doing some animations.
When I click login button, I move the logo 100px to the top, then I show the inputs.
That worked correctly, but when I click the textfield to edit it, the image (logo) returns to its original position!
My code:
#IBAction func LoginClick(sender: AnyObject) {
UIView.animateWithDuration(2, animations: {
var center = self.logoImage.center
center.y -= 100
self.logoImage.center = center
self.usernameInput.hidden=false
self.passwordInput.hidden=false
self.usernameLine.hidden=false
self.passwordLine.hidden=false
self.slidesImg.hidden=true
})
}
Auto Layout is running and placing your logo back to where the constraints say it should be. Instead of modifying the frame by changing the center, you should create an IBOutlet to the vertical space constraint and then update the constant property to move your logo up.
To create the IBOutlet, first click on the vertical bar that represents the vertical constraint in the Storyboard. Then control-click on the constraint and drag to your viewController code. Give it a name like topSpace.
You'll need to call layoutIfNeeded() to animate the constraint change:
#IBOutlet weak var topSpace: NSLayoutConstraint!
#IBAction func LoginClick(sender: AnyObject) {
topSpace.constant -= 100
UIView.animateWithDuration(2, animations: {
self.logoImage.layoutIfNeeded()
self.usernameInput.hidden=false
self.passwordInput.hidden=false
self.usernameLine.hidden=false
self.passwordLine.hidden=false
self.slidesImg.hidden=true
})
}

Resources