I want to create a transition effect on my label so that it comes out from the left side of the view and centre itself in the middle of the screen. I am doing:
override func viewDidLoad() {
super.viewDidLoad()
label.center.x -= view.bounds.width
}
to place the label out of the view, but this is not working as the label is still present in the view. Please help.
Because label.center.x -= view.bounds.width will make it appear at the left of the view, so you can't see any effect on it.
You can use UIView.animateWithDuration to make animation effect:
UIView.animateWithDuration(0.5, delay: 0, options: [.CurveEaseOut], animations: {
label.center.x += view.bounds.width
self.view.layoutIfNeeded()
}, completion: nil)
And you should put them in your viewDidAppear instead of viewDidLoad, so everytime your view is resume, it will animate your label. Your code will look like this:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
label.center.x = view.center.x // Place it in the center x of the view.
label.center.x -= view.bounds.width // Place it on the left of the view with the width = the bounds'width of the view.
// animate it from the left to the right
UIView.animateWithDuration(0.5, delay: 0, options: [.CurveEaseOut], animations: {
label.center.x += view.bounds.width
self.view.layoutIfNeeded()
}, completion: nil)
}
This will make your label appear from the left to the right.
SWIFT 5
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
label.center.x = view.center.x // Place it in the center x of the view.
label.center.x -= view.bounds.width // Place it on the left of the view with the width = the bounds'width of the view.
// animate it from the left to the right
UIView.animate(withDuration: 1, delay: 0, options: [.curveLinear], animations: {
self.label.center.x += self.view.bounds.width
self.view.layoutIfNeeded()
}, completion: nil)
}
Here is a solution for Swift 3
UIView.animate(withDuration: 1.0) {
label = self.view.frame.size.width / 2
}
make sure that the label is initially positioned away from the screen.
Related
I’m trying to change height of a collectionview and a view when I click a button. But when I click the button the height of the view changes but not the height of the collectionview.
Here is my code:
#IBAction func button(_ sender: Any) {
UIView.animate(withDuration: 1, animations: {
self.backView.frame.size.height -= 160
self.collectionView.frame.size.height -= 160
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut,
animations: self.view.layoutIfNeeded, completion: nil)
}, completion: nil)
}
What can I do to also resize the collectionview?
If you used constraints on that collection view, you need to change the constant of the height constraint, and not its frame.
Like this:
#IBAction func button(_ sender: Any) {
UIView.animate(withDuration: 1, animations: {
self.backView.frame.size.height -= 160
self.collectionViewHeightConstraint.constant = <value>
self.view.layoutIfNeeded()
}, completion: nil)
}
how can I implement that when I click on button, my Image moves out of the screen with animation and when I click again on the button , comes back to its place?
On the button click event, simply animate the x coordinate of origin of the imageView according to your requirement.
Example:
#IBAction func onTapButton(_ sender: UIButton)
{
if sender.isSelected
{
UIView.animate(withDuration: 2.0, animations: {
self.imageView.frame.origin.x = 0.0
})
}
else
{
UIView.animate(withDuration: 2.0, animations: {
self.imageView.frame.origin.x = UIScreen.main.bounds.width
})
}
sender.isSelected = !sender.isSelected
}
The above code will work as follows:
when selecting button, imageView's x coordinate of origin is moved to extreme right of the screen (UIScreen.main.bounds.width)
when de-selecting button, imageView's x coordinate of origin is moved to extreme left of the screen (0.0)
Use this code to move left-
func moveToLeft()
{
var frame = imageView.frame
frame.origin.x = -imageView.frame.size.width //Adjust this value according to your need
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseOut, animations: {() -> Void in
self.imageView.frame = frame
}, completion: {(_ finished: Bool) -> Void in
/*done*/
})
}
Use this code to move right-
func moveToRight()
{
var frame = imageView.frame
frame.origin.x = 0 //Adjust this value according to your need
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseOut, animations: {() -> Void in
self.imageView.frame = frame
}, completion: {(_ finished: Bool) -> Void in
/*done*/
})
}
Here is my code:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
cloud.center.x -= view.bounds.width
cloud1.center.x -= view.bounds.width
cloud2.center.x -= view.bounds.width
cloud3.center.x -= view.bounds.width
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 12) {
self.cloud.center.x += self.view.bounds.width*2
UIView.animate(withDuration: 12, delay: 9, options: [],
animations: {
self.cloud1.center.x += self.view.bounds.width*2
},
completion: nil
)
UIView.animate(withDuration: 12, delay: 18, options: [],
animations: {
self.cloud2.center.x += self.view.bounds.width*2
},
completion: nil
)
UIView.animate(withDuration: 12, delay: 22, options: [],
animations: {
self.cloud3.center.x += self.view.bounds.width*2
},
completion: nil
)
}
}
I have got a redo which resets everything in the page apart from my animation which just stays in one position. How can I reset the animation in order for it to re-play the animation again?
Your animation code moves your 4 cloud views to the right by self.view.bounds.width*2, by adding that amount to their center positions.
To undo that change, simply subtract the same amount.
I'm trying to add animation to my tabBarController when hidden. Im able to accomplish this effect with the navigationBarController by using self.navigationController?.isNavigationBarHidden = true. I'm able to hide the tabBar by using self.tabBarController?.tabBar.isHidden = true but i do not get the animation how can I do this thank you in advance.
You could change the tab bar's frame inside an animation, so something like:
func hideTabBar() {
var frame = self.tabBarController?.tabBar.frame
frame?.origin.y = self.view.frame.size.height + (frame?.size.height)!
UIView.animate(withDuration: 0.5, animations: {
self.tabBarController?.tabBar.frame = frame!
})
}
func showTabBar() {
var frame = self.tabBarController?.tabBar.frame
frame?.origin.y = self.view.frame.size.height - (frame?.size.height)!
UIView.animate(withDuration: 0.5, animations: {
self.tabBarController?.tabBar.frame = frame!
})
}
Which sets the tab bar just below the visible screen, so that it slides up/down from the bottom.
I've developed a util extension for UIViewController
Swift 4 compatible:
extension UIViewController {
func setTabBarHidden(_ hidden: Bool, animated: Bool = true, duration: TimeInterval = 0.3) {
if animated {
if let frame = self.tabBarController?.tabBar.frame {
let factor: CGFloat = hidden ? 1 : -1
let y = frame.origin.y + (frame.size.height * factor)
UIView.animate(withDuration: duration, animations: {
self.tabBarController?.tabBar.frame = CGRect(x: frame.origin.x, y: y, width: frame.width, height: frame.height)
})
return
}
}
self.tabBarController?.tabBar.isHidden = hidden
}
}
Improvement of the response of #Luca Davanzo. If the bar is already hidden, it will continue hiding it and moving it lower. Also get rid of the return, so the state of the tabbar.hidden changes when the animation happens.
So I added a check:
extension UIViewController {
func setTabBarHidden(_ hidden: Bool, animated: Bool = true, duration: TimeInterval = 0.5) {
if self.tabBarController?.tabBar.isHidden != hidden{
if animated {
//Show the tabbar before the animation in case it has to appear
if (self.tabBarController?.tabBar.isHidden)!{
self.tabBarController?.tabBar.isHidden = hidden
}
if let frame = self.tabBarController?.tabBar.frame {
let factor: CGFloat = hidden ? 1 : -1
let y = frame.origin.y + (frame.size.height * factor)
UIView.animate(withDuration: duration, animations: {
self.tabBarController?.tabBar.frame = CGRect(x: frame.origin.x, y: y, width: frame.width, height: frame.height)
}) { (bool) in
//hide the tabbar after the animation in case ti has to be hidden
if (!(self.tabBarController?.tabBar.isHidden)!){
self.tabBarController?.tabBar.isHidden = hidden
}
}
}
}
}
}
}
In case if you need to toggle it from hide to visible and vice versa:
func toggleTabbar() {
guard var frame = tabBarController?.tabBar.frame else { return }
let hidden = frame.origin.y == view.frame.size.height
frame.origin.y = hidden ? view.frame.size.height - frame.size.height : view.frame.size.height
UIView.animate(withDuration: 0.3) {
self.tabBarController?.tabBar.frame = frame
}
}
Swift 4 solution:
tabBarController?.tabBar.isHidden = true
UIView.transition(with: tabBarController!.view, duration: 0.35, options: .transitionCrossDissolve, animations: nil)
Here is a simple extension :
func setTabBar(hidden:Bool) {
guard let frame = self.tabBarController?.tabBar.frame else {return }
if hidden {
UIView.animate(withDuration: 0.3, animations: {
self.tabBarController?.tabBar.frame = CGRect(x: frame.origin.x, y: frame.origin.y + frame.height, width: frame.width, height: frame.height)
})
}else {
UIView.animate(withDuration: 0.3, animations: {
self.tabBarController?.tabBar.frame = UITabBarController().tabBar.frame
})
}
}
So I've been playing around for 3 days with this now, finding out that the one that worked for me in my code was Adriana's post from 14th Sept 2018. But I was not sure how to use the coding once copied into my Project. So, after much experimenting I found that the way I could use this func was to put the following into into the respective swipe actions.
setTabBarHidden(false)
setTabBarHidden(true)
My next step is to try to get the swipe actions working while using UIScrollView in the same UIView at the same time.
You have to add UIView transitionWithView class func
Swift 2
func hideTabBarWithAnimation() -> () {
UIView.transitionWithView(tableView, duration: 1.0, options: .TransitionCrossDissolve, animations: { () -> Void in
self.tabBarController?.tabBar.hidden = true
}, completion: nil)
}
Swift 3, 4, 5
func hideTabBarWithAnimation() -> () {
UIView.transition(with: tableView, duration: 1.0, options: .transitionCrossDissolve, animations: { () -> Void in
self.tabBarController?.tabBar.isHidden = true
}, completion: nil)
}
I have got this problem with breaking animations block in my app. I am animating an image inside UIScrollView (zooming-in, moving from left to right, zooming-out). Animation is being launched on tap with UITapGestureRecognizer.
The problem is that even though I can zoom-out the image when it is being animated, animations block continues and as a result I get the image off the iPhone screen.
I have tried to use removeAllAnimations() method on both scrollView.layer and view.layer but it seems not to work.
Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
setupGestureRecognizer()
}
func setupGestureRecognizer() {
let singleTap = UITapGestureRecognizer(target: self, action: #selector(self.handleSingleTap(recognizer:)))
singleTap.numberOfTapsRequired = 1
scrollView.addGestureRecognizer(singleTap)
}
func handleSingleTap(recognizer: UITapGestureRecognizer) {
animateRecipeImage()
}
// MARK: - Recipe Image Animation
func animateRecipeImage() {
let offset = CGPoint(x: 0, y: 0)
var middleOffset = CGPoint()
let endOffset = CGPoint(x: (imageView.bounds.width / 2), y: 0)
// To avoid animation in landscape mode we check for current device orientation
if (UIDeviceOrientationIsPortrait(UIDevice.current.orientation)) {
if (scrollView.zoomScale > scrollView.minimumZoomScale) {
scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
// Remove all animations and update image contraints to fit the screen
self.scrollView.layer.removeAllAnimations()
self.view.layer.removeAllAnimations()
updateConstraintsForSize(size: view.bounds.size)
} else {
scrollView.setZoomScale(scrollView.maximumZoomScale, animated: true)
let screenWidth = screenSize.width
// Handle big screen sizes
if (screenWidth < self.imageView.bounds.width) {
middleOffset = CGPoint(x: ((self.imageView.bounds.width - screenWidth) * self.scrollView.zoomScale), y: 0)
} else {
middleOffset = CGPoint(x: (self.imageView.frame.width - screenWidth), y: 0)
}
// Start animating the image
UIView.animate(withDuration: 2, delay: 0.5, options: [.allowUserInteraction], animations: {
self.scrollView.setContentOffset(offset, animated: false)
}, completion: { _ in
UIView.animate(withDuration: 4, delay: 0.5, options: [.allowUserInteraction], animations: {
self.scrollView.setContentOffset(middleOffset, animated: false)
}, completion: { _ in
UIView.animate(withDuration: 1.0, delay: 0.2, usingSpringWithDamping: 0.4, initialSpringVelocity: 1.1, options: [.allowUserInteraction], animations: {
self.scrollView.setContentOffset(endOffset, animated: false)
}, completion: nil)
})
})
}
}
}
Any ideas how to break that animations block? The result I would like to achieve is break animation and zoom-out image.