How to determine UIViewAnimation hierarchy view. Swift - swift

I have 2 animations that get triggered by pressing 2 different buttons. How can I determine which one I see first when they are literally occupying the same space and are on top of each other. Is there some code I can use to determine the hierarchy of what UIImageView is shown first?
Here is an example of what I am dealing with. I have a "lightning" image and a cloud image.
//Lightning
#IBAction func lightningOne(sender: UIButton) {
self.darkCloud.hidden = false
let lightning = UIImageView()
lightning.image = UIImage(named: "lightning")
lightning.frame = CGRect(x:-41, y:29, width:30, height:105)
self.view.addSubview(lightning)
let options = UIViewAnimationOptions.CurveEaseIn
UIView.animateWithDuration(0.1, delay: 0.5, options: options, animations: {
lightning.frame = CGRect(x: -45, y: 34, width: 30, height: 105)
}, completion: { animationFinished in
self.darkCloud.hidden = false
UIView.animateWithDuration(0.0, delay: 0.0, options: options, animations: {
self.view.addSubview(lightning)
lightning.frame = CGRect(x: 41, y: 34, width: 30, height: 105)
}, completion: { animationFinished in
self.darkCloud.hidden = false
UIView.animateWithDuration(0.7, delay: 0.0, options: options, animations: {
self.view.addSubview(lightning)
lightning.frame = CGRect(x: 41, y: 35, width: 30, height: 105)
}, completion: { animationFinished in
lightning.removeFromSuperview()
self.darkCloud.hidden = true
})
})
})
}
Here is the code I use to show the cloud.
// Clouds
func movingClouds() {
let options = UIViewAnimationOptions.Repeat
let cloud = UIImageView()
cloud.image = UIImage(named: "cloud1")
cloud.frame = CGRect(x: -80, y: 110, width: 78, height: 42)
self.view.addSubview(cloud)
UIView.animateWithDuration(140.0, delay: 0.0, options: options, animations: {
cloud.frame = CGRect(x: 350, y: 110, width: 78, height: 42)
}, completion: nil)
}
How can I make sure the lightning image shows up behind the cloud when I trigger it and they happen to cross each other?

Related

I'm trying to make a card that slides while on swipe in swift

I'm having a hard time with animations and PanGestureRecognizers, I want a view that slides by dragging up or dawn with your finger. It has 4 parts
1 - 2 the height, width and bottom constraints need to be changed
2 - 3 the height is the maximum height and you can slide it in or out
3 - 4 the card is at its maximum height and you can swipe it down
here is an image for a better understanding
thanks!
this is how I would do it.
var theView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
// First create your view.
theView = UIView(frame: CGRect(x: 40, y: self.view.bounds.height - 120, width: self.view.frame.width - 80, height: 100))
// set its background color
theView.backgroundColor = UIColor.black
// Create the round corners
theView.layer.cornerRadius = 20
// And add it to the view
self.view.addSubview(theView)
// Create the UIPanGestureRecognizer and assign the function to the selector
let gS = UIPanGestureRecognizer(target: self, action: #selector(growShink(_:)))
// Enable user interactions on the view
theView.isUserInteractionEnabled = true
// Add the gesture recognizer to the view
theView.addGestureRecognizer(gS)
}
// The control value is used to determine wether the user swiped up or down
var controlValue:CGFloat = 0
var animating = false
// The function called when the user swipes
#objc func growShink(_ sender:UIPanGestureRecognizer){
let translation = sender.location(in: theView)
// Check the control value to see if it has been set
if controlValue != 0 && !animating{
// if it has been set check that the control value is greater than the new value recieved by the pan gesture
if translation.x < controlValue{
animating = true
// If it is, change the values of the frame using animate
UIView.animate(withDuration: 0.5, animations: {
self.theView.frame = CGRect(x: 0, y: self.view.bounds.height - 300, width: self.view.frame.width, height: 300)
}, completion: {finished in
UIView.animate(withDuration: 1.0, animations: {
self.theView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}, completion: {finished in self.animating = false; self.controlValue = 0})})
}else if translation.x > controlValue{
animating = true
// else, change the values of the frame back.
UIView.animate(withDuration: 0.5, animations: {
self.theView.frame = CGRect(x: 0, y: self.view.bounds.height - 300, width: self.view.frame.width, height: 300)
}, completion: {finished in
UIView.animate(withDuration: 1.0, animations: {
self.theView.frame = CGRect(x: 40, y: self.view.bounds.height - 120, width: self.view.frame.width - 80, height: 100)
}, completion: {finished in self.animating = false; self.controlValue = 0})})
}
}
// set the control value to the value received from the pan gesture
controlValue = translation.x
}
}
You can adjust the width and height values however you want.

