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*/
})
}
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)
}
I have 3 UIButtons in a UIView that have the same text colour and the same background colour. On tap all three of them fire their corresponding event. But only one of them "blinks" in response to the touch. What can be happening with the other two? They sometimes (but rarely) have the "blink" behaviour, but the touch up inside event is always fired on tap.
The buttons are added in storyboard:
func btnFlash_Clicked(sender: AnyObject) {
if !flashing{
callButton.alpha = 1.0
UIView.animate(withDuration: 0.5, delay: 0.0, options: [.allowUserInteraction], animations: {() -> Void in
callButton.alpha = 0.5
}, completion: {(finished: Bool) -> Void in
})
flashing = true
} else{
flashing = false
callButton.alpha = 0.5
UIView.animate(withDuration: 0.5, delay: 0.0, options: [.allowUserInteraction], animations: {() -> Void in
callButton.alpha = 1.0
}, completion: {(finished: Bool) -> Void in
})
I would setup the button type to UIButtonTypeCustom to stop blinking.
In Swift, I have a hamburger bar button, so when tapped I want that hamburger Bar button to rotate 90 degrees (so that the lines are vertical) and then when you click it again I would like it to go back to it's original state (horizontal)
NOTE: Can you make sure that this works for a UIBarButtonItem, because some solution to a normal UIButton does not work.
I use a UIButton inside of UIBarButtonItem to achieve this, and a variable with state vertical or not
this is my storyboard setup
Here is the code of simple view controller
import UIKit
class ViewController: UIViewController {
var isVertical : Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func rotateAction(_ sender: Any) {
if(!self.isVertical)
{
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: 90 * .pi / 180)
}, completion: { (finished) in
self.isVertical = true
})
}else{
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform.identity
}, completion: { (finished) in
self.isVertical = false
})
}
}
}
Result
Hope this helps
#IBAction func rotateAction1(_ sender: Any) {
if (!self.isVertical) {
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: 90 * .pi / 180)
}, completion: {
(finished) in
self.isVertical = true
})
revealViewController().revealToggle(true)
} else {
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform.identity
}, completion: {
(finished) in
self.isVertical = false
})
revealViewController().revealToggle(false)
}
}
Swift 4:
func rotateBarButton() {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) // Create new button & set its frame
button.setImage(#imageLiteral(resourceName: "settings"), for: UIControlState()) // Assign an image
let lef = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItem = lef// Set as barButton's customView
// Gets you half way there //
UIView.animate(withDuration: 0.8, delay: 0.1, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI))
}, completion: nil)
// Rotates all the way around //
UIView.animate(withDuration: 0.5, delay: 0.5, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI * 2))
}, completion: nil)
}
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 put a UIView on center of the screen with Autolayout. This UIView is a square sized to be 15% of screen width. Then on my controller I add the cornerRadius :
override func viewDidLayoutSubviews() {
circle.layer.cornerRadius = circle.frame.size.width / 2.0
}
Then when user click on a button, the circular view is scaling down with a first animation.
UIView.animateWithDuration(0.4, delay: 0.1, options: .CurveEaseIn, animations: { () -> Void in
self.circle.alpha = 0.0
self.circle.transform = CGAffineTransformMakeScale(0.01, 0.01)
}) { (finished) -> Void in
scaleUp()
}
private func scaleUp() {
UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveEaseInOut, animations: { () -> Void in
self.circle.alpha = 1.0
self.circle.transform = CGAffineTransformIdentity
}) { (finished) -> Void in
}
}
Sometimes the scale down animation doesn't work properly. Before starting the cornerRadius is removed and my UIView become a square. But sometimes my animation works well and the circle scale down animation is OK.
Moreover the scale up animation seems to work well all the time.
I don't understand why the scale down animation isn't working all the time.
Any idea?
Thanks
When animating with Auto Layout enabled, it is usually a good idea to call layoutIfNeeded on your view before starting the animation and again in the loop.
override func viewDidLayoutSubviews() {
circle.layer.cornerRadius = circle.frame.size.width / 2.0
}
#IBAction func scaleDownUp(sender: AnyObject) {
self.circle.layoutIfNeeded()
UIView.animateWithDuration(0.4, delay: 0.1, options: .CurveEaseIn, animations: { () -> Void in
self.circle.alpha = 0.0
self.circle.transform = CGAffineTransformMakeScale(0.01, 0.01)
self.circle.layoutIfNeeded()
}) { (finished) -> Void in
self.scaleUp()
}
}
private func scaleUp() {
self.circle.layoutIfNeeded()
UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveEaseInOut, animations: {
self.circle.alpha = 1.0
self.circle.transform = CGAffineTransformIdentity
self.circle.layoutIfNeeded()
}) { (finished) -> Void in
}
}
Try using bounds instead of frame in this method:
override func viewDidLayoutSubviews() {
circle.layer.cornerRadius = circle.frame.size.width / 2.0
}
It worked for me =)