Looping animations with duration, Swift 4

I have an image that I want to move 10 separate times in a row. Each time I want it to do a check, as notated by the print statement of checkForStuff. I noticed that the loop starts and it times out while the first of the 10 moves occurs. Any thoughts on how to chain animations, or do I need to manually write each chain in the sequential closure?
#objc func moveBox(sender: UIButton!) {
print("Started")
let imageToMove = UIImageView()
imageToMove.frame = CGRect(x: 50, y: 50, width: 50, height: 50)
imageToMove.backgroundColor = .red
self.view.addSubview(imageToMove)
var counter = 0
var altitude = 100
while counter <= 10 {
print("looping")
UIView.animate(withDuration: 0.5, animations: {
imageToMove.frame = CGRect(x: 50, y: altitude, width: 50, height: 50)
}, completion: { finished in
counter += 1
altitude += 50
print("Check For Stuff")
})
}
}
In short, in should move 50 pixels down, execute the closure, move 50 pixels down again. and again, and again.
Try Recursion as suggested by #matt
func animate(view: UIView, altitude: Int, numberOfTime: Int ) {
if numberOfTime == 0 { return }
UIView.animate(withDuration: 0.5, animations: {
view.frame = CGRect(x: 50, y: altitude, width: 50, height: 50)
}, completion: { finished in
self.animate(view: view, altitude: altitude + 50, numberOfTime: numberOfTime - 1)
})
}
Use this as
#objc func moveBox(sender: UIButton!) {
print("Started")
let imageToMove = UIImageView()
imageToMove.frame = CGRect(x: 50, y: 50, width: 50, height: 50)
imageToMove.backgroundColor = .red
self.view.addSubview(imageToMove)
animate(view: imageToMove, altitude: 100, numberOfTime: 10)
}

Swift - How to make animated arrow point in right direction?

I have two buttons which when connected, show a line with an animated arrow to show that they are connected.The issue is the arrow it self is not rotating appropriately to point in the right direction when animated.
How can I rotate the arrow to point in the right direction when moving?
class ViewController: UIViewController {
let line = CAShapeLayer()
let linePath = UIBezierPath()
var triangleImage = UIImage(named: "triangle" )
let startCoordinate = CGRect(x: 100, y: 100, width: 0, height: 0)
let btn1 = UIButton()
let btn2 = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
btn1.createRectangleButton(buttonPositionX: 100, buttonPositionY: 100, buttonWidth: 80, buttonHeight: 40, buttonTitle: "", buttonTag: 0)
btn2.createRectangleButton(buttonPositionX: 300, buttonPositionY: 400, buttonWidth: 80, buttonHeight: 40, buttonTitle: "", buttonTag: 1)
view.addSubview(btn1)
view.addSubview(btn2)
let imageView = UIImageView(image: triangleImage)
imageView.frame = CGRect(x:100, y:100, width: 20, height: 20)
imageView.center = self.btn1.center
view.addSubview(imageView)
linePath.move(to: btn1.center)
linePath.addLine(to: btn2.center)
line.path = linePath.cgPath
line.strokeColor = UIColor.red.cgColor
self.view.layer.addSublayer(line)
view.bringSubviewToFront(imageView)
UIView.animate(withDuration: 3, delay: 0.0, options: [.repeat, .curveLinear], animations: {
imageView.center = self.btn2.center
}, completion: nil)
}
note: the code above will look slightly different to the image
Try this rotation transformation
// rotation
imageView.transform = CGAffineTransform(rotationAngle: atan2(btn2.center.y - btn1.center.y, btn2.center.x - btn1.center.x) + CGFloat.pi / 2)
// used triangle image below

How to make this UIButton's action operate correctly?

Every time I run this swift playground (on Xcode), I get an error on the last line saying:
'PlaygroundView' cannot be constructed because it has no accessible initialisers.
I also have another error on line 4 saying:
class 'PlaygroundView' has no initializers.
import UIKit
import PlaygroundSupport
class PlaygroundView:UIViewController {
var introImage:UIImageView
var introButton:UIButton
override func loadView() {
print("workspace started running.")
//Main Constant and Variable Declarations/General Setup
let mainView = UIView()
//Main View Modifications & styling
mainView.backgroundColor = UIColor.init(colorLiteralRed: 250, green: 250, blue: 250, alpha: 1)
func addItem(item: UIView) {
mainView.addSubview(item)
}
//Sub-Element Constant and Variable Declarations
introImage = UIImageView(frame: CGRect(x: 87.5, y: -300, width: 200, height: 200))
introImage.layer.borderColor = UIColor.black.cgColor
introImage.layer.borderWidth = 4
introImage.alpha = 0
introImage.transform = CGAffineTransform(rotationAngle: -90.0 * 3.14/180.0)
introImage.image = UIImage(named: "profile_pic.png")
introImage.image?.accessibilityFrame = introImage.frame
introImage.layer.cornerRadius = 100
addItem(item: introImage)
introButton = UIButton(frame: CGRect(x: 87.5, y: 900, width: 200, height: 30))
introButton.alpha = 0
introButton.setTitle("Tap to meet me", for: .normal)
introButton.titleLabel?.font = UIFont(name: "Avenir Book", size: 20)
introButton.backgroundColor = UIColor.black
introButton.layer.cornerRadius = 15
introButton.layer.borderWidth = 5
addItem(item: introButton)
introButton.addTarget(self, action: #selector(self.introButtonAction), for: .touchDown)
UIView.animate(withDuration: 1.5, delay: 1, options: .curveEaseInOut, animations: {
self.introImage.frame = CGRect(x: 87.5, y: 175, width: 200, height: 200)
self.introButton.frame = CGRect(x: 87.5, y: 400, width: 200, height: 30)
self.introImage.transform = CGAffineTransform(rotationAngle: 0.0 * 3.14/180.0)
self.introImage.alpha = 1
self.introButton.alpha = 1
}) { (mainAnimationComped) in
if mainAnimationComped == true {
print("introduction animation comped.")
}
}
}
//User Interface Actions
func introButtonAction() {
print("user interacted with user interface")
}
}
PlaygroundPage.current.liveView = PlaygroundView()
How would I fix this problem?
That's because in Swift, you need to initialize variables before use them in the code. On the other hand, since in this case you set them explicitly in your function, you might declare them as implicitly unwrapped optionals
var introImage:UIImageView!
var introButton:UIButton!
and this should work without changing anything else in your code
Add ? after introImage and introButton
var introImage:UIImageView?
var introButton:UIButton?

How i move an image from left to right in swift?

I did that...
ivImageLoadingInside.center = CGPoint(x: 25, y: 0)
UIView.animate(withDuration: 2, delay: 0, options: .repeat, animations: {
self.ivImageLoadingInside.center = CGPoint(x: 80, y: 0)
}, completion: nil)
But always stops in the middle.
Here is the image with the animation
private func animation(viewAnimation: UIView) {
UIView.animate(withDuration: 2, animations: {
viewAnimation.frame.origin.x = +viewAnimation.frame.width
}) { (_) in
UIView.animate(withDuration: 2, delay: 1, options: [.curveEaseIn], animations: {
viewAnimation.frame.origin.x -= viewAnimation.frame.width
})
}
}
self.ivImageLoadingInside.center = CGPoint(x: 80 - self.ivImageLoadingInside.bounds.width / 2, y: 0)
I got it! You have to put the constraints and do this...
if animate {
ivImageLoadingInside.frame = CGRect(x: 0 - 160, y: 123, width: 160, height: 12)
UIView.animate(withDuration: 1.2, delay: 0, options: .repeat, animations: {
self.ivImageLoadingInside.frame = CGRect(x: ScreenSize.SCREEN_WIDTH, y: 123, width: 160, height: 12)
}, completion: nil)
} else {
ivImageLoadingInside.layer.removeAllAnimations()
}*
Look at this link http://mathewsanders.com/prototyping-iOS-iPhone-iPad-animations-in-swift